summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:06:29 +0000
commit94994d372d014ce4c8758b9605d63fae651bd8aa (patch)
tree51c0b708bd59f205d6b35cb2a8c24d62f0c33d77
parent39be7ce23363d12ae3e49aeb1fdb2bfeb892e836 (diff)
downloadsrc-test2-94994d372d014ce4c8758b9605d63fae651bd8aa.tar.gz
src-test2-94994d372d014ce4c8758b9605d63fae651bd8aa.zip
Vendor import of lldb trunk r351319 (just before the release_80 branchvendor/lldb/lldb-trunk-r351319
Notes
Notes: svn path=/vendor/lldb/dist/; revision=343181 svn path=/vendor/lldb/lldb-trunk-r351319/; revision=343182; tag=vendor/lldb/lldb-trunk-r351319
-rw-r--r--CMakeLists.txt122
-rw-r--r--cmake/modules/AddLLDB.cmake115
-rw-r--r--cmake/modules/LLDBConfig.cmake127
-rw-r--r--cmake/modules/LLDBFramework.cmake115
-rw-r--r--cmake/modules/LLDBStandalone.cmake7
-rw-r--r--cmake/modules/debugserverConfig.cmake3
-rw-r--r--docs/building-with-debug-llvm.txt1
-rw-r--r--docs/lldb-platform-packets.txt404
-rw-r--r--examples/darwin/heap_find/heap.py2
-rw-r--r--examples/interposing/darwin/fd_interposing/FDInterposing.cpp2
-rwxr-xr-xexamples/python/bsd.py105
-rwxr-xr-xexamples/python/crashlog.py83
-rwxr-xr-xexamples/python/gdbremote.py190
-rw-r--r--examples/synthetic/bitfield/program.cpp2
-rw-r--r--include/lldb/API/LLDB.h4
-rw-r--r--include/lldb/API/SBAddress.h1
-rw-r--r--include/lldb/API/SBBreakpoint.h10
-rw-r--r--include/lldb/API/SBCommandInterpreter.h22
-rw-r--r--include/lldb/API/SBCommandReturnObject.h4
-rw-r--r--include/lldb/API/SBDebugger.h6
-rw-r--r--include/lldb/API/SBDefines.h5
-rw-r--r--include/lldb/API/SBExpressionOptions.h6
-rw-r--r--include/lldb/API/SBFileSpec.h3
-rw-r--r--include/lldb/API/SBFrame.h4
-rw-r--r--include/lldb/API/SBInitializerOptions.h43
-rw-r--r--include/lldb/API/SBMemoryRegionInfo.h1
-rw-r--r--include/lldb/API/SBMemoryRegionInfoList.h6
-rw-r--r--include/lldb/API/SBModule.h1
-rw-r--r--include/lldb/API/SBProcess.h6
-rw-r--r--include/lldb/API/SBStructuredData.h10
-rw-r--r--include/lldb/API/SBSymbolContext.h4
-rw-r--r--include/lldb/API/SBTarget.h70
-rw-r--r--include/lldb/API/SBThread.h4
-rw-r--r--include/lldb/API/SBThreadPlan.h14
-rw-r--r--include/lldb/API/SBVariablesOptions.h4
-rw-r--r--include/lldb/Breakpoint/Breakpoint.h14
-rw-r--r--include/lldb/Breakpoint/BreakpointID.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointIDList.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointList.h37
-rw-r--r--include/lldb/Breakpoint/BreakpointLocation.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointLocationCollection.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointLocationList.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointName.h6
-rw-r--r--include/lldb/Breakpoint/BreakpointOptions.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointResolver.h20
-rw-r--r--include/lldb/Breakpoint/BreakpointResolverAddress.h6
-rw-r--r--include/lldb/Breakpoint/BreakpointResolverFileLine.h21
-rw-r--r--include/lldb/Breakpoint/BreakpointResolverFileRegex.h6
-rw-r--r--include/lldb/Breakpoint/BreakpointResolverName.h20
-rw-r--r--include/lldb/Breakpoint/BreakpointResolverScripted.h81
-rw-r--r--include/lldb/Breakpoint/BreakpointSite.h4
-rw-r--r--include/lldb/Breakpoint/BreakpointSiteList.h4
-rw-r--r--include/lldb/Breakpoint/Stoppoint.h4
-rw-r--r--include/lldb/Breakpoint/StoppointLocation.h4
-rw-r--r--include/lldb/Breakpoint/Watchpoint.h4
-rw-r--r--include/lldb/Breakpoint/WatchpointList.h4
-rw-r--r--include/lldb/Breakpoint/WatchpointOptions.h4
-rw-r--r--include/lldb/Core/Address.h18
-rw-r--r--include/lldb/Core/AddressRange.h6
-rw-r--r--include/lldb/Core/AddressResolver.h4
-rw-r--r--include/lldb/Core/AddressResolverFileLine.h10
-rw-r--r--include/lldb/Core/AddressResolverName.h8
-rw-r--r--include/lldb/Core/Architecture.h45
-rw-r--r--include/lldb/Core/ClangForward.h4
-rw-r--r--include/lldb/Core/Communication.h16
-rw-r--r--include/lldb/Core/Debugger.h51
-rw-r--r--include/lldb/Core/Disassembler.h26
-rw-r--r--include/lldb/Core/DumpDataExtractor.h6
-rw-r--r--include/lldb/Core/EmulateInstruction.h18
-rw-r--r--include/lldb/Core/FileLineResolver.h10
-rw-r--r--include/lldb/Core/FileSpecList.h2
-rw-r--r--include/lldb/Core/FormatEntity.h14
-rw-r--r--include/lldb/Core/Highlighter.h165
-rw-r--r--include/lldb/Core/IOHandler.h19
-rw-r--r--include/lldb/Core/LoadedModuleInfoList.h3
-rw-r--r--include/lldb/Core/Mangled.h46
-rw-r--r--include/lldb/Core/MappedHash.h4
-rw-r--r--include/lldb/Core/Module.h113
-rw-r--r--include/lldb/Core/ModuleList.h42
-rw-r--r--include/lldb/Core/ModuleSpec.h19
-rw-r--r--include/lldb/Core/Opcode.h6
-rw-r--r--include/lldb/Core/PluginInterface.h4
-rw-r--r--include/lldb/Core/PluginManager.h16
-rw-r--r--include/lldb/Core/RangeMap.h290
-rw-r--r--include/lldb/Core/RichManglingContext.h108
-rw-r--r--include/lldb/Core/STLUtils.h4
-rw-r--r--include/lldb/Core/SearchFilter.h29
-rw-r--r--include/lldb/Core/Section.h16
-rw-r--r--include/lldb/Core/SourceManager.h12
-rw-r--r--include/lldb/Core/StreamAsynchronousIO.h5
-rw-r--r--include/lldb/Core/StreamBuffer.h12
-rw-r--r--include/lldb/Core/StreamFile.h10
-rw-r--r--include/lldb/Core/StructuredDataImpl.h2
-rw-r--r--include/lldb/Core/ThreadSafeDenseMap.h4
-rw-r--r--include/lldb/Core/ThreadSafeDenseSet.h4
-rw-r--r--include/lldb/Core/ThreadSafeSTLMap.h4
-rw-r--r--include/lldb/Core/ThreadSafeSTLVector.h4
-rw-r--r--include/lldb/Core/ThreadSafeValue.h4
-rw-r--r--include/lldb/Core/UniqueCStringMap.h6
-rw-r--r--include/lldb/Core/UserSettingsController.h12
-rw-r--r--include/lldb/Core/Value.h14
-rw-r--r--include/lldb/Core/ValueObject.h27
-rw-r--r--include/lldb/Core/ValueObjectCast.h12
-rw-r--r--include/lldb/Core/ValueObjectChild.h16
-rw-r--r--include/lldb/Core/ValueObjectConstResult.h24
-rw-r--r--include/lldb/Core/ValueObjectConstResultCast.h16
-rw-r--r--include/lldb/Core/ValueObjectConstResultChild.h19
-rw-r--r--include/lldb/Core/ValueObjectConstResultImpl.h16
-rw-r--r--include/lldb/Core/ValueObjectDynamicValue.h24
-rw-r--r--include/lldb/Core/ValueObjectList.h6
-rw-r--r--include/lldb/Core/ValueObjectMemory.h18
-rw-r--r--include/lldb/Core/ValueObjectRegister.h20
-rw-r--r--include/lldb/Core/ValueObjectSyntheticFilter.h18
-rw-r--r--include/lldb/Core/ValueObjectVariable.h18
-rw-r--r--include/lldb/DataFormatters/DataVisualization.h4
-rw-r--r--include/lldb/DataFormatters/DumpValueObjectOptions.h4
-rw-r--r--include/lldb/DataFormatters/FormatCache.h4
-rw-r--r--include/lldb/DataFormatters/FormatClasses.h4
-rw-r--r--include/lldb/DataFormatters/FormatManager.h4
-rw-r--r--include/lldb/DataFormatters/FormattersContainer.h4
-rw-r--r--include/lldb/DataFormatters/FormattersHelpers.h4
-rw-r--r--include/lldb/DataFormatters/LanguageCategory.h4
-rw-r--r--include/lldb/DataFormatters/StringPrinter.h4
-rw-r--r--include/lldb/DataFormatters/TypeCategory.h6
-rw-r--r--include/lldb/DataFormatters/TypeCategoryMap.h4
-rw-r--r--include/lldb/DataFormatters/TypeFormat.h4
-rw-r--r--include/lldb/DataFormatters/TypeSummary.h4
-rw-r--r--include/lldb/DataFormatters/TypeSynthetic.h4
-rw-r--r--include/lldb/DataFormatters/TypeValidator.h4
-rw-r--r--include/lldb/DataFormatters/ValueObjectPrinter.h8
-rw-r--r--include/lldb/Expression/DWARFExpression.h9
-rw-r--r--include/lldb/Expression/Expression.h4
-rw-r--r--include/lldb/Expression/ExpressionParser.h36
-rw-r--r--include/lldb/Expression/ExpressionVariable.h4
-rw-r--r--include/lldb/Expression/FunctionCaller.h4
-rw-r--r--include/lldb/Expression/IRExecutionUnit.h6
-rw-r--r--include/lldb/Expression/IRMemoryMap.h28
-rw-r--r--include/lldb/Expression/LLVMUserExpression.h4
-rw-r--r--include/lldb/Expression/Materializer.h4
-rw-r--r--include/lldb/Expression/REPL.h6
-rw-r--r--include/lldb/Expression/UserExpression.h32
-rw-r--r--include/lldb/Expression/UtilityFunction.h4
-rw-r--r--include/lldb/Host/Debug.h4
-rw-r--r--include/lldb/Host/Editline.h5
-rw-r--r--include/lldb/Host/File.h75
-rw-r--r--include/lldb/Host/FileSystem.h151
-rw-r--r--include/lldb/Host/HostInfoBase.h4
-rw-r--r--include/lldb/Host/HostNativeThreadBase.h1
-rw-r--r--include/lldb/Host/MonitoringProcessLauncher.h4
-rw-r--r--include/lldb/Host/PipeBase.h3
-rw-r--r--include/lldb/Host/ProcessRunLock.h4
-rw-r--r--include/lldb/Host/SafeMachO.h (renamed from include/lldb/Utility/SafeMachO.h)0
-rw-r--r--include/lldb/Host/Socket.h2
-rw-r--r--include/lldb/Host/SocketAddress.h4
-rw-r--r--include/lldb/Host/StringConvert.h4
-rw-r--r--include/lldb/Host/Symbols.h4
-rw-r--r--include/lldb/Host/TaskPool.h8
-rw-r--r--include/lldb/Host/XML.h4
-rw-r--r--include/lldb/Host/common/NativeBreakpoint.h56
-rw-r--r--include/lldb/Host/common/NativeBreakpointList.h35
-rw-r--r--include/lldb/Host/common/NativeProcessProtocol.h41
-rw-r--r--include/lldb/Host/common/NativeRegisterContext.h4
-rw-r--r--include/lldb/Host/common/SoftwareBreakpoint.h53
-rw-r--r--include/lldb/Host/posix/ConnectionFileDescriptorPosix.h5
-rw-r--r--include/lldb/Host/posix/HostProcessPosix.h4
-rw-r--r--include/lldb/Host/posix/PipePosix.h9
-rw-r--r--include/lldb/Host/windows/HostThreadWindows.h1
-rw-r--r--include/lldb/Host/windows/PipeWindows.h11
-rw-r--r--include/lldb/Host/windows/editlinewin.h2
-rw-r--r--include/lldb/Host/windows/windows.h1
-rw-r--r--include/lldb/Initialization/SystemInitializer.h13
-rw-r--r--include/lldb/Initialization/SystemInitializerCommon.h2
-rw-r--r--include/lldb/Initialization/SystemLifetimeManager.h8
-rw-r--r--include/lldb/Interpreter/CommandAlias.h4
-rw-r--r--include/lldb/Interpreter/CommandCompletions.h12
-rw-r--r--include/lldb/Interpreter/CommandHistory.h4
-rw-r--r--include/lldb/Interpreter/CommandInterpreter.h85
-rw-r--r--include/lldb/Interpreter/CommandObject.h11
-rw-r--r--include/lldb/Interpreter/CommandObjectMultiword.h4
-rw-r--r--include/lldb/Interpreter/CommandObjectRegexCommand.h4
-rw-r--r--include/lldb/Interpreter/CommandOptionValidators.h4
-rw-r--r--include/lldb/Interpreter/CommandReturnObject.h4
-rw-r--r--include/lldb/Interpreter/OptionArgParser.h2
-rw-r--r--include/lldb/Interpreter/OptionGroupBoolean.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupFile.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupFormat.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupOutputFile.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupPlatform.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupString.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupUInt64.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupUUID.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupValueObjectDisplay.h4
-rw-r--r--include/lldb/Interpreter/OptionGroupVariable.h6
-rw-r--r--include/lldb/Interpreter/OptionGroupWatchpoint.h4
-rw-r--r--include/lldb/Interpreter/OptionValue.h8
-rw-r--r--include/lldb/Interpreter/OptionValueArgs.h4
-rw-r--r--include/lldb/Interpreter/OptionValueArray.h4
-rw-r--r--include/lldb/Interpreter/OptionValueBoolean.h4
-rw-r--r--include/lldb/Interpreter/OptionValueChar.h4
-rw-r--r--include/lldb/Interpreter/OptionValueDictionary.h4
-rw-r--r--include/lldb/Interpreter/OptionValueEnumeration.h5
-rw-r--r--include/lldb/Interpreter/OptionValueFileSpecList.h4
-rw-r--r--include/lldb/Interpreter/OptionValueFormat.h4
-rw-r--r--include/lldb/Interpreter/OptionValueFormatEntity.h4
-rw-r--r--include/lldb/Interpreter/OptionValueLanguage.h4
-rw-r--r--include/lldb/Interpreter/OptionValuePathMappings.h4
-rw-r--r--include/lldb/Interpreter/OptionValueProperties.h6
-rw-r--r--include/lldb/Interpreter/OptionValueRegex.h4
-rw-r--r--include/lldb/Interpreter/OptionValueSInt64.h4
-rw-r--r--include/lldb/Interpreter/OptionValueString.h4
-rw-r--r--include/lldb/Interpreter/OptionValueUInt64.h4
-rw-r--r--include/lldb/Interpreter/OptionValueUUID.h4
-rw-r--r--include/lldb/Interpreter/Options.h4
-rw-r--r--include/lldb/Interpreter/Property.h4
-rw-r--r--include/lldb/Interpreter/ScriptInterpreter.h38
-rw-r--r--include/lldb/Symbol/Block.h12
-rw-r--r--include/lldb/Symbol/ClangASTContext.h73
-rw-r--r--include/lldb/Symbol/ClangASTImporter.h4
-rw-r--r--include/lldb/Symbol/ClangExternalASTSourceCallbacks.h4
-rw-r--r--include/lldb/Symbol/ClangExternalASTSourceCommon.h4
-rw-r--r--include/lldb/Symbol/ClangUtil.h6
-rw-r--r--include/lldb/Symbol/CompileUnit.h35
-rw-r--r--include/lldb/Symbol/CompilerType.h14
-rw-r--r--include/lldb/Symbol/DebugMacros.h4
-rw-r--r--include/lldb/Symbol/Function.h109
-rw-r--r--include/lldb/Symbol/GoASTContext.h421
-rw-r--r--include/lldb/Symbol/JavaASTContext.h350
-rw-r--r--include/lldb/Symbol/LineTable.h59
-rw-r--r--include/lldb/Symbol/OCamlASTContext.h318
-rw-r--r--include/lldb/Symbol/ObjectContainer.h4
-rw-r--r--include/lldb/Symbol/ObjectFile.h46
-rw-r--r--include/lldb/Symbol/SymbolContext.h22
-rw-r--r--include/lldb/Symbol/SymbolContextScope.h4
-rw-r--r--include/lldb/Symbol/SymbolFile.h83
-rw-r--r--include/lldb/Symbol/SymbolVendor.h42
-rw-r--r--include/lldb/Symbol/Symtab.h13
-rw-r--r--include/lldb/Symbol/TypeSystem.h11
-rw-r--r--include/lldb/Symbol/UnwindPlan.h64
-rw-r--r--include/lldb/Symbol/UnwindTable.h2
-rw-r--r--include/lldb/Target/ABI.h4
-rw-r--r--include/lldb/Target/CPPLanguageRuntime.h36
-rw-r--r--include/lldb/Target/DynamicLoader.h15
-rw-r--r--include/lldb/Target/ExecutionContext.h4
-rw-r--r--include/lldb/Target/ExecutionContextScope.h4
-rw-r--r--include/lldb/Target/InstrumentationRuntime.h4
-rw-r--r--include/lldb/Target/InstrumentationRuntimeStopInfo.h4
-rw-r--r--include/lldb/Target/Language.h16
-rw-r--r--include/lldb/Target/LanguageRuntime.h15
-rw-r--r--include/lldb/Target/Memory.h4
-rw-r--r--include/lldb/Target/MemoryHistory.h4
-rw-r--r--include/lldb/Target/MemoryRegionInfo.h21
-rw-r--r--include/lldb/Target/ObjCLanguageRuntime.h4
-rw-r--r--include/lldb/Target/OperatingSystem.h3
-rw-r--r--include/lldb/Target/PathMappingList.h4
-rw-r--r--include/lldb/Target/Platform.h16
-rw-r--r--include/lldb/Target/Process.h52
-rw-r--r--include/lldb/Target/ProcessLaunchInfo.h7
-rw-r--r--include/lldb/Target/ProcessStructReader.h12
-rw-r--r--include/lldb/Target/QueueItem.h4
-rw-r--r--include/lldb/Target/RegisterContext.h4
-rw-r--r--include/lldb/Target/SectionLoadHistory.h3
-rw-r--r--include/lldb/Target/SectionLoadList.h4
-rw-r--r--include/lldb/Target/StackFrame.h92
-rw-r--r--include/lldb/Target/StackFrameList.h66
-rw-r--r--include/lldb/Target/StackFrameRecognizer.h129
-rw-r--r--include/lldb/Target/StackID.h4
-rw-r--r--include/lldb/Target/StopInfo.h4
-rw-r--r--include/lldb/Target/SystemRuntime.h4
-rw-r--r--include/lldb/Target/Target.h122
-rw-r--r--include/lldb/Target/TargetList.h17
-rw-r--r--include/lldb/Target/Thread.h85
-rw-r--r--include/lldb/Target/ThreadPlan.h10
-rw-r--r--include/lldb/Target/ThreadPlanBase.h4
-rw-r--r--include/lldb/Target/ThreadPlanCallFunction.h4
-rw-r--r--include/lldb/Target/ThreadPlanCallFunctionUsingABI.h4
-rw-r--r--include/lldb/Target/ThreadPlanCallUserExpression.h4
-rw-r--r--include/lldb/Target/ThreadPlanPython.h5
-rw-r--r--include/lldb/Target/ThreadPlanRunToAddress.h4
-rw-r--r--include/lldb/Target/ThreadPlanShouldStopHere.h18
-rw-r--r--include/lldb/Target/ThreadPlanStepInRange.h10
-rw-r--r--include/lldb/Target/ThreadPlanStepInstruction.h7
-rw-r--r--include/lldb/Target/ThreadPlanStepOut.h7
-rw-r--r--include/lldb/Target/ThreadPlanStepOverBreakpoint.h4
-rw-r--r--include/lldb/Target/ThreadPlanStepOverRange.h4
-rw-r--r--include/lldb/Target/ThreadPlanStepRange.h4
-rw-r--r--include/lldb/Target/ThreadPlanStepThrough.h7
-rw-r--r--include/lldb/Target/ThreadPlanStepUntil.h6
-rw-r--r--include/lldb/Target/ThreadPlanTracer.h6
-rw-r--r--include/lldb/Target/UnixSignals.h4
-rw-r--r--include/lldb/Target/Unwind.h4
-rw-r--r--include/lldb/Utility/ArchSpec.h9
-rw-r--r--include/lldb/Utility/Baton.h4
-rw-r--r--include/lldb/Utility/Broadcaster.h (renamed from include/lldb/Core/Broadcaster.h)20
-rw-r--r--include/lldb/Utility/CompletionRequest.h89
-rw-r--r--include/lldb/Utility/Connection.h12
-rw-r--r--include/lldb/Utility/ConstString.h22
-rw-r--r--include/lldb/Utility/DataBufferHeap.h9
-rw-r--r--include/lldb/Utility/DataBufferLLVM.h12
-rw-r--r--include/lldb/Utility/DataEncoder.h10
-rw-r--r--include/lldb/Utility/DataExtractor.h10
-rw-r--r--include/lldb/Utility/Either.h126
-rw-r--r--include/lldb/Utility/Event.h (renamed from include/lldb/Core/Event.h)20
-rw-r--r--include/lldb/Utility/FastDemangle.h26
-rw-r--r--include/lldb/Utility/FileSpec.h119
-rw-r--r--include/lldb/Utility/Iterable.h4
-rw-r--r--include/lldb/Utility/LLDBAssert.h3
-rw-r--r--include/lldb/Utility/Listener.h (renamed from include/lldb/Core/Listener.h)20
-rw-r--r--include/lldb/Utility/Log.h10
-rw-r--r--include/lldb/Utility/Predicate.h (renamed from include/lldb/Host/Predicate.h)12
-rw-r--r--include/lldb/Utility/Range.h60
-rw-r--r--include/lldb/Utility/RegisterValue.h (renamed from include/lldb/Core/RegisterValue.h)28
-rw-r--r--include/lldb/Utility/RegularExpression.h2
-rw-r--r--include/lldb/Utility/Reproducer.h215
-rw-r--r--include/lldb/Utility/Scalar.h (renamed from include/lldb/Core/Scalar.h)22
-rw-r--r--include/lldb/Utility/SelectHelper.h4
-rw-r--r--include/lldb/Utility/SharingPtr.h4
-rw-r--r--include/lldb/Utility/State.h (renamed from include/lldb/Core/State.h)18
-rw-r--r--include/lldb/Utility/Status.h10
-rw-r--r--include/lldb/Utility/Stream.h119
-rw-r--r--include/lldb/Utility/StreamCallback.h4
-rw-r--r--include/lldb/Utility/StreamGDBRemote.h8
-rw-r--r--include/lldb/Utility/StreamString.h15
-rw-r--r--include/lldb/Utility/StreamTee.h46
-rw-r--r--include/lldb/Utility/StringExtractor.h4
-rw-r--r--include/lldb/Utility/StringExtractorGDBRemote.h6
-rw-r--r--include/lldb/Utility/StringLexer.h9
-rw-r--r--include/lldb/Utility/StringList.h2
-rw-r--r--include/lldb/Utility/StructuredData.h16
-rw-r--r--include/lldb/Utility/Timer.h4
-rw-r--r--include/lldb/Utility/UUID.h2
-rw-r--r--include/lldb/Utility/UserID.h4
-rw-r--r--include/lldb/Utility/VMRange.h24
-rw-r--r--include/lldb/lldb-defines.h1
-rw-r--r--include/lldb/lldb-enumerations.h106
-rw-r--r--include/lldb/lldb-forward.h24
-rw-r--r--include/lldb/lldb-private-forward.h11
-rw-r--r--include/lldb/lldb-private-interfaces.h4
-rw-r--r--include/lldb/lldb-private-types.h7
-rw-r--r--include/lldb/lldb-types.h9
-rw-r--r--include/lldb/module.modulemap2
-rw-r--r--lit/Breakpoint/Inputs/debug_addrx.yaml57
-rw-r--r--lit/Breakpoint/Inputs/debug_rnglist_basic.yaml50
-rw-r--r--lit/Breakpoint/Inputs/debug_rnglist_offset_pair.yaml53
-rw-r--r--lit/Breakpoint/Inputs/debug_rnglist_rlestartend.yaml49
-rw-r--r--lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml57
-rw-r--r--lit/Breakpoint/Inputs/implicit_const_form_support.yaml41
-rw-r--r--lit/Breakpoint/Inputs/single-file-split-dwarf.o.yaml84
-rw-r--r--lit/Breakpoint/Inputs/single-file-split-dwarf.yaml61
-rw-r--r--lit/Breakpoint/Inputs/split-dwarf-5-addrbase.dwo.yaml35
-rw-r--r--lit/Breakpoint/Inputs/split-dwarf-5-addrbase.yaml61
-rw-r--r--lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file1.dwo.yaml40
-rw-r--r--lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file2.dwo.yaml40
-rw-r--r--lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-main.yaml70
-rw-r--r--lit/Breakpoint/case-insensitive.test8
-rw-r--r--lit/Breakpoint/case-sensitive.test2
-rw-r--r--lit/Breakpoint/debug_addrx.test30
-rw-r--r--lit/Breakpoint/debug_rnglist_basic.test30
-rw-r--r--lit/Breakpoint/debug_rnglist_offset_pair.test33
-rw-r--r--lit/Breakpoint/debug_rnglist_rlestartend.test28
-rw-r--r--lit/Breakpoint/debug_rnglistx_rlex.test28
-rw-r--r--lit/Breakpoint/implicit_const_form_support.test33
-rw-r--r--lit/Breakpoint/single-file-split-dwarf.test44
-rw-r--r--lit/Breakpoint/split-dwarf-5-addrbase.test30
-rw-r--r--lit/Breakpoint/split-dwarf5-debug-stroffsets.test84
-rw-r--r--lit/BuildScript/modes.test35
-rw-r--r--lit/BuildScript/script-args.test32
-rw-r--r--lit/BuildScript/toolchain-clang-cl.test49
-rw-r--r--lit/BuildScript/toolchain-clang.test14
-rw-r--r--lit/BuildScript/toolchain-msvc.test62
-rw-r--r--lit/CMakeLists.txt55
-rw-r--r--lit/Driver/Inputs/Print0.in1
-rw-r--r--lit/Driver/Inputs/Print2.in1
-rw-r--r--lit/Driver/Inputs/Print4.in1
-rw-r--r--lit/Driver/Inputs/Print6.in1
-rw-r--r--lit/Driver/Inputs/convenience.in9
-rw-r--r--lit/Driver/Inputs/hello.cpp11
-rw-r--r--lit/Driver/TestCommands.test41
-rw-r--r--lit/Driver/TestConvenienceVariables.test22
-rw-r--r--lit/Driver/TestCore.test2
-rw-r--r--lit/Driver/TestFile.test2
-rw-r--r--lit/Driver/TestNoUseColor.test4
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook-1.lldbinit1
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook-2.lldbinit1
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook-3.lldbinit3
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook-threads-1.lldbinit7
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook-threads-2.lldbinit4
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook-threads.cpp (renamed from packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp)11
-rw-r--r--lit/ExecControl/StopHook/Inputs/stop-hook.c (renamed from packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp)0
-rw-r--r--lit/ExecControl/StopHook/stop-hook-threads.test33
-rw-r--r--lit/ExecControl/StopHook/stop-hook.test76
-rw-r--r--lit/Expr/TestIRMemoryMap.test4
-rw-r--r--lit/Expr/TestIRMemoryMapWindows.test13
-rw-r--r--lit/Expr/TestMultilineExpr.test9
-rw-r--r--lit/Heap/Inputs/cstr.c17
-rw-r--r--lit/Heap/heap-cstr.test10
-rw-r--r--lit/Minidump/Inputs/dump-content.dmpbin0 -> 664 bytes
-rw-r--r--lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.cpp40
-rw-r--r--lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.dmpbin0 -> 102370 bytes
-rw-r--r--lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.lldbinit2
-rw-r--r--lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.pdbbin0 -> 102400 bytes
-rw-r--r--lit/Minidump/Windows/Sigsegv/sigsegv.test13
-rw-r--r--lit/Minidump/dump-all.test86
-rw-r--r--lit/Modules/Breakpad/Inputs/bad-module-id-1.syms2
-rw-r--r--lit/Modules/Breakpad/Inputs/bad-module-id-2.syms2
-rw-r--r--lit/Modules/Breakpad/Inputs/bad-module-id-3.syms2
-rw-r--r--lit/Modules/Breakpad/Inputs/discontiguous-sections.syms5
-rw-r--r--lit/Modules/Breakpad/Inputs/identification-linux.syms6
-rw-r--r--lit/Modules/Breakpad/Inputs/identification-macosx.syms6
-rw-r--r--lit/Modules/Breakpad/Inputs/identification-windows.syms4
-rw-r--r--lit/Modules/Breakpad/Inputs/sections-trailing-func.syms8
-rw-r--r--lit/Modules/Breakpad/Inputs/sections.syms12
-rw-r--r--lit/Modules/Breakpad/breakpad-identification.test32
-rw-r--r--lit/Modules/Breakpad/discontiguous-sections.test27
-rw-r--r--lit/Modules/Breakpad/lit.local.cfg (renamed from lit/Breakpoint/lit.local.cfg)0
-rw-r--r--lit/Modules/Breakpad/sections-trailing-func.test15
-rw-r--r--lit/Modules/Breakpad/sections.test89
-rw-r--r--lit/Modules/ELF/Inputs/PT_LOAD-overlap-section.elfbin0 -> 402 bytes
-rw-r--r--lit/Modules/ELF/PT_LOAD-empty.yaml26
-rw-r--r--lit/Modules/ELF/PT_LOAD-overlap-PT_INTERP.yaml50
-rw-r--r--lit/Modules/ELF/PT_LOAD-overlap-section.yaml66
-rw-r--r--lit/Modules/ELF/PT_LOAD-overlap.yaml42
-rw-r--r--lit/Modules/ELF/PT_LOAD.yaml79
-rw-r--r--lit/Modules/ELF/base-address.yaml34
-rw-r--r--lit/Modules/ELF/basic-info.yaml27
-rw-r--r--lit/Modules/ELF/build-id-case.yaml (renamed from lit/Modules/build-id-case.yaml)2
-rw-r--r--lit/Modules/ELF/compressed-sections.yaml (renamed from lit/Modules/compressed-sections.yaml)5
-rw-r--r--lit/Modules/ELF/duplicate-section.yaml (renamed from lit/Modules/elf-duplicate-section.yaml)0
-rw-r--r--lit/Modules/ELF/many-sections.s (renamed from lit/Modules/elf-many-sections.s)2
-rw-r--r--lit/Modules/ELF/section-addresses.yaml58
-rw-r--r--lit/Modules/ELF/section-overlap.yaml51
-rw-r--r--lit/Modules/ELF/section-permissions.yaml34
-rw-r--r--lit/Modules/ELF/section-types-edgecases.yaml35
-rw-r--r--lit/Modules/ELF/section-types.yaml (renamed from lit/Modules/elf-section-types.yaml)49
-rw-r--r--lit/Modules/ELF/short-build-id.yaml (renamed from lit/Modules/short-build-id.yaml)0
-rw-r--r--lit/Modules/MachO/lc_build_version.yaml209
-rw-r--r--lit/Modules/MachO/lc_build_version_notools.yaml206
-rw-r--r--lit/Modules/MachO/lc_version_min.yaml (renamed from lit/Modules/lc_version_min.yaml)0
-rw-r--r--lit/Modules/MachO/subsections.yaml126
-rw-r--r--lit/Modules/PECOFF/dep-modules.yaml170
-rw-r--r--lit/Modules/PECOFF/export-dllfunc.yaml172
-rw-r--r--lit/Modules/PECOFF/lit.local.cfg1
-rw-r--r--lit/Modules/PECOFF/sections-names.yaml52
-rw-r--r--lit/Python/crashlog.test99
-rw-r--r--lit/Quit/TestQuitExitCode-30.test2
-rw-r--r--lit/Quit/TestQuitExitCode30.test2
-rw-r--r--lit/Quit/TestQuitExitCodeHexA.test2
-rw-r--r--lit/Quit/lit.local.cfg1
-rw-r--r--lit/Reproducer/Inputs/GDBRemoteCapture.in6
-rw-r--r--lit/Reproducer/Inputs/GDBRemoteReplay.in5
-rw-r--r--lit/Reproducer/Inputs/simple.c19
-rw-r--r--lit/Reproducer/TestDriverOptions.test7
-rw-r--r--lit/Reproducer/TestGDBRemoteRepro.test26
-rw-r--r--lit/Settings/Inputs/EchoCommandsAll.out6
-rw-r--r--lit/Settings/Inputs/EchoCommandsNoComments.out5
-rw-r--r--lit/Settings/Inputs/EchoCommandsNone.out4
-rw-r--r--lit/Settings/Inputs/EchoCommandsQuiet.out2
-rw-r--r--lit/Settings/Inputs/EchoCommandsTest.in2
-rw-r--r--lit/Settings/TestDisableColor.test7
-rw-r--r--lit/Settings/TestDisassemblyFormat.test2
-rw-r--r--lit/Settings/TestEchoCommands.test4
-rw-r--r--lit/Settings/TestSettingsSet.test15
-rw-r--r--lit/Settings/TestSettingsWrite.test32
-rw-r--r--lit/Suite/lit.cfg13
-rw-r--r--lit/Suite/lit.site.cfg.in6
-rw-r--r--lit/Suite/lldbtest.py46
-rw-r--r--lit/SymbolFile/Breakpad/Inputs/basic-elf.yaml33
-rw-r--r--lit/SymbolFile/Breakpad/Inputs/symtab.syms7
-rw-r--r--lit/SymbolFile/Breakpad/symtab.test23
-rw-r--r--lit/SymbolFile/DWARF/apple-index-is-used.cpp2
-rw-r--r--lit/SymbolFile/DWARF/array-sizes.s147
-rw-r--r--lit/SymbolFile/DWARF/childless-compile-unit.s45
-rw-r--r--lit/SymbolFile/DWARF/debug-names-compressed.cpp2
-rw-r--r--lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp2
-rw-r--r--lit/SymbolFile/DWARF/dwarf5-partial-index.cpp4
-rw-r--r--lit/SymbolFile/DWARF/find-basic-function.cpp6
-rw-r--r--lit/SymbolFile/DWARF/find-basic-namespace.cpp6
-rw-r--r--lit/SymbolFile/DWARF/find-basic-type.cpp6
-rw-r--r--lit/SymbolFile/DWARF/find-basic-variable.cpp6
-rw-r--r--lit/SymbolFile/DWARF/find-function-regex.cpp6
-rw-r--r--lit/SymbolFile/DWARF/find-method-local-struct.cpp2
-rw-r--r--lit/SymbolFile/DWARF/find-method.cpp4
-rw-r--r--lit/SymbolFile/DWARF/find-qualified-variable.cpp2
-rw-r--r--lit/SymbolFile/DWARF/find-type-in-function.cpp2
-rw-r--r--lit/SymbolFile/DWARF/find-variable-dwo.cpp4
-rw-r--r--lit/SymbolFile/DWARF/find-variable-file.cpp8
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit8
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit20
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit5
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/break-by-function.lldbinit6
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/break-by-line.lldbinit3
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/disassembly.lldbinit2
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit70
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit7
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit14
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/globals-bss.lldbinit3
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit16
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit222
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/local-variables.lldbinit32
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/nested-types.lldbinit13
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/s_constant.lldbinit25
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/s_constant.s971
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/source-list.lldbinit3
-rw-r--r--lit/SymbolFile/NativePDB/Inputs/tag-types.lldbinit8
-rw-r--r--lit/SymbolFile/NativePDB/ast-functions-msvc.cpp7
-rw-r--r--lit/SymbolFile/NativePDB/ast-functions.cpp29
-rw-r--r--lit/SymbolFile/NativePDB/ast-types.cpp131
-rw-r--r--lit/SymbolFile/NativePDB/bitfields.cpp60
-rw-r--r--lit/SymbolFile/NativePDB/break-by-function.cpp57
-rw-r--r--lit/SymbolFile/NativePDB/break-by-line.cpp26
-rw-r--r--lit/SymbolFile/NativePDB/disassembly.cpp38
-rw-r--r--lit/SymbolFile/NativePDB/function-types-builtins.cpp214
-rw-r--r--lit/SymbolFile/NativePDB/function-types-calling-conv.cpp32
-rw-r--r--lit/SymbolFile/NativePDB/function-types-classes.cpp141
-rw-r--r--lit/SymbolFile/NativePDB/global-classes.cpp370
-rw-r--r--lit/SymbolFile/NativePDB/globals-bss.cpp34
-rw-r--r--lit/SymbolFile/NativePDB/globals-fundamental.cpp880
-rw-r--r--lit/SymbolFile/NativePDB/local-variables.cpp161
-rw-r--r--lit/SymbolFile/NativePDB/nested-types.cpp153
-rw-r--r--lit/SymbolFile/NativePDB/s_constant.cpp115
-rw-r--r--lit/SymbolFile/NativePDB/source-list.cpp42
-rw-r--r--lit/SymbolFile/NativePDB/tag-types.cpp235
-rw-r--r--lit/SymbolFile/NativePDB/typedefs.cpp71
-rw-r--r--lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp55
-rw-r--r--lit/SymbolFile/PDB/Inputs/CallingConventionsTest.cpp20
-rw-r--r--lit/SymbolFile/PDB/Inputs/ClassLayoutTest.cpp111
-rw-r--r--lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp20
-rw-r--r--lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script7
-rw-r--r--lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script1
-rw-r--r--lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script2
-rw-r--r--lit/SymbolFile/PDB/Inputs/PointerTypeTest.cpp23
-rw-r--r--lit/SymbolFile/PDB/Inputs/SimpleTypesTest.cpp3
-rw-r--r--lit/SymbolFile/PDB/Inputs/UdtLayoutTest.cpp61
-rw-r--r--lit/SymbolFile/PDB/Inputs/UdtLayoutTest.script4
-rw-r--r--lit/SymbolFile/PDB/Inputs/VBases.cpp16
-rw-r--r--lit/SymbolFile/PDB/Inputs/VBases.script7
-rw-r--r--lit/SymbolFile/PDB/ast-restore.test82
-rw-r--r--lit/SymbolFile/PDB/calling-conventions.test10
-rw-r--r--lit/SymbolFile/PDB/class-layout.test92
-rw-r--r--lit/SymbolFile/PDB/compilands.test10
-rw-r--r--lit/SymbolFile/PDB/enums-layout.test72
-rw-r--r--lit/SymbolFile/PDB/expressions.test35
-rw-r--r--lit/SymbolFile/PDB/func-symbols.test16
-rw-r--r--lit/SymbolFile/PDB/function-level-linking.test7
-rw-r--r--lit/SymbolFile/PDB/function-nested-block.test16
-rw-r--r--lit/SymbolFile/PDB/lit.local.cfg1
-rw-r--r--lit/SymbolFile/PDB/pointers.test38
-rw-r--r--lit/SymbolFile/PDB/type-quals.test56
-rw-r--r--lit/SymbolFile/PDB/typedefs.test12
-rw-r--r--lit/SymbolFile/PDB/udt-layout.test51
-rw-r--r--lit/SymbolFile/PDB/variables-locations.test6
-rw-r--r--lit/SymbolFile/PDB/variables.test114
-rw-r--r--lit/SymbolFile/PDB/vbases.test15
-rw-r--r--lit/Unit/lit.cfg.py (renamed from lit/Unit/lit.cfg)9
-rw-r--r--lit/Unit/lit.site.cfg.py.in (renamed from lit/Unit/lit.site.cfg.in)7
-rw-r--r--lit/helper/__init__.py0
-rwxr-xr-xlit/helper/build.py787
-rw-r--r--lit/helper/toolchain.py122
-rw-r--r--lit/lit-lldb-init1
-rw-r--r--lit/lit.cfg174
-rw-r--r--lit/lit.cfg.py75
-rw-r--r--lit/lit.site.cfg.py.in (renamed from lit/lit.site.cfg.in)19
-rw-r--r--lit/tools/lldb-mi/breakpoint/break-insert-enable-pending.test47
-rw-r--r--lit/tools/lldb-mi/breakpoint/break-insert.test5
-rw-r--r--lit/tools/lldb-mi/breakpoint/inputs/break-insert-pending.c6
-rw-r--r--lit/tools/lldb-mi/data/data-info-line.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-continue.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-finish.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-interrupt.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-next-instruction.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-next.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-step-instruction.test5
-rw-r--r--lit/tools/lldb-mi/exec/exec-step.test5
-rw-r--r--lit/tools/lldb-mi/symbol/symbol-list-lines.test9
-rw-r--r--lit/tools/lldb-mi/target/inputs/main.c4
-rw-r--r--lit/tools/lldb-mi/target/inputs/target-select-so-path.py50
-rw-r--r--lit/tools/lldb-mi/target/lit.local.cfg (renamed from lit/Expr/lit.local.cfg)0
-rw-r--r--lit/tools/lldb-mi/target/target-select-so-path.test25
-rw-r--r--lldb.xcodeproj/project.pbxproj1169
-rw-r--r--lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme1
-rw-r--r--lldb.xcodeproj/xcshareddata/xcschemes/darwin-debug.xcscheme1
-rw-r--r--packages/Python/lldbsuite/support/encoded_file.py2
-rw-r--r--packages/Python/lldbsuite/test/README-TestSuite101
-rw-r--r--packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py2
-rw-r--r--packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py2
-rw-r--r--packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py165
-rw-r--r--packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py70
-rw-r--r--packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py120
-rw-r--r--packages/Python/lldbsuite/test/configuration.py48
-rw-r--r--packages/Python/lldbsuite/test/decorators.py66
-rw-r--r--packages/Python/lldbsuite/test/dosep.py15
-rw-r--r--packages/Python/lldbsuite/test/dotest.py82
-rw-r--r--packages/Python/lldbsuite/test/dotest_args.py2
-rw-r--r--packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py53
-rw-r--r--packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py5
-rw-r--r--packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py4
-rw-r--r--packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py3
-rw-r--r--packages/Python/lldbsuite/test/expression_command/completion/.categories1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/completion/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py257
-rw-r--r--packages/Python/lldbsuite/test/expression_command/completion/main.cpp35
-rw-r--r--packages/Python/lldbsuite/test/expression_command/completion/other.cpp4
-rw-r--r--packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py90
-rw-r--r--packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c15
-rw-r--r--packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py118
-rw-r--r--packages/Python/lldbsuite/test/expression_command/formatters/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py90
-rw-r--r--packages/Python/lldbsuite/test/expression_command/multiline/main.c6
-rw-r--r--packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py28
-rw-r--r--packages/Python/lldbsuite/test/expression_command/options/main.cpp4
-rw-r--r--packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py44
-rw-r--r--packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp16
-rw-r--r--packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py1
-rw-r--r--packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile3
-rw-r--r--packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py4
-rw-r--r--packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c8
-rw-r--r--packages/Python/lldbsuite/test/expression_command/test/TestExprs.py2
-rw-r--r--packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py7
-rw-r--r--packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/asan/Makefile2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py48
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c23
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile9
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py106
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c9
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py199
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c21
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py54
-rw-r--r--packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py9
-rw-r--r--packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py57
-rw-r--r--packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py20
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp21
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile7
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py75
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp42
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py8
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile7
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py83
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp60
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp7
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile (renamed from packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile)0
-rw-r--r--packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py31
-rw-r--r--packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp9
-rw-r--r--packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py108
-rw-r--r--packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/exec/TestExec.py6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile (renamed from packages/Python/lldbsuite/test/expression_command/multiline/Makefile)0
-rw-r--r--packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py34
-rw-r--r--packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c10
-rw-r--r--packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile10
-rw-r--r--packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py117
-rw-r--r--packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m28
-rw-r--r--packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py21
-rw-r--r--packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py130
-rw-r--r--packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py64
-rw-r--r--packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py46
-rw-r--r--packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py36
-rw-r--r--packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py25
-rw-r--r--packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/memory-region/Makefile8
-rw-r--r--packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py59
-rw-r--r--packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py50
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py271
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmpbin0 -> 588 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmpbin0 -> 588 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmpbin0 -> 1016 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmpbin0 -> 1379 bytes
-rw-r--r--packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py25
-rw-r--r--packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py34
-rw-r--r--packages/Python/lldbsuite/test/functionalities/show_location/a.yaml58
-rw-r--r--packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py9
-rw-r--r--packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile (renamed from packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile)0
-rw-r--r--packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py37
-rw-r--r--packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py41
-rw-r--r--packages/Python/lldbsuite/test/functionalities/step_scripted/main.c10
-rw-r--r--packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py77
-rw-r--r--packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py128
-rw-r--r--packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py100
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp33
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp38
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp32
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp38
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp31
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp50
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py73
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp25
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp28
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py95
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp25
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py5
-rw-r--r--packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp30
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile16
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py100
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp13
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk9
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp17
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_var/Makefile10
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py23
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_var/globals.c6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/target_var/globals.ll42
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile6
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py31
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp13
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py1
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py4
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py25
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py3
-rw-r--r--packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py2
-rw-r--r--packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py1
-rw-r--r--packages/Python/lldbsuite/test/help/TestHelp.py11
-rw-r--r--packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py32
-rw-r--r--packages/Python/lldbsuite/test/lang/c/bitfields/main.c15
-rw-r--r--packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py10
-rw-r--r--packages/Python/lldbsuite/test/lang/c/local_variables/Makefile7
-rw-r--r--packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py55
-rw-r--r--packages/Python/lldbsuite/test/lang/c/local_variables/main.c19
-rw-r--r--packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py2
-rw-r--r--packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py5
-rw-r--r--packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/c/vla/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py27
-rw-r--r--packages/Python/lldbsuite/test/lang/c/vla/main.c15
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py3
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py2
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py4
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py2
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py5
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py5
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py19
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py5
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py3
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py3
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py2
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile7
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py71
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp38
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py3
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py24
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp16
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py9
-rw-r--r--packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py1
-rw-r--r--packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py123
-rw-r--r--packages/Python/lldbsuite/test/lang/go/expressions/main.go21
-rw-r--r--packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py76
-rw-r--r--packages/Python/lldbsuite/test/lang/go/formatters/main.go9
-rw-r--r--packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py104
-rw-r--r--packages/Python/lldbsuite/test/lang/go/goroutines/main.go89
-rw-r--r--packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime80
-rw-r--r--packages/Python/lldbsuite/test/lang/go/runtime/main.go38
-rw-r--r--packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py145
-rw-r--r--packages/Python/lldbsuite/test/lang/go/types/main.go47
-rw-r--r--packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py2
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile9
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py205
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm63
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py17
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h2
-rw-r--r--packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h2
-rw-r--r--packages/Python/lldbsuite/test/lldbinline.py2
-rw-r--r--packages/Python/lldbsuite/test/lldbtest.py188
-rw-r--r--packages/Python/lldbsuite/test/lldbutil.py46
-rw-r--r--packages/Python/lldbsuite/test/macosx/function-starts/Makefile10
-rw-r--r--packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py76
-rw-r--r--packages/Python/lldbsuite/test/macosx/function-starts/main.cpp26
-rw-r--r--packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py38
-rw-r--r--packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml222
-rw-r--r--packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py3
-rw-r--r--packages/Python/lldbsuite/test/macosx/queues/TestQueues.py18
-rw-r--r--packages/Python/lldbsuite/test/macosx/queues/main.c48
-rw-r--r--packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c1
-rw-r--r--packages/Python/lldbsuite/test/macosx/universal/Makefile18
-rw-r--r--packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py100
-rw-r--r--packages/Python/lldbsuite/test/make/Makefile.rules91
-rw-r--r--packages/Python/lldbsuite/test/python_api/event/TestEvents.py2
-rw-r--r--packages/Python/lldbsuite/test/python_api/frame/TestFrames.py1
-rw-r--r--packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py41
-rw-r--r--packages/Python/lldbsuite/test/python_api/hello_world/main.c24
-rw-r--r--packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp2
-rw-r--r--packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py3
-rw-r--r--packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py1
-rw-r--r--packages/Python/lldbsuite/test/settings/TestSettings.py6
-rw-r--r--packages/Python/lldbsuite/test/source-manager/TestSourceManager.py32
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py8
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py10
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py23
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error1
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py2
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py11
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py1
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/.categories1
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py192
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c8
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py211
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py51
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py167
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp27
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py352
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c15
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py288
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py160
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c13
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile (renamed from packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile)3
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py79
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp16
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile5
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py225
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp18
-rw-r--r--packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py1084
-rw-r--r--resources/LLDB-Info.plist.in24
-rw-r--r--scripts/CMakeLists.txt45
-rw-r--r--scripts/Python/python-extensions.swig82
-rw-r--r--scripts/Python/python-swigsafecast.swig23
-rw-r--r--scripts/Python/python-typemaps.swig269
-rw-r--r--scripts/Python/python-wrapper.swig143
-rw-r--r--scripts/Xcode/lldbbuild.py2
-rw-r--r--scripts/Xcode/package-clang-headers.py3
-rw-r--r--scripts/analyze-project-deps.py38
-rwxr-xr-xscripts/framework-header-fix.sh14
-rw-r--r--scripts/interface/SBBreakpoint.i7
-rw-r--r--scripts/interface/SBCommandInterpreter.i7
-rw-r--r--scripts/interface/SBDebugger.i54
-rw-r--r--scripts/interface/SBExpressionOptions.i8
-rw-r--r--scripts/interface/SBFrame.i11
-rw-r--r--scripts/interface/SBInitializerOptions.i24
-rw-r--r--scripts/interface/SBMemoryRegionInfo.i3
-rw-r--r--scripts/interface/SBModule.i3
-rw-r--r--scripts/interface/SBStructuredData.i2
-rw-r--r--scripts/interface/SBTarget.i85
-rw-r--r--scripts/interface/SBThread.i18
-rw-r--r--scripts/interface/SBThreadPlan.i3
-rw-r--r--scripts/interface/SBVariablesOptions.i8
-rw-r--r--scripts/lldb.swig11
-rw-r--r--scripts/utilsOsType.py5
-rw-r--r--source/API/CMakeLists.txt44
-rw-r--r--source/API/SBAddress.cpp7
-rw-r--r--source/API/SBAttachInfo.cpp9
-rw-r--r--source/API/SBBreakpoint.cpp47
-rw-r--r--source/API/SBBreakpointName.cpp8
-rw-r--r--source/API/SBBreakpointOptionCommon.cpp4
-rw-r--r--source/API/SBBroadcaster.cpp2
-rw-r--r--source/API/SBCommandInterpreter.cpp47
-rw-r--r--source/API/SBCommandReturnObject.cpp8
-rw-r--r--source/API/SBCompileUnit.cpp26
-rw-r--r--source/API/SBData.cpp2
-rw-r--r--source/API/SBDebugger.cpp43
-rw-r--r--source/API/SBDeclaration.cpp8
-rw-r--r--source/API/SBError.cpp20
-rw-r--r--source/API/SBEvent.cpp2
-rw-r--r--source/API/SBExpressionOptions.cpp9
-rw-r--r--source/API/SBFileSpec.cpp25
-rw-r--r--source/API/SBFileSpecList.cpp8
-rw-r--r--source/API/SBFrame.cpp71
-rw-r--r--source/API/SBHostOS.cpp6
-rw-r--r--source/API/SBInitializerOptions.cpp49
-rw-r--r--source/API/SBLaunchInfo.cpp7
-rw-r--r--source/API/SBLineEntry.cpp12
-rw-r--r--source/API/SBListener.cpp4
-rw-r--r--source/API/SBMemoryRegionInfoList.cpp34
-rw-r--r--source/API/SBModule.cpp43
-rw-r--r--source/API/SBModuleSpec.cpp3
-rw-r--r--source/API/SBPlatform.cpp18
-rw-r--r--source/API/SBProcess.cpp59
-rw-r--r--source/API/SBProcessInfo.cpp4
-rw-r--r--source/API/SBQueue.cpp6
-rw-r--r--source/API/SBSection.cpp3
-rw-r--r--source/API/SBSourceManager.cpp2
-rw-r--r--source/API/SBStream.cpp29
-rw-r--r--source/API/SBStringList.cpp2
-rw-r--r--source/API/SBStructuredData.cpp33
-rw-r--r--source/API/SBSymbolContext.cpp35
-rw-r--r--source/API/SBSymbolContextList.cpp12
-rw-r--r--source/API/SBTarget.cpp155
-rw-r--r--source/API/SBThread.cpp118
-rw-r--r--source/API/SBThreadPlan.cpp102
-rw-r--r--source/API/SBType.cpp41
-rw-r--r--source/API/SBTypeCategory.cpp4
-rw-r--r--source/API/SBTypeEnumMember.cpp4
-rw-r--r--source/API/SBTypeFilter.cpp6
-rw-r--r--source/API/SBTypeFormat.cpp6
-rw-r--r--source/API/SBTypeNameSpecifier.cpp6
-rw-r--r--source/API/SBTypeSummary.cpp10
-rw-r--r--source/API/SBTypeSynthetic.cpp6
-rw-r--r--source/API/SBValue.cpp7
-rw-r--r--source/API/SBValueList.cpp14
-rw-r--r--source/API/SBVariablesOptions.cpp29
-rw-r--r--source/API/SystemInitializerFull.cpp75
-rw-r--r--source/API/SystemInitializerFull.h2
-rw-r--r--source/Breakpoint/Breakpoint.cpp12
-rw-r--r--source/Breakpoint/BreakpointID.cpp4
-rw-r--r--source/Breakpoint/BreakpointIDList.cpp4
-rw-r--r--source/Breakpoint/BreakpointList.cpp173
-rw-r--r--source/Breakpoint/BreakpointLocation.cpp4
-rw-r--r--source/Breakpoint/BreakpointLocationCollection.cpp4
-rw-r--r--source/Breakpoint/BreakpointLocationList.cpp4
-rw-r--r--source/Breakpoint/BreakpointName.cpp4
-rw-r--r--source/Breakpoint/BreakpointOptions.cpp4
-rw-r--r--source/Breakpoint/BreakpointResolver.cpp277
-rw-r--r--source/Breakpoint/BreakpointResolverAddress.cpp10
-rw-r--r--source/Breakpoint/BreakpointResolverFileLine.cpp51
-rw-r--r--source/Breakpoint/BreakpointResolverFileRegex.cpp8
-rw-r--r--source/Breakpoint/BreakpointResolverName.cpp31
-rw-r--r--source/Breakpoint/BreakpointResolverScripted.cpp189
-rw-r--r--source/Breakpoint/BreakpointSite.cpp4
-rw-r--r--source/Breakpoint/BreakpointSiteList.cpp4
-rw-r--r--source/Breakpoint/CMakeLists.txt1
-rw-r--r--source/Breakpoint/Stoppoint.cpp4
-rw-r--r--source/Breakpoint/StoppointCallbackContext.cpp4
-rw-r--r--source/Breakpoint/StoppointLocation.cpp4
-rw-r--r--source/Breakpoint/Watchpoint.cpp9
-rw-r--r--source/Breakpoint/WatchpointList.cpp4
-rw-r--r--source/Breakpoint/WatchpointOptions.cpp4
-rw-r--r--source/Commands/CMakeLists.txt1
-rw-r--r--source/Commands/CommandCompletions.cpp56
-rw-r--r--source/Commands/CommandObjectApropos.cpp4
-rw-r--r--source/Commands/CommandObjectApropos.h4
-rw-r--r--source/Commands/CommandObjectBreakpoint.cpp228
-rw-r--r--source/Commands/CommandObjectBreakpoint.h4
-rw-r--r--source/Commands/CommandObjectBreakpointCommand.cpp31
-rw-r--r--source/Commands/CommandObjectBreakpointCommand.h4
-rw-r--r--source/Commands/CommandObjectBugreport.cpp13
-rw-r--r--source/Commands/CommandObjectBugreport.h4
-rw-r--r--source/Commands/CommandObjectCommands.cpp82
-rw-r--r--source/Commands/CommandObjectCommands.h4
-rw-r--r--source/Commands/CommandObjectDisassemble.cpp36
-rw-r--r--source/Commands/CommandObjectDisassemble.h1
-rw-r--r--source/Commands/CommandObjectExpression.cpp104
-rw-r--r--source/Commands/CommandObjectExpression.h9
-rw-r--r--source/Commands/CommandObjectFrame.cpp414
-rw-r--r--source/Commands/CommandObjectGUI.cpp4
-rw-r--r--source/Commands/CommandObjectGUI.h4
-rw-r--r--source/Commands/CommandObjectHelp.cpp21
-rw-r--r--source/Commands/CommandObjectHelp.h4
-rw-r--r--source/Commands/CommandObjectLanguage.h4
-rw-r--r--source/Commands/CommandObjectLog.cpp29
-rw-r--r--source/Commands/CommandObjectLog.h4
-rw-r--r--source/Commands/CommandObjectMemory.cpp101
-rw-r--r--source/Commands/CommandObjectMemory.h4
-rw-r--r--source/Commands/CommandObjectMultiword.cpp11
-rw-r--r--source/Commands/CommandObjectPlatform.cpp124
-rw-r--r--source/Commands/CommandObjectPlatform.h4
-rw-r--r--source/Commands/CommandObjectPlugin.cpp7
-rw-r--r--source/Commands/CommandObjectPlugin.h4
-rw-r--r--source/Commands/CommandObjectProcess.cpp62
-rw-r--r--source/Commands/CommandObjectProcess.h4
-rw-r--r--source/Commands/CommandObjectQuit.cpp15
-rw-r--r--source/Commands/CommandObjectQuit.h4
-rw-r--r--source/Commands/CommandObjectRegister.cpp12
-rw-r--r--source/Commands/CommandObjectRegister.h4
-rw-r--r--source/Commands/CommandObjectReproducer.cpp97
-rw-r--r--source/Commands/CommandObjectReproducer.h31
-rw-r--r--source/Commands/CommandObjectSettings.cpp240
-rw-r--r--source/Commands/CommandObjectSettings.h4
-rw-r--r--source/Commands/CommandObjectSource.cpp52
-rw-r--r--source/Commands/CommandObjectSource.h4
-rw-r--r--source/Commands/CommandObjectTarget.cpp376
-rw-r--r--source/Commands/CommandObjectThread.cpp187
-rw-r--r--source/Commands/CommandObjectThread.h4
-rw-r--r--source/Commands/CommandObjectType.cpp132
-rw-r--r--source/Commands/CommandObjectType.h4
-rw-r--r--source/Commands/CommandObjectVersion.cpp4
-rw-r--r--source/Commands/CommandObjectVersion.h4
-rw-r--r--source/Commands/CommandObjectWatchpoint.cpp26
-rw-r--r--source/Commands/CommandObjectWatchpoint.h4
-rw-r--r--source/Commands/CommandObjectWatchpointCommand.cpp25
-rw-r--r--source/Commands/CommandObjectWatchpointCommand.h4
-rw-r--r--source/Core/Address.cpp59
-rw-r--r--source/Core/AddressRange.cpp12
-rw-r--r--source/Core/AddressResolverFileLine.cpp24
-rw-r--r--source/Core/AddressResolverName.cpp28
-rw-r--r--source/Core/CMakeLists.txt12
-rw-r--r--source/Core/Communication.cpp28
-rw-r--r--source/Core/Debugger.cpp224
-rw-r--r--source/Core/Disassembler.cpp56
-rw-r--r--source/Core/DumpDataExtractor.cpp34
-rw-r--r--source/Core/DumpRegisterValue.cpp2
-rw-r--r--source/Core/DynamicLoader.cpp24
-rw-r--r--source/Core/EmulateInstruction.cpp20
-rw-r--r--source/Core/FileLineResolver.cpp13
-rw-r--r--source/Core/FileSpecList.cpp6
-rw-r--r--source/Core/FormatEntity.cpp75
-rw-r--r--source/Core/Highlighter.cpp81
-rw-r--r--source/Core/IOHandler.cpp88
-rw-r--r--source/Core/Mangled.cpp186
-rw-r--r--source/Core/Module.cpp196
-rw-r--r--source/Core/ModuleList.cpp108
-rw-r--r--source/Core/Opcode.cpp33
-rw-r--r--source/Core/PluginManager.cpp62
-rw-r--r--source/Core/RichManglingContext.cpp175
-rw-r--r--source/Core/SearchFilter.cpp119
-rw-r--r--source/Core/Section.cpp28
-rw-r--r--source/Core/SourceManager.cpp177
-rw-r--r--source/Core/StreamAsynchronousIO.cpp4
-rw-r--r--source/Core/StreamFile.cpp19
-rw-r--r--source/Core/UserSettingsController.cpp2
-rw-r--r--source/Core/Value.cpp62
-rw-r--r--source/Core/ValueObject.cpp153
-rw-r--r--source/Core/ValueObjectCast.cpp8
-rw-r--r--source/Core/ValueObjectChild.cpp36
-rw-r--r--source/Core/ValueObjectConstResult.cpp20
-rw-r--r--source/Core/ValueObjectConstResultChild.cpp7
-rw-r--r--source/Core/ValueObjectConstResultImpl.cpp24
-rw-r--r--source/Core/ValueObjectDynamicValue.cpp15
-rw-r--r--source/Core/ValueObjectList.cpp8
-rw-r--r--source/Core/ValueObjectMemory.cpp22
-rw-r--r--source/Core/ValueObjectRegister.cpp23
-rw-r--r--source/Core/ValueObjectSyntheticFilter.cpp16
-rw-r--r--source/Core/ValueObjectVariable.cpp31
-rw-r--r--source/DataFormatters/CXXFunctionPointer.cpp2
-rw-r--r--source/DataFormatters/DataVisualization.cpp8
-rw-r--r--source/DataFormatters/DumpValueObjectOptions.cpp6
-rw-r--r--source/DataFormatters/FormatCache.cpp4
-rw-r--r--source/DataFormatters/FormatClasses.cpp4
-rw-r--r--source/DataFormatters/FormatManager.cpp18
-rw-r--r--source/DataFormatters/FormattersHelpers.cpp4
-rw-r--r--source/DataFormatters/LanguageCategory.cpp4
-rw-r--r--source/DataFormatters/StringPrinter.cpp2
-rw-r--r--source/DataFormatters/TypeCategory.cpp9
-rw-r--r--source/DataFormatters/TypeCategoryMap.cpp7
-rw-r--r--source/DataFormatters/TypeFormat.cpp29
-rw-r--r--source/DataFormatters/TypeSummary.cpp6
-rw-r--r--source/DataFormatters/TypeSynthetic.cpp4
-rw-r--r--source/DataFormatters/TypeValidator.cpp4
-rw-r--r--source/DataFormatters/ValueObjectPrinter.cpp16
-rw-r--r--source/DataFormatters/VectorType.cpp22
-rw-r--r--source/Expression/DWARFExpression.cpp38
-rw-r--r--source/Expression/ExpressionSourceCode.cpp9
-rw-r--r--source/Expression/FunctionCaller.cpp6
-rw-r--r--source/Expression/IRDynamicChecks.cpp4
-rw-r--r--source/Expression/IRExecutionUnit.cpp21
-rw-r--r--source/Expression/IRInterpreter.cpp34
-rw-r--r--source/Expression/IRMemoryMap.cpp19
-rw-r--r--source/Expression/LLVMUserExpression.cpp3
-rw-r--r--source/Expression/Materializer.cpp21
-rw-r--r--source/Expression/REPL.cpp23
-rw-r--r--source/Expression/UtilityFunction.cpp2
-rw-r--r--source/Host/CMakeLists.txt13
-rw-r--r--source/Host/android/HostInfoAndroid.cpp21
-rw-r--r--source/Host/common/Editline.cpp58
-rw-r--r--source/Host/common/File.cpp132
-rw-r--r--source/Host/common/FileCache.cpp8
-rw-r--r--source/Host/common/FileSystem.cpp390
-rw-r--r--source/Host/common/Host.cpp19
-rw-r--r--source/Host/common/HostInfoBase.cpp7
-rw-r--r--source/Host/common/HostNativeThreadBase.cpp4
-rw-r--r--source/Host/common/HostThread.cpp2
-rw-r--r--source/Host/common/MainLoop.cpp4
-rw-r--r--source/Host/common/MonitoringProcessLauncher.cpp20
-rw-r--r--source/Host/common/NativeBreakpoint.cpp109
-rw-r--r--source/Host/common/NativeBreakpointList.cpp229
-rw-r--r--source/Host/common/NativeProcessProtocol.cpp312
-rw-r--r--source/Host/common/NativeRegisterContext.cpp2
-rw-r--r--source/Host/common/NativeThreadProtocol.cpp1
-rw-r--r--source/Host/common/ProcessRunLock.cpp2
-rw-r--r--source/Host/common/PseudoTerminal.cpp31
-rw-r--r--source/Host/common/SocketAddress.cpp4
-rw-r--r--source/Host/common/SoftwareBreakpoint.cpp350
-rw-r--r--source/Host/common/StringConvert.cpp4
-rw-r--r--source/Host/common/Symbols.cpp256
-rw-r--r--source/Host/common/TaskPool.cpp6
-rw-r--r--source/Host/common/XML.cpp11
-rw-r--r--source/Host/freebsd/Host.cpp10
-rw-r--r--source/Host/freebsd/HostInfoFreeBSD.cpp2
-rw-r--r--source/Host/linux/Host.cpp11
-rw-r--r--source/Host/linux/HostInfoLinux.cpp12
-rw-r--r--source/Host/macosx/Symbols.cpp72
-rw-r--r--source/Host/macosx/cfcpp/CFCMutableArray.cpp6
-rw-r--r--source/Host/macosx/cfcpp/CFCMutableSet.cpp6
-rw-r--r--source/Host/macosx/objcxx/Host.mm58
-rw-r--r--source/Host/macosx/objcxx/HostInfoMacOSX.mm20
-rw-r--r--source/Host/netbsd/Host.cpp6
-rw-r--r--source/Host/netbsd/HostInfoNetBSD.cpp2
-rw-r--r--source/Host/openbsd/Host.cpp4
-rw-r--r--source/Host/posix/ConnectionFileDescriptorPosix.cpp4
-rw-r--r--source/Host/posix/FileSystem.cpp9
-rw-r--r--source/Host/posix/HostInfoPosix.cpp4
-rw-r--r--source/Host/posix/HostProcessPosix.cpp2
-rw-r--r--source/Host/posix/PipePosix.cpp9
-rw-r--r--source/Host/posix/ProcessLauncherPosixFork.cpp2
-rw-r--r--source/Host/windows/FileSystem.cpp11
-rw-r--r--source/Host/windows/Host.cpp18
-rw-r--r--source/Host/windows/HostInfoWindows.cpp8
-rw-r--r--source/Host/windows/HostProcessWindows.cpp2
-rw-r--r--source/Host/windows/HostThreadWindows.cpp4
-rw-r--r--source/Host/windows/PipeWindows.cpp79
-rw-r--r--source/Host/windows/ProcessLauncherWindows.cpp3
-rw-r--r--source/Initialization/SystemInitializerCommon.cpp20
-rw-r--r--source/Initialization/SystemLifetimeManager.cpp10
-rw-r--r--source/Interpreter/CMakeLists.txt4
-rw-r--r--source/Interpreter/CommandAlias.cpp3
-rw-r--r--source/Interpreter/CommandInterpreter.cpp484
-rw-r--r--source/Interpreter/CommandObject.cpp15
-rw-r--r--source/Interpreter/CommandObjectRegexCommand.cpp4
-rw-r--r--source/Interpreter/CommandObjectScript.cpp4
-rw-r--r--source/Interpreter/CommandObjectScript.h4
-rw-r--r--source/Interpreter/CommandReturnObject.cpp4
-rw-r--r--source/Interpreter/OptionArgParser.cpp16
-rw-r--r--source/Interpreter/OptionGroupArchitecture.cpp4
-rw-r--r--source/Interpreter/OptionGroupBoolean.cpp6
-rw-r--r--source/Interpreter/OptionGroupFile.cpp8
-rw-r--r--source/Interpreter/OptionGroupFormat.cpp10
-rw-r--r--source/Interpreter/OptionGroupOutputFile.cpp10
-rw-r--r--source/Interpreter/OptionGroupPlatform.cpp22
-rw-r--r--source/Interpreter/OptionGroupString.cpp6
-rw-r--r--source/Interpreter/OptionGroupUInt64.cpp6
-rw-r--r--source/Interpreter/OptionGroupUUID.cpp8
-rw-r--r--source/Interpreter/OptionGroupValueObjectDisplay.cpp44
-rw-r--r--source/Interpreter/OptionGroupVariable.cpp33
-rw-r--r--source/Interpreter/OptionGroupWatchpoint.cpp26
-rw-r--r--source/Interpreter/OptionValue.cpp4
-rw-r--r--source/Interpreter/OptionValueArch.cpp6
-rw-r--r--source/Interpreter/OptionValueArgs.cpp4
-rw-r--r--source/Interpreter/OptionValueArray.cpp32
-rw-r--r--source/Interpreter/OptionValueBoolean.cpp4
-rw-r--r--source/Interpreter/OptionValueChar.cpp4
-rw-r--r--source/Interpreter/OptionValueDictionary.cpp20
-rw-r--r--source/Interpreter/OptionValueEnumeration.cpp24
-rw-r--r--source/Interpreter/OptionValueFileSpec.cpp12
-rw-r--r--source/Interpreter/OptionValueFileSpecLIst.cpp32
-rw-r--r--source/Interpreter/OptionValueFormat.cpp4
-rw-r--r--source/Interpreter/OptionValueFormatEntity.cpp24
-rw-r--r--source/Interpreter/OptionValueLanguage.cpp7
-rw-r--r--source/Interpreter/OptionValuePathMappings.cpp9
-rw-r--r--source/Interpreter/OptionValueProperties.cpp14
-rw-r--r--source/Interpreter/OptionValueRegex.cpp4
-rw-r--r--source/Interpreter/OptionValueSInt64.cpp4
-rw-r--r--source/Interpreter/OptionValueString.cpp4
-rw-r--r--source/Interpreter/OptionValueUInt64.cpp4
-rw-r--r--source/Interpreter/OptionValueUUID.cpp4
-rw-r--r--source/Interpreter/Options.cpp39
-rw-r--r--source/Interpreter/Property.cpp13
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp46
-rw-r--r--source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h4
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp218
-rw-r--r--source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h4
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp35
-rw-r--r--source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h4
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp86
-rw-r--r--source/Plugins/ABI/SysV-arm/ABISysV_arm.h4
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp73
-rw-r--r--source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h4
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp11
-rw-r--r--source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h4
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp57
-rw-r--r--source/Plugins/ABI/SysV-i386/ABISysV_i386.h4
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp21
-rw-r--r--source/Plugins/ABI/SysV-mips/ABISysV_mips.h4
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp68
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h4
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp94
-rw-r--r--source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h4
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp62
-rw-r--r--source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h4
-rw-r--r--source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp56
-rw-r--r--source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h8
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp87
-rw-r--r--source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h4
-rw-r--r--source/Plugins/Architecture/Arm/ArchitectureArm.cpp30
-rw-r--r--source/Plugins/Architecture/Arm/ArchitectureArm.h6
-rw-r--r--source/Plugins/Architecture/CMakeLists.txt1
-rw-r--r--source/Plugins/Architecture/Mips/ArchitectureMips.cpp241
-rw-r--r--source/Plugins/Architecture/Mips/ArchitectureMips.h52
-rw-r--r--source/Plugins/Architecture/Mips/CMakeLists.txt10
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp123
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h16
-rw-r--r--source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp97
-rw-r--r--source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h6
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp18
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h4
-rw-r--r--source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h5
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp47
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h6
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp47
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h13
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp19
-rw-r--r--source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h8
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp2
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h3
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp16
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h3
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp14
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h4
-rw-r--r--source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h4
-rw-r--r--source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp36
-rw-r--r--source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h4
-rw-r--r--source/Plugins/ExpressionParser/CMakeLists.txt1
-rw-r--r--source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp3
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp54
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp2
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h10
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h4
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp352
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h38
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h4
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp6
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h4
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangHost.cpp13
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp9
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h4
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp146
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUserExpression.h18
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp2
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h4
-rw-r--r--source/Plugins/ExpressionParser/Clang/IRForTarget.cpp42
-rw-r--r--source/Plugins/ExpressionParser/Go/CMakeLists.txt13
-rw-r--r--source/Plugins/ExpressionParser/Go/GoAST.h1977
-rw-r--r--source/Plugins/ExpressionParser/Go/GoLexer.cpp350
-rw-r--r--source/Plugins/ExpressionParser/Go/GoLexer.h181
-rw-r--r--source/Plugins/ExpressionParser/Go/GoParser.cpp886
-rw-r--r--source/Plugins/ExpressionParser/Go/GoParser.h145
-rw-r--r--source/Plugins/ExpressionParser/Go/GoUserExpression.cpp668
-rw-r--r--source/Plugins/ExpressionParser/Go/GoUserExpression.h94
-rw-r--r--source/Plugins/ExpressionParser/Go/gen_go_ast.py464
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp96
-rw-r--r--source/Plugins/Instruction/ARM/EmulationStateARM.cpp4
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp18
-rw-r--r--source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h4
-rw-r--r--source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp137
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp130
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h4
-rw-r--r--source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h4
-rw-r--r--source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.h4
-rw-r--r--source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h4
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp8
-rw-r--r--source/Plugins/JITLoader/GDB/JITLoaderGDB.h4
-rw-r--r--source/Plugins/Language/CMakeLists.txt4
-rw-r--r--source/Plugins/Language/CPlusPlus/BlockPointer.cpp6
-rw-r--r--source/Plugins/Language/CPlusPlus/CMakeLists.txt5
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp216
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h11
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h4
-rw-r--r--source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp14
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.cpp186
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxx.h31
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp19
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp15
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxList.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxMap.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp85
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp4
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp256
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVariant.h31
-rw-r--r--source/Plugins/Language/CPlusPlus/LibCxxVector.cpp38
-rw-r--r--source/Plugins/Language/CPlusPlus/LibStdcpp.cpp11
-rw-r--r--source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp99
-rw-r--r--source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h51
-rw-r--r--source/Plugins/Language/ClangCommon/CMakeLists.txt9
-rw-r--r--source/Plugins/Language/ClangCommon/ClangHighlighter.cpp237
-rw-r--r--source/Plugins/Language/ClangCommon/ClangHighlighter.h38
-rw-r--r--source/Plugins/Language/Go/CMakeLists.txt13
-rw-r--r--source/Plugins/Language/Go/GoFormatterFunctions.cpp152
-rw-r--r--source/Plugins/Language/Go/GoFormatterFunctions.h43
-rw-r--r--source/Plugins/Language/Go/GoLanguage.cpp127
-rw-r--r--source/Plugins/Language/Go/GoLanguage.h63
-rw-r--r--source/Plugins/Language/Java/CMakeLists.txt12
-rw-r--r--source/Plugins/Language/Java/JavaFormatterFunctions.cpp167
-rw-r--r--source/Plugins/Language/Java/JavaFormatterFunctions.h35
-rw-r--r--source/Plugins/Language/Java/JavaLanguage.cpp101
-rw-r--r--source/Plugins/Language/Java/JavaLanguage.h52
-rw-r--r--source/Plugins/Language/OCaml/CMakeLists.txt12
-rw-r--r--source/Plugins/Language/OCaml/OCamlLanguage.cpp63
-rw-r--r--source/Plugins/Language/OCaml/OCamlLanguage.h51
-rw-r--r--source/Plugins/Language/ObjC/CF.cpp2
-rw-r--r--source/Plugins/Language/ObjC/CMakeLists.txt1
-rw-r--r--source/Plugins/Language/ObjC/Cocoa.cpp67
-rw-r--r--source/Plugins/Language/ObjC/NSArray.cpp31
-rw-r--r--source/Plugins/Language/ObjC/NSDictionary.cpp4
-rw-r--r--source/Plugins/Language/ObjC/NSError.cpp4
-rw-r--r--source/Plugins/Language/ObjC/NSException.cpp158
-rw-r--r--source/Plugins/Language/ObjC/NSIndexPath.cpp10
-rw-r--r--source/Plugins/Language/ObjC/NSSet.cpp4
-rw-r--r--source/Plugins/Language/ObjC/NSString.cpp13
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.cpp20
-rw-r--r--source/Plugins/Language/ObjC/ObjCLanguage.h11
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt3
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp9
-rw-r--r--source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h11
-rw-r--r--source/Plugins/LanguageRuntime/CMakeLists.txt2
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp188
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h7
-rw-r--r--source/Plugins/LanguageRuntime/Go/CMakeLists.txt2
-rw-r--r--source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp215
-rw-r--r--source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h86
-rw-r--r--source/Plugins/LanguageRuntime/Java/CMakeLists.txt10
-rw-r--r--source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp157
-rw-r--r--source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h78
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp15
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h4
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp2
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h4
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp124
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h12
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp9
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h4
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp94
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h4
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp8
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h4
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h4
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp15
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h4
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp4
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h4
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp82
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h10
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp4
-rw-r--r--source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h4
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp9
-rw-r--r--source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h3
-rw-r--r--source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h6
-rw-r--r--source/Plugins/ObjectFile/Breakpad/CMakeLists.txt11
-rw-r--r--source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp315
-rw-r--r--source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h109
-rw-r--r--source/Plugins/ObjectFile/CMakeLists.txt3
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp29
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp735
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h28
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp16
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.h8
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp435
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h21
-rw-r--r--source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp441
-rw-r--r--source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h19
-rw-r--r--source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp2
-rw-r--r--source/Plugins/OperatingSystem/CMakeLists.txt1
-rw-r--r--source/Plugins/OperatingSystem/Go/CMakeLists.txt10
-rw-r--r--source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp498
-rw-r--r--source/Plugins/OperatingSystem/Go/OperatingSystemGo.h90
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp10
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.h4
-rw-r--r--source/Plugins/Platform/Android/AdbClient.cpp3
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.cpp12
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroid.h4
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp1
-rw-r--r--source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h4
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp14
-rw-r--r--source/Plugins/Platform/Kalimba/PlatformKalimba.cpp5
-rw-r--r--source/Plugins/Platform/Kalimba/PlatformKalimba.h4
-rw-r--r--source/Plugins/Platform/Linux/PlatformLinux.cpp16
-rw-r--r--source/Plugins/Platform/MacOSX/CMakeLists.txt1
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp9
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp37
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp37
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwin.cpp131
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwin.h21
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp127
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h31
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp23
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformMacOSX.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp186
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h73
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp6
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp6
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp99
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h12
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp8
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h4
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp37
-rw-r--r--source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h4
-rw-r--r--source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h4
-rw-r--r--source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm4
-rw-r--r--source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp16
-rw-r--r--source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp8
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp39
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h4
-rw-r--r--source/Plugins/Platform/Windows/PlatformWindows.cpp32
-rw-r--r--source/Plugins/Platform/Windows/PlatformWindows.h4
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp21
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h4
-rw-r--r--source/Plugins/Process/Darwin/NativeProcessDarwin.cpp13
-rw-r--r--source/Plugins/Process/Darwin/NativeProcessDarwin.h1
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp8
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.h2
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp31
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp7
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h3
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h3
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp2
-rw-r--r--source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp2
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.cpp325
-rw-r--r--source/Plugins/Process/Linux/NativeProcessLinux.h16
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp2
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp2
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp5
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp5
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp2
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp2
-rwxr-xr-xsource/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp2
-rw-r--r--source/Plugins/Process/Linux/NativeThreadLinux.cpp2
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp24
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h8
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp22
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h5
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h4
-rw-r--r--source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp4
-rw-r--r--source/Plugins/Process/NetBSD/CMakeLists.txt1
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp128
-rw-r--r--source/Plugins/Process/NetBSD/NativeProcessNetBSD.h15
-rw-r--r--source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp2
-rw-r--r--source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp4
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIXLog.h4
-rw-r--r--source/Plugins/Process/Utility/ARMUtils.h2
-rw-r--r--source/Plugins/Process/Utility/CMakeLists.txt1
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.cpp4
-rw-r--r--source/Plugins/Process/Utility/DynamicRegisterInfo.h4
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.cpp4
-rw-r--r--source/Plugins/Process/Utility/FreeBSDSignals.h1
-rw-r--r--source/Plugins/Process/Utility/GDBRemoteSignals.cpp3
-rw-r--r--source/Plugins/Process/Utility/GDBRemoteSignals.h4
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.h8
-rw-r--r--source/Plugins/Process/Utility/HistoryUnwind.h4
-rw-r--r--source/Plugins/Process/Utility/LinuxProcMaps.cpp113
-rw-r--r--source/Plugins/Process/Utility/LinuxProcMaps.h28
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.cpp3
-rw-r--r--source/Plugins/Process/Utility/LinuxSignals.h4
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.cpp3
-rw-r--r--source/Plugins/Process/Utility/MipsLinuxSignals.h4
-rw-r--r--source/Plugins/Process/Utility/NetBSDSignals.cpp4
-rw-r--r--source/Plugins/Process/Utility/NetBSDSignals.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp9
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp21
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp10
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_i386.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp12
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDummy.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextDummy.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.cpp2
-rw-r--r--source/Plugins/Process/Utility/RegisterContextHistory.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp180
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.h11
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp8
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMach_arm.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMach_arm.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMach_i386.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMach_i386.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMach_x86_64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMemory.cpp6
-rw-r--r--source/Plugins/Process/Utility/RegisterContextMemory.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp6
-rw-r--r--source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContextThreadMemory.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterContext_x86.h2
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_arm64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_i386.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_mips64.h4
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_ppc64.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_ppc64le.h1
-rw-r--r--source/Plugins/Process/Utility/RegisterInfos_s390x.h4
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.cpp57
-rw-r--r--source/Plugins/Process/Utility/StopInfoMachException.h4
-rw-r--r--source/Plugins/Process/Utility/ThreadMemory.h4
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp23
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.h4
-rw-r--r--source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp4
-rw-r--r--source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h4
-rw-r--r--source/Plugins/Process/Windows/Common/DebuggerThread.cpp16
-rw-r--r--source/Plugins/Process/Windows/Common/DebuggerThread.h2
-rw-r--r--source/Plugins/Process/Windows/Common/ForwardDecl.h2
-rw-r--r--source/Plugins/Process/Windows/Common/ProcessWindows.cpp104
-rw-r--r--source/Plugins/Process/Windows/Common/ProcessWindows.h4
-rw-r--r--source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp7
-rw-r--r--source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp2
-rw-r--r--source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp14
-rw-r--r--source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp2
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp59
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.h10
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp2
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp2
-rw-r--r--source/Plugins/Process/gdb-remote/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp212
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h98
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp57
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h2
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp143
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h156
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp204
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h83
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp3
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp51
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp18
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp18
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h4
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp12
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h4
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp215
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h12
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h4
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp13
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h4
-rw-r--r--source/Plugins/Process/mach-core/ProcessMachCore.cpp78
-rw-r--r--source/Plugins/Process/mach-core/ProcessMachCore.h4
-rw-r--r--source/Plugins/Process/mach-core/ThreadMachCore.cpp4
-rw-r--r--source/Plugins/Process/mach-core/ThreadMachCore.h4
-rw-r--r--source/Plugins/Process/minidump/CMakeLists.txt2
-rw-r--r--source/Plugins/Process/minidump/MinidumpParser.cpp354
-rw-r--r--source/Plugins/Process/minidump/MinidumpParser.h24
-rw-r--r--source/Plugins/Process/minidump/MinidumpTypes.cpp4
-rw-r--r--source/Plugins/Process/minidump/MinidumpTypes.h65
-rw-r--r--source/Plugins/Process/minidump/ProcessMinidump.cpp334
-rw-r--r--source/Plugins/Process/minidump/ProcessMinidump.h14
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp532
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h93
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp834
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h83
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp2
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h2
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp2
-rw-r--r--source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h2
-rw-r--r--source/Plugins/Process/minidump/ThreadMinidump.cpp28
-rw-r--r--source/Plugins/Process/minidump/ThreadMinidump.h4
-rw-r--r--source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h4
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp11
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h4
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp177
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h45
-rw-r--r--source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp42
-rw-r--r--source/Plugins/SymbolFile/Breakpad/CMakeLists.txt12
-rw-r--r--source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp223
-rw-r--r--source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h146
-rw-r--r--source/Plugins/SymbolFile/CMakeLists.txt2
-rw-r--r--source/Plugins/SymbolFile/DWARF/CMakeLists.txt3
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParser.h12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp308
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h37
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp772
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h84
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp510
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h81
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp210
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h59
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h17
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFAttribute.h11
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp31
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDIE.h5
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h1
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp140
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h28
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp146
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h18
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp178
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h46
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFDefines.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp248
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h8
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp108
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFUnit.h11
-rw-r--r--source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp10
-rw-r--r--source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp397
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h96
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp182
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h55
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp39
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h10
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp9
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h4
-rw-r--r--source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp4
-rw-r--r--source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h4
-rw-r--r--source/Plugins/SymbolFile/NativePDB/CMakeLists.txt21
-rw-r--r--source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp217
-rw-r--r--source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h95
-rw-r--r--source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp673
-rw-r--r--source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h42
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp1348
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h144
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp200
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbIndex.h162
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp161
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbSymUid.h126
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp750
-rw-r--r--source/Plugins/SymbolFile/NativePDB/PdbUtil.h159
-rw-r--r--source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp1571
-rw-r--r--source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h245
-rw-r--r--source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp191
-rw-r--r--source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h75
-rw-r--r--source/Plugins/SymbolFile/PDB/CMakeLists.txt1
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBASTParser.cpp1005
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBASTParser.h67
-rw-r--r--source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp658
-rw-r--r--source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp591
-rw-r--r--source/Plugins/SymbolFile/PDB/SymbolFilePDB.h69
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp38
-rw-r--r--source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h33
-rw-r--r--source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp9
-rw-r--r--source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h4
-rw-r--r--source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp26
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp7
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h4
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp7
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h4
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp7
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h4
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp7
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h4
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp9
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h3
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp2
-rw-r--r--source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h6
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp8
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h4
-rw-r--r--source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp344
-rw-r--r--source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h7
-rw-r--r--source/Symbol/ArmUnwindInfo.cpp2
-rw-r--r--source/Symbol/Block.cpp27
-rw-r--r--source/Symbol/CMakeLists.txt6
-rw-r--r--source/Symbol/ClangASTContext.cpp751
-rw-r--r--source/Symbol/ClangASTImporter.cpp4
-rw-r--r--source/Symbol/ClangExternalASTSourceCallbacks.cpp3
-rw-r--r--source/Symbol/ClangUtil.cpp8
-rw-r--r--source/Symbol/CompactUnwindInfo.cpp42
-rw-r--r--source/Symbol/CompileUnit.cpp87
-rw-r--r--source/Symbol/CompilerType.cpp104
-rw-r--r--source/Symbol/DWARFCallFrameInfo.cpp13
-rw-r--r--source/Symbol/FuncUnwinders.cpp5
-rw-r--r--source/Symbol/Function.cpp117
-rw-r--r--source/Symbol/GoASTContext.cpp1444
-rw-r--r--source/Symbol/JavaASTContext.cpp1324
-rw-r--r--source/Symbol/LineEntry.cpp14
-rw-r--r--source/Symbol/OCamlASTContext.cpp670
-rw-r--r--source/Symbol/ObjectFile.cpp94
-rw-r--r--source/Symbol/Symbol.cpp2
-rw-r--r--source/Symbol/SymbolContext.cpp92
-rw-r--r--source/Symbol/SymbolFile.cpp29
-rw-r--r--source/Symbol/SymbolVendor.cpp89
-rw-r--r--source/Symbol/Symtab.cpp254
-rw-r--r--source/Symbol/Type.cpp29
-rw-r--r--source/Symbol/TypeList.cpp7
-rw-r--r--source/Symbol/TypeMap.cpp7
-rw-r--r--source/Symbol/TypeSystem.cpp6
-rw-r--r--source/Symbol/UnwindPlan.cpp36
-rw-r--r--source/Symbol/UnwindTable.cpp4
-rw-r--r--source/Symbol/Variable.cpp22
-rw-r--r--source/Target/ABI.cpp4
-rw-r--r--source/Target/CMakeLists.txt1
-rw-r--r--source/Target/CPPLanguageRuntime.cpp304
-rw-r--r--source/Target/ExecutionContext.cpp6
-rw-r--r--source/Target/InstrumentationRuntime.cpp4
-rw-r--r--source/Target/JITLoader.cpp4
-rw-r--r--source/Target/Language.cpp35
-rw-r--r--source/Target/LanguageRuntime.cpp8
-rw-r--r--source/Target/Memory.cpp6
-rw-r--r--source/Target/MemoryHistory.cpp4
-rw-r--r--source/Target/ModuleCache.cpp20
-rw-r--r--source/Target/ObjCLanguageRuntime.cpp3
-rw-r--r--source/Target/OperatingSystem.cpp4
-rw-r--r--source/Target/PathMappingList.cpp22
-rw-r--r--source/Target/Platform.cpp160
-rw-r--r--source/Target/Process.cpp125
-rw-r--r--source/Target/ProcessInfo.cpp16
-rw-r--r--source/Target/ProcessLaunchInfo.cpp162
-rw-r--r--source/Target/Queue.cpp4
-rw-r--r--source/Target/QueueItem.cpp2
-rw-r--r--source/Target/RegisterContext.cpp8
-rw-r--r--source/Target/RegisterNumber.cpp17
-rw-r--r--source/Target/SectionLoadHistory.cpp4
-rw-r--r--source/Target/SectionLoadList.cpp4
-rw-r--r--source/Target/StackFrame.cpp102
-rw-r--r--source/Target/StackFrameList.cpp768
-rw-r--r--source/Target/StackFrameRecognizer.cpp191
-rw-r--r--source/Target/StackID.cpp4
-rw-r--r--source/Target/StopInfo.cpp44
-rw-r--r--source/Target/SystemRuntime.cpp4
-rw-r--r--source/Target/Target.cpp708
-rw-r--r--source/Target/TargetList.cpp46
-rw-r--r--source/Target/Thread.cpp193
-rw-r--r--source/Target/ThreadList.cpp6
-rw-r--r--source/Target/ThreadPlan.cpp7
-rw-r--r--source/Target/ThreadPlanBase.cpp9
-rw-r--r--source/Target/ThreadPlanCallFunction.cpp4
-rw-r--r--source/Target/ThreadPlanCallFunctionUsingABI.cpp4
-rw-r--r--source/Target/ThreadPlanCallOnFunctionExit.cpp7
-rw-r--r--source/Target/ThreadPlanCallUserExpression.cpp4
-rw-r--r--source/Target/ThreadPlanPython.cpp24
-rw-r--r--source/Target/ThreadPlanRunToAddress.cpp14
-rw-r--r--source/Target/ThreadPlanShouldStopHere.cpp31
-rw-r--r--source/Target/ThreadPlanStepInRange.cpp36
-rw-r--r--source/Target/ThreadPlanStepInstruction.cpp17
-rw-r--r--source/Target/ThreadPlanStepOut.cpp61
-rw-r--r--source/Target/ThreadPlanStepOverBreakpoint.cpp4
-rw-r--r--source/Target/ThreadPlanStepOverRange.cpp41
-rw-r--r--source/Target/ThreadPlanStepRange.cpp22
-rw-r--r--source/Target/ThreadPlanStepThrough.cpp39
-rw-r--r--source/Target/ThreadPlanStepUntil.cpp19
-rw-r--r--source/Target/ThreadPlanTracer.cpp4
-rw-r--r--source/Target/ThreadSpec.cpp4
-rw-r--r--source/Target/UnixSignals.cpp6
-rw-r--r--source/Target/UnwindAssembly.cpp4
-rw-r--r--source/Utility/ArchSpec.cpp42
-rw-r--r--source/Utility/Broadcaster.cpp (renamed from source/Core/Broadcaster.cpp)20
-rw-r--r--source/Utility/CMakeLists.txt15
-rw-r--r--source/Utility/CompletionRequest.cpp43
-rw-r--r--source/Utility/ConstString.cpp66
-rw-r--r--source/Utility/DataBufferHeap.cpp4
-rw-r--r--source/Utility/DataBufferLLVM.cpp32
-rw-r--r--source/Utility/DataEncoder.cpp2
-rw-r--r--source/Utility/DataExtractor.cpp20
-rw-r--r--source/Utility/Event.cpp (renamed from source/Core/Event.cpp)10
-rw-r--r--source/Utility/FastDemangle.cpp2393
-rw-r--r--source/Utility/FileSpec.cpp220
-rw-r--r--source/Utility/JSON.cpp8
-rw-r--r--source/Utility/LLDBAssert.cpp20
-rw-r--r--source/Utility/Listener.cpp (renamed from source/Core/Listener.cpp)20
-rw-r--r--source/Utility/Log.cpp14
-rw-r--r--source/Utility/Logging.cpp4
-rw-r--r--source/Utility/Range.cpp76
-rw-r--r--source/Utility/RegisterValue.cpp (renamed from source/Core/RegisterValue.cpp)52
-rw-r--r--source/Utility/Reproducer.cpp225
-rw-r--r--source/Utility/Scalar.cpp (renamed from source/Core/Scalar.cpp)185
-rw-r--r--source/Utility/SelectHelper.cpp10
-rw-r--r--source/Utility/State.cpp (renamed from source/Core/State.cpp)6
-rw-r--r--source/Utility/Status.cpp43
-rw-r--r--source/Utility/Stream.cpp140
-rw-r--r--source/Utility/StreamGDBRemote.cpp4
-rw-r--r--source/Utility/StreamString.cpp7
-rw-r--r--source/Utility/StringExtractor.cpp4
-rw-r--r--source/Utility/StringExtractorGDBRemote.cpp2
-rw-r--r--source/Utility/StringList.cpp12
-rw-r--r--source/Utility/StructuredData.cpp19
-rw-r--r--source/Utility/TildeExpressionResolver.cpp12
-rw-r--r--source/Utility/Timer.cpp8
-rw-r--r--source/Utility/UUID.cpp7
-rw-r--r--source/Utility/VASprintf.cpp10
-rw-r--r--source/Utility/VMRange.cpp20
-rw-r--r--test/CMakeLists.txt22
-rw-r--r--test/use_lldb_suite.py4
-rw-r--r--third_party/Python/module/unittest2/unittest2/result.py4
-rw-r--r--tools/CMakeLists.txt15
-rw-r--r--tools/argdumper/CMakeLists.txt2
-rw-r--r--tools/darwin-debug/CMakeLists.txt2
-rw-r--r--tools/darwin-debug/darwin-debug.cpp2
-rw-r--r--tools/debugserver/CMakeLists.txt3
-rw-r--r--tools/debugserver/debugserver.xcodeproj/project.pbxproj95
-rw-r--r--tools/debugserver/source/CMakeLists.txt196
-rw-r--r--tools/debugserver/source/DNBRegisterInfo.cpp1
-rw-r--r--tools/debugserver/source/JSONGenerator.h6
-rw-r--r--tools/debugserver/source/MacOSX/Genealogy.cpp3
-rw-r--r--tools/debugserver/source/MacOSX/MachException.cpp55
-rw-r--r--tools/debugserver/source/MacOSX/MachProcess.mm16
-rw-r--r--tools/debugserver/source/MacOSX/MachTask.h4
-rw-r--r--tools/debugserver/source/MacOSX/MachThread.cpp4
-rw-r--r--tools/debugserver/source/MacOSX/MachVMRegion.cpp5
-rw-r--r--tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp7
-rw-r--r--tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp7
-rw-r--r--tools/debugserver/source/PThreadMutex.cpp4
-rw-r--r--tools/debugserver/source/RNBRemote.cpp141
-rw-r--r--tools/debugserver/source/RNBServices.cpp6
-rw-r--r--tools/debugserver/source/StdStringExtractor.cpp4
-rw-r--r--tools/debugserver/source/StdStringExtractor.h4
-rw-r--r--tools/debugserver/source/TTYState.h2
-rw-r--r--tools/debugserver/source/debugserver-entitlements.plist2
-rw-r--r--tools/debugserver/source/debugserver.cpp4
-rw-r--r--tools/debugserver/source/libdebugserver.cpp2
-rw-r--r--tools/driver/CMakeLists.txt23
-rw-r--r--tools/driver/Driver.cpp1109
-rw-r--r--tools/driver/Driver.h88
-rw-r--r--tools/driver/Options.td229
-rw-r--r--tools/driver/Platform.h3
-rw-r--r--tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp1
-rw-r--r--tools/intel-features/intel-pt/Decoder.cpp2
-rw-r--r--tools/intel-features/intel-pt/Decoder.h1
-rw-r--r--tools/intel-features/intel-pt/PTDecoder.cpp1
-rw-r--r--tools/intel-features/intel-pt/PTDecoder.h1
-rw-r--r--tools/lldb-mi/CMakeLists.txt4
-rw-r--r--tools/lldb-mi/MICmdArgSet.h4
-rw-r--r--tools/lldb-mi/MICmdArgValBase.cpp4
-rw-r--r--tools/lldb-mi/MICmdArgValBase.h4
-rw-r--r--tools/lldb-mi/MICmdArgValConsume.cpp2
-rw-r--r--tools/lldb-mi/MICmdArgValFile.cpp5
-rw-r--r--tools/lldb-mi/MICmdArgValOptionLong.cpp5
-rw-r--r--tools/lldb-mi/MICmdArgValString.cpp7
-rw-r--r--tools/lldb-mi/MICmdArgValThreadGrp.cpp5
-rw-r--r--tools/lldb-mi/MICmdBase.h6
-rw-r--r--tools/lldb-mi/MICmdCmdBreak.cpp9
-rw-r--r--tools/lldb-mi/MICmdCmdData.cpp4
-rw-r--r--tools/lldb-mi/MICmdCmdGdbInfo.cpp2
-rw-r--r--tools/lldb-mi/MICmdCmdGdbSet.cpp53
-rw-r--r--tools/lldb-mi/MICmdCmdGdbSet.h1
-rw-r--r--tools/lldb-mi/MICmdCmdGdbShow.cpp40
-rw-r--r--tools/lldb-mi/MICmdCmdGdbShow.h1
-rw-r--r--tools/lldb-mi/MICmdCmdTarget.cpp59
-rw-r--r--tools/lldb-mi/MICmdFactory.cpp5
-rw-r--r--tools/lldb-mi/MICmnBase.cpp2
-rw-r--r--tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp8
-rw-r--r--tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp30
-rw-r--r--tools/lldb-mi/MICmnLog.cpp5
-rw-r--r--tools/lldb-mi/MICmnResources.cpp10
-rw-r--r--tools/lldb-mi/MICmnResources.h3
-rw-r--r--tools/lldb-mi/MICmnStreamStdin.cpp2
-rw-r--r--tools/lldb-mi/MIDataTypes.h2
-rw-r--r--tools/lldb-mi/MIDriver.cpp17
-rw-r--r--tools/lldb-mi/MIDriverMain.cpp6
-rw-r--r--tools/lldb-mi/MIDriverMgr.cpp20
-rw-r--r--tools/lldb-mi/MIUtilDebug.cpp19
-rw-r--r--tools/lldb-mi/MIUtilDebug.h1
-rw-r--r--tools/lldb-mi/MIUtilFileStd.cpp2
-rw-r--r--tools/lldb-mi/MIUtilMapIdToVariant.cpp5
-rw-r--r--tools/lldb-mi/MIUtilString.cpp32
-rw-r--r--tools/lldb-server/CMakeLists.txt2
-rw-r--r--tools/lldb-server/SystemInitializerLLGS.cpp9
-rw-r--r--tools/lldb-server/SystemInitializerLLGS.h4
-rw-r--r--tools/lldb-server/lldb-gdbserver.cpp31
-rw-r--r--tools/lldb-server/lldb-platform.cpp7
-rw-r--r--tools/lldb-server/lldb-server.cpp5
-rw-r--r--tools/lldb-test/FormatUtil.cpp47
-rw-r--r--tools/lldb-test/FormatUtil.h27
-rw-r--r--tools/lldb-test/SystemInitializerTest.cpp40
-rw-r--r--tools/lldb-test/SystemInitializerTest.h2
-rw-r--r--tools/lldb-test/lldb-test.cpp290
-rw-r--r--tools/lldb-vscode/BreakpointBase.cpp37
-rw-r--r--tools/lldb-vscode/BreakpointBase.h44
-rw-r--r--tools/lldb-vscode/CMakeLists.txt34
-rw-r--r--tools/lldb-vscode/ExceptionBreakpoint.cpp32
-rw-r--r--tools/lldb-vscode/ExceptionBreakpoint.h38
-rw-r--r--tools/lldb-vscode/FunctionBreakpoint.cpp28
-rw-r--r--tools/lldb-vscode/FunctionBreakpoint.h29
-rw-r--r--tools/lldb-vscode/JSONUtils.cpp892
-rw-r--r--tools/lldb-vscode/JSONUtils.h438
-rw-r--r--tools/lldb-vscode/LLDBUtils.cpp98
-rw-r--r--tools/lldb-vscode/LLDBUtils.h170
-rw-r--r--tools/lldb-vscode/README.md195
-rw-r--r--tools/lldb-vscode/SourceBreakpoint.cpp27
-rw-r--r--tools/lldb-vscode/SourceBreakpoint.h39
-rw-r--r--tools/lldb-vscode/SourceReference.h33
-rw-r--r--tools/lldb-vscode/VSCode.cpp349
-rw-r--r--tools/lldb-vscode/VSCode.h146
-rw-r--r--tools/lldb-vscode/VSCodeForward.h47
-rw-r--r--tools/lldb-vscode/lldb-vscode-Info.plist21
-rw-r--r--tools/lldb-vscode/lldb-vscode.cpp2706
-rw-r--r--tools/lldb-vscode/package.json242
-rw-r--r--unittests/CMakeLists.txt1
-rw-r--r--unittests/Core/CMakeLists.txt22
-rw-r--r--unittests/Core/Inputs/mangled-function-names.yaml116
-rw-r--r--unittests/Core/MangledTest.cpp137
-rw-r--r--unittests/Core/RangeMapTest.cpp55
-rw-r--r--unittests/Core/RangeTest.cpp330
-rw-r--r--unittests/Core/RichManglingContextTest.cpp140
-rw-r--r--unittests/Core/StateTest.cpp21
-rw-r--r--unittests/Disassembler/CMakeLists.txt13
-rw-r--r--unittests/Disassembler/TestArmv7Disassembly.cpp93
-rw-r--r--unittests/Editline/EditlineTest.cpp5
-rw-r--r--unittests/Expression/CMakeLists.txt2
-rw-r--r--unittests/Expression/ClangParserTest.cpp13
-rw-r--r--unittests/Expression/GoParserTest.cpp273
-rw-r--r--unittests/Host/CMakeLists.txt3
-rw-r--r--unittests/Host/FileSystemTest.cpp271
-rw-r--r--unittests/Host/HostInfoTest.cpp21
-rw-r--r--unittests/Host/NativeProcessProtocolTest.cpp225
-rw-r--r--unittests/Host/SocketTest.cpp19
-rw-r--r--unittests/Host/SymbolsTest.cpp30
-rw-r--r--unittests/Host/linux/HostTest.cpp11
-rw-r--r--unittests/Interpreter/TestCompletion.cpp95
-rw-r--r--unittests/Language/CMakeLists.txt1
-rw-r--r--unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp11
-rw-r--r--unittests/Language/Highlighting/CMakeLists.txt8
-rw-r--r--unittests/Language/Highlighting/HighlighterTest.cpp293
-rw-r--r--unittests/ObjectFile/ELF/CMakeLists.txt1
-rw-r--r--unittests/ObjectFile/ELF/Inputs/debug-info-relocations.pcm.yaml183
-rw-r--r--unittests/ObjectFile/ELF/TestObjectFileELF.cpp78
-rw-r--r--unittests/Platform/PlatformDarwinTest.cpp25
-rw-r--r--unittests/Process/Linux/ProcessorTraceTest.cpp2
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp3
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp13
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp3
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp37
-rw-r--r--unittests/Process/gdb-remote/GDBRemoteTestUtils.h4
-rw-r--r--unittests/Process/minidump/CMakeLists.txt24
-rw-r--r--unittests/Process/minidump/Inputs/dump-content.dmpbin0 -> 664 bytes
-rw-r--r--unittests/Process/minidump/Inputs/modules-dup-min-addr.dmpbin0 -> 420 bytes
-rw-r--r--unittests/Process/minidump/Inputs/modules-order.dmpbin0 -> 420 bytes
-rw-r--r--unittests/Process/minidump/Inputs/regions-linux-map.dmpbin0 -> 1379 bytes
-rw-r--r--unittests/Process/minidump/Inputs/regions-memlist.dmpbin0 -> 252 bytes
-rw-r--r--unittests/Process/minidump/Inputs/regions-memlist64.dmpbin0 -> 260 bytes
-rw-r--r--unittests/Process/minidump/MinidumpParserTest.cpp175
-rw-r--r--unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp6
-rw-r--r--unittests/ScriptInterpreter/Python/PythonTestSuite.cpp6
-rw-r--r--unittests/Symbol/TestClangASTContext.cpp48
-rw-r--r--unittests/Symbol/TestDWARFCallFrameInfo.cpp12
-rw-r--r--unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp17
-rw-r--r--unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h2
-rw-r--r--unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp9
-rw-r--r--unittests/SymbolFile/PDB/Inputs/test-pdb-types.exebin7168 -> 8192 bytes
-rw-r--r--unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdbbin143360 -> 102400 bytes
-rw-r--r--unittests/SymbolFile/PDB/Inputs/test-pdb.h2
-rw-r--r--unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp181
-rw-r--r--unittests/Target/ModuleCacheTest.cpp18
-rw-r--r--unittests/Target/PathMappingListTest.cpp5
-rw-r--r--unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp65
-rw-r--r--unittests/Utility/ArchSpecTest.cpp62
-rw-r--r--unittests/Utility/BroadcasterTest.cpp (renamed from unittests/Core/BroadcasterTest.cpp)10
-rw-r--r--unittests/Utility/CMakeLists.txt12
-rw-r--r--unittests/Utility/CompletionRequestTest.cpp100
-rw-r--r--unittests/Utility/ConstStringTest.cpp74
-rw-r--r--unittests/Utility/DataExtractorTest.cpp (renamed from unittests/Core/DataExtractorTest.cpp)0
-rw-r--r--unittests/Utility/EventTest.cpp (renamed from unittests/Core/EventTest.cpp)2
-rw-r--r--unittests/Utility/FileSpecTest.cpp83
-rw-r--r--unittests/Utility/ListenerTest.cpp (renamed from unittests/Core/ListenerTest.cpp)8
-rw-r--r--unittests/Utility/PredicateTest.cpp (renamed from unittests/Host/PredicateTest.cpp)2
-rw-r--r--unittests/Utility/RegisterValueTest.cpp23
-rw-r--r--unittests/Utility/ReproducerTest.cpp134
-rw-r--r--unittests/Utility/ScalarTest.cpp (renamed from unittests/Core/ScalarTest.cpp)48
-rw-r--r--unittests/Utility/StateTest.cpp31
-rw-r--r--unittests/Utility/StatusTest.cpp23
-rw-r--r--unittests/Utility/StreamTeeTest.cpp4
-rw-r--r--unittests/Utility/StreamTest.cpp130
-rw-r--r--unittests/Utility/StringLexerTest.cpp141
-rw-r--r--unittests/Utility/StringListTest.cpp512
-rw-r--r--unittests/Utility/StructuredDataTest.cpp4
-rw-r--r--unittests/tools/CMakeLists.txt2
-rw-r--r--unittests/tools/lldb-server/CMakeLists.txt2
-rw-r--r--unittests/tools/lldb-server/tests/MessageObjects.h2
-rw-r--r--unittests/tools/lldb-server/tests/TestBase.h6
-rw-r--r--utils/sync-source/README.txt2
-rwxr-xr-xwww/build.html25
-rwxr-xr-xwww/download.html19
-rwxr-xr-xwww/python-reference.html259
-rw-r--r--www/python_reference/epydoc.css2
-rwxr-xr-xwww/symbols.html27
2046 files changed, 64725 insertions, 37735 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 00ddcdc1488f..cdf22c4b0fc8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,15 +18,6 @@ else()
add_definitions( -DLLDB_CONFIGURATION_RELEASE )
endif()
-if (CMAKE_SYSTEM_NAME MATCHES "Windows|Android")
- set(LLDB_DEFAULT_DISABLE_LIBEDIT 1)
-else()
- set(LLDB_DEFAULT_DISABLE_LIBEDIT 0)
-endif ()
-
-# We need libedit support to go down both the source and
-# the scripts directories.
-set(LLDB_DISABLE_LIBEDIT ${LLDB_DEFAULT_DISABLE_LIBEDIT} CACHE BOOL "Disables the use of editline.")
if (LLDB_DISABLE_LIBEDIT)
add_definitions( -DLLDB_DISABLE_LIBEDIT )
else()
@@ -37,65 +28,24 @@ if(APPLE)
add_definitions(-DLLDB_USE_OS_LOG)
endif()
-# lldb-suite is a dummy target that encompasses all the necessary tools and
-# libraries for building a fully-functioning liblldb.
-add_custom_target(lldb-suite)
-set(LLDB_SUITE_TARGET lldb-suite)
-
-option(LLDB_BUILD_FRAMEWORK "Build the Darwin LLDB.framework" Off)
-if(LLDB_BUILD_FRAMEWORK)
- if (CMAKE_VERSION VERSION_LESS 3.7)
- message(FATAL_ERROR "LLDB_BUILD_FRAMEWORK is not supported on CMake < 3.7")
- endif()
- if (NOT APPLE)
- message(FATAL_ERROR "LLDB.framework can only be generated when targeting Apple platforms")
- endif()
-
- # These are used to fill out LLDB-Info.plist. These are relevant when building
- # the framework, and must be defined before building liblldb.
- set(PRODUCT_NAME "LLDB")
- set(EXECUTABLE_NAME "LLDB")
- set(CURRENT_PROJECT_VERSION "360.99.0")
- set(LLDB_SUITE_TARGET lldb-framework)
-
- set(LLDB_FRAMEWORK_DIR
- ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${LLDB_FRAMEWORK_INSTALL_DIR})
-endif()
-
add_subdirectory(docs)
if (NOT LLDB_DISABLE_PYTHON)
- if(LLDB_USE_SYSTEM_SIX)
- set(SIX_EXTRA_ARGS "--useSystemSix")
- endif()
-
- set(LLDB_PYTHON_TARGET_DIR ${LLDB_BINARY_DIR}/scripts)
- set(LLDB_WRAP_PYTHON ${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp)
- if(LLDB_BUILD_FRAMEWORK)
- set(LLDB_PYTHON_TARGET_DIR ${LLDB_FRAMEWORK_DIR})
- set(LLDB_WRAP_PYTHON ${LLDB_PYTHON_TARGET_DIR}/LLDBWrapPython.cpp)
- else()
- # Don't set -m when building the framework.
- set(FINISH_EXTRA_ARGS "-m")
- endif()
-
-
add_subdirectory(scripts)
endif ()
-
add_subdirectory(source)
add_subdirectory(tools)
-option(LLDB_INCLUDE_TESTS "Generate build targets for the LLDB unit tests."
- ${LLVM_INCLUDE_TESTS})
+option(LLDB_INCLUDE_TESTS "Generate build targets for the LLDB unit tests." ${LLVM_INCLUDE_TESTS})
option(LLDB_TEST_USE_CUSTOM_C_COMPILER "Use the C compiler provided via LLDB_TEST_C_COMPILER for building test inferiors (instead of the just-built compiler). Defaults to OFF." OFF)
option(LLDB_TEST_USE_CUSTOM_CXX_COMPILER "Use the C++ compiler provided via LLDB_TEST_CXX_COMPILER for building test inferiors (instead of the just-built compiler). Defaults to OFF." OFF)
if(LLDB_INCLUDE_TESTS)
- # The difference between the following two paths is significant. The path to
- # LLDB will point to LLDB's binary directory, while the other will point to
- # LLVM's binary directory in case the two differ.
+ # Set the path to the default lldb test executable.
set(LLDB_DEFAULT_TEST_EXECUTABLE "${LLVM_RUNTIME_OUTPUT_INTDIR}/lldb${CMAKE_EXECUTABLE_SUFFIX}")
+
+ # Set the paths to default llvm tools.
set(LLDB_DEFAULT_TEST_DSYMUTIL "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/dsymutil${CMAKE_EXECUTABLE_SUFFIX}")
+ set(LLDB_DEFAULT_TEST_FILECHECK "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/FileCheck${CMAKE_EXECUTABLE_SUFFIX}")
if (NOT LLDB_TEST_USE_CUSTOM_C_COMPILER AND TARGET clang)
set(LLDB_DEFAULT_TEST_C_COMPILER "${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}")
@@ -113,6 +63,7 @@ if(LLDB_INCLUDE_TESTS)
set(LLDB_TEST_C_COMPILER "${LLDB_DEFAULT_TEST_C_COMPILER}" CACHE PATH "C Compiler to use for building LLDB test inferiors")
set(LLDB_TEST_CXX_COMPILER "${LLDB_DEFAULT_TEST_CXX_COMPILER}" CACHE PATH "C++ Compiler to use for building LLDB test inferiors")
set(LLDB_TEST_DSYMUTIL "${LLDB_DEFAULT_TEST_DSYMUTIL}" CACHE PATH "dsymutil used for generating dSYM bundles")
+ set(LLDB_TEST_FILECHECK "${LLDB_DEFAULT_TEST_FILECHECK}" CACHE PATH "FileCheck used for testing purposes")
if (("${LLDB_TEST_C_COMPILER}" STREQUAL "") OR
("${LLDB_TEST_CXX_COMPILER}" STREQUAL ""))
@@ -131,9 +82,7 @@ if(LLDB_INCLUDE_TESTS)
endif()
if(TARGET debugserver)
- if(NOT CMAKE_HOST_APPLE OR LLDB_CODESIGN_IDENTITY)
- list(APPEND LLDB_TEST_DEPS debugserver)
- endif()
+ list(APPEND LLDB_TEST_DEPS debugserver)
endif()
if(TARGET lldb-mi)
@@ -148,8 +97,23 @@ if(LLDB_INCLUDE_TESTS)
list(APPEND LLDB_TEST_DEPS liblldb)
endif()
+ # Add dependencies if we test with the in-tree clang.
+ # This works with standalone builds as they import the clang target.
if(TARGET clang)
list(APPEND LLDB_TEST_DEPS clang)
+ if(APPLE)
+ # If we build clang, we should build libcxx.
+ # FIXME: Standalone builds should import the cxx target as well.
+ if(LLDB_BUILT_STANDALONE)
+ # For now check that the include directory exists.
+ set(cxx_dir "${LLVM_BINARY_DIR}/include/c++")
+ if(NOT EXISTS ${cxx_dir})
+ message(WARNING "LLDB test suite requires libc++ in llvm/projects/libcxx or an existing build symlinked to ${cxx_dir}")
+ endif()
+ else()
+ list(APPEND LLDB_TEST_DEPS cxx)
+ endif()
+ endif()
endif()
if(TARGET dsymutil)
@@ -162,46 +126,44 @@ if(LLDB_INCLUDE_TESTS)
add_subdirectory(utils/lldb-dotest)
endif()
-if (LLDB_BUILD_FRAMEWORK)
- add_custom_target(lldb-framework)
- include(LLDBFramework)
-endif()
-
if (NOT LLDB_DISABLE_PYTHON)
+ if(NOT LLDB_BUILD_FRAMEWORK)
+ set(use_python_wrapper_from_src_dir -m)
+ endif()
+ if(LLDB_USE_SYSTEM_SIX)
+ set(use_six_py_from_system --useSystemSix)
+ endif()
+ get_target_property(lldb_scripts_dir swig_wrapper BINARY_DIR)
+ get_target_property(liblldb_build_dir liblldb LIBRARY_OUTPUT_DIRECTORY)
+
# Add a Post-Build Event to copy over Python files and create the symlink
# to liblldb.so for the Python API(hardlink on Windows)
add_custom_target(finish_swig ALL
COMMAND
- ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/finishSwigWrapperClasses.py
+ ${PYTHON_EXECUTABLE} ${LLDB_SOURCE_DIR}/scripts/finishSwigWrapperClasses.py
--srcRoot=${LLDB_SOURCE_DIR}
- --targetDir=${LLDB_PYTHON_TARGET_DIR}
- --cfgBldDir=${LLDB_PYTHON_TARGET_DIR}
+ --targetDir=${liblldb_build_dir}
+ --cfgBldDir=${lldb_scripts_dir}
--prefix=${CMAKE_BINARY_DIR}
--cmakeBuildConfiguration=${CMAKE_CFG_INTDIR}
--lldbLibDir=lib${LLVM_LIBDIR_SUFFIX}
- ${SIX_EXTRA_ARGS}
- ${FINISH_EXTRA_ARGS}
+ ${use_python_wrapper_from_src_dir}
+ ${use_six_py_from_system}
VERBATIM
- DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/scripts/finishSwigWrapperClasses.py
- DEPENDS ${LLDB_PYTHON_TARGET_DIR}/lldb.py
+ DEPENDS ${LLDB_SOURCE_DIR}/scripts/finishSwigWrapperClasses.py
+ DEPENDS ${lldb_scripts_dir}/lldb.py
COMMENT "Python script sym-linking LLDB Python API")
- # We depend on liblldb and lldb-argdumper being built before we can do this step.
- add_dependencies(finish_swig ${LLDB_SUITE_TARGET})
-
- # If we build the readline module, we depend on that happening
- # first.
if (TARGET readline)
- add_dependencies(finish_swig readline)
+ set(readline_dep readline)
endif()
+ add_dependencies(finish_swig swig_wrapper liblldb lldb-argdumper ${readline_dep})
# Ensure we do the python post-build step when building lldb.
add_dependencies(lldb finish_swig)
- if (LLDB_BUILD_FRAMEWORK)
- # The target to install libLLDB needs to depend on finish_swig so that the
- # framework build properly copies over the Python files.
- add_dependencies(install-liblldb finish_swig)
+ if(LLDB_BUILD_FRAMEWORK)
+ add_dependencies(lldb-framework finish_swig)
endif()
# Add a Post-Build Event to copy the custom Python DLL to the lldb binaries dir so that Windows can find it when launching
diff --git a/cmake/modules/AddLLDB.cmake b/cmake/modules/AddLLDB.cmake
index 129a5ef7500d..f7cac3dad837 100644
--- a/cmake/modules/AddLLDB.cmake
+++ b/cmake/modules/AddLLDB.cmake
@@ -44,21 +44,32 @@ function(add_lldb_library name)
if (PARAM_OBJECT)
add_library(${name} ${libkind} ${srcs})
else()
- llvm_add_library(${name} ${libkind} ${srcs} LINK_LIBS
- ${PARAM_LINK_LIBS}
- DEPENDS ${PARAM_DEPENDS})
+ if(LLDB_NO_INSTALL_DEFAULT_RPATH)
+ set(pass_NO_INSTALL_RPATH NO_INSTALL_RPATH)
+ endif()
+
+ llvm_add_library(${name} ${libkind} ${srcs}
+ LINK_LIBS ${PARAM_LINK_LIBS}
+ DEPENDS ${PARAM_DEPENDS}
+ ${pass_NO_INSTALL_RPATH}
+ )
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "liblldb")
if (PARAM_SHARED)
- set(out_dir lib${LLVM_LIBDIR_SUFFIX})
if(${name} STREQUAL "liblldb" AND LLDB_BUILD_FRAMEWORK)
- set(out_dir ${LLDB_FRAMEWORK_INSTALL_DIR})
+ if(LLDB_FRAMEWORK_INSTALL_DIR)
+ set(install_dir ${LLDB_FRAMEWORK_INSTALL_DIR})
+ else()
+ set(install_dir ".")
+ endif()
+ else()
+ set(install_dir lib${LLVM_LIBDIR_SUFFIX})
endif()
install(TARGETS ${name}
COMPONENT ${name}
RUNTIME DESTINATION bin
- LIBRARY DESTINATION ${out_dir}
- ARCHIVE DESTINATION ${out_dir})
+ LIBRARY DESTINATION ${install_dir}
+ ARCHIVE DESTINATION ${install_dir})
else()
install(TARGETS ${name}
COMPONENT ${name}
@@ -67,12 +78,13 @@ function(add_lldb_library name)
endif()
if (NOT CMAKE_CONFIGURATION_TYPES)
add_llvm_install_targets(install-${name}
- DEPENDS ${name}
+ DEPENDS $<TARGET_FILE:${name}>
COMPONENT ${name})
endif()
endif()
endif()
+
# Hack: only some LLDB libraries depend on the clang autogenerated headers,
# but it is simple enough to make all of LLDB depend on some of those
# headers without negatively impacting much of anything.
@@ -86,59 +98,35 @@ endfunction(add_lldb_library)
function(add_lldb_executable name)
cmake_parse_arguments(ARG
- "INCLUDE_IN_SUITE;GENERATE_INSTALL"
- ""
+ "GENERATE_INSTALL"
+ "ENTITLEMENTS"
"LINK_LIBS;LINK_COMPONENTS"
${ARGN}
)
+ if(LLDB_NO_INSTALL_DEFAULT_RPATH)
+ set(pass_NO_INSTALL_RPATH NO_INSTALL_RPATH)
+ endif()
+
list(APPEND LLVM_LINK_COMPONENTS ${ARG_LINK_COMPONENTS})
- add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS})
+ add_llvm_executable(${name} ${ARG_UNPARSED_ARGUMENTS}
+ ENTITLEMENTS ${ARG_ENTITLEMENTS}
+ ${pass_NO_INSTALL_RPATH}
+ )
target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS})
- set_target_properties(${name} PROPERTIES
- FOLDER "lldb executables")
-
- if(ARG_INCLUDE_IN_SUITE)
- add_dependencies(lldb-suite ${name})
- if(LLDB_BUILD_FRAMEWORK)
- if(NOT IOS)
- set(resource_dir "/Resources")
- set(resource_dots "../")
- endif()
- string(REGEX REPLACE "[^/]+" ".." _dots ${LLDB_FRAMEWORK_INSTALL_DIR})
- set_target_properties(${name} PROPERTIES
- RUNTIME_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:liblldb>${resource_dir}
- BUILD_WITH_INSTALL_RPATH On
- INSTALL_RPATH "@loader_path/../../../${resource_dots}${_dots}/${LLDB_FRAMEWORK_INSTALL_DIR}")
- endif()
- endif()
-
- if(LLDB_BUILD_FRAMEWORK AND NOT ARG_INCLUDE_IN_SUITE)
- set_target_properties(${name} PROPERTIES
- BUILD_WITH_INSTALL_RPATH On
- INSTALL_RPATH "@loader_path/../${LLDB_FRAMEWORK_INSTALL_DIR}")
- endif()
+ set_target_properties(${name} PROPERTIES FOLDER "lldb executables")
if(ARG_GENERATE_INSTALL)
- set(out_dir "bin")
- if (LLDB_BUILD_FRAMEWORK AND ARG_INCLUDE_IN_SUITE)
- set(out_dir ${LLDB_FRAMEWORK_INSTALL_DIR}/${LLDB_FRAMEWORK_RESOURCE_DIR})
- endif()
install(TARGETS ${name}
- COMPONENT ${name}
- RUNTIME DESTINATION ${out_dir})
+ COMPONENT ${name}
+ RUNTIME DESTINATION bin)
if (NOT CMAKE_CONFIGURATION_TYPES)
add_llvm_install_targets(install-${name}
DEPENDS ${name}
COMPONENT ${name})
endif()
endif()
-
- if(ARG_INCLUDE_IN_SUITE AND LLDB_BUILD_FRAMEWORK)
- add_llvm_tool_symlink(${name} ${name} ALWAYS_GENERATE SKIP_INSTALL
- OUTPUT_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
- endif()
endfunction(add_lldb_executable)
function(add_lldb_tool name)
@@ -160,3 +148,40 @@ function(lldb_append_link_flags target_name new_link_flags)
# Now set them onto the target.
set_target_properties(${target_name} PROPERTIES LINK_FLAGS ${new_link_flags})
endfunction()
+
+# For tools that depend on liblldb, account for varying directory structures in
+# which LLDB.framework can be used and distributed: In the build-tree we find it
+# by its absolute target path. This is only relevant for running the test suite.
+# In the install step CMake will remove this entry and insert the final RPATHs.
+# These are relative to the file path from where the tool will be loaded on the
+# enduser system.
+#
+# Note that the LLVM install-tree doesn't match the enduser system structure
+# for LLDB.framework, so by default dependent tools will not be functional in
+# their install location. The LLDB_FRAMEWORK_INSTALL_DIR variable allows to fix
+# this. If specified, it causes the install-tree location of the framework to be
+# added as an extra RPATH below.
+#
+function(lldb_setup_framework_rpaths_in_tool name)
+ # In the build-tree, we know the exact path to the binary in the framework.
+ set(rpath_build_tree "$<TARGET_FILE:liblldb>")
+
+ # The installed framework is relocatable and can be in different locations.
+ set(rpaths_install_tree "@loader_path/../../../SharedFrameworks")
+ list(APPEND rpaths_install_tree "@loader_path/../../System/Library/PrivateFrameworks")
+ list(APPEND rpaths_install_tree "@loader_path/../../Library/PrivateFrameworks")
+
+ if(LLDB_FRAMEWORK_INSTALL_DIR)
+ set(rpaths_install_tree "@loader_path/../${LLDB_FRAMEWORK_INSTALL_DIR}")
+ endif()
+
+ # If LLDB_NO_INSTALL_DEFAULT_RPATH was NOT enabled (default), this overwrites
+ # the default settings from llvm_setup_rpath().
+ set_target_properties(${name} PROPERTIES
+ BUILD_WITH_INSTALL_RPATH OFF
+ BUILD_RPATH "${rpath_build_tree}"
+ INSTALL_RPATH "${rpaths_install_tree}"
+ )
+
+ add_dependencies(${name} lldb-framework)
+endfunction()
diff --git a/cmake/modules/LLDBConfig.cmake b/cmake/modules/LLDBConfig.cmake
index dae6e365da38..109c5132d3be 100644
--- a/cmake/modules/LLDBConfig.cmake
+++ b/cmake/modules/LLDBConfig.cmake
@@ -4,34 +4,74 @@ set(LLDB_PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
set(LLDB_SOURCE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/source")
set(LLDB_INCLUDE_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/include")
+set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
+
+if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
+ message(FATAL_ERROR
+ "In-source builds are not allowed. CMake would overwrite the makefiles "
+ "distributed with LLDB. Please create a directory and run cmake from "
+ "there, passing the path to this source directory as the last argument. "
+ "This process created the file `CMakeCache.txt' and the directory "
+ "`CMakeFiles'. Please delete them.")
+endif()
+
set(LLDB_LINKER_SUPPORTS_GROUPS OFF)
if (LLVM_COMPILER_IS_GCC_COMPATIBLE AND NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
# The Darwin linker doesn't understand --start-group/--end-group.
set(LLDB_LINKER_SUPPORTS_GROUPS ON)
endif()
-set(LLDB_DEFAULT_DISABLE_PYTHON 0)
-set(LLDB_DEFAULT_DISABLE_CURSES 0)
+set(default_disable_python OFF)
+set(default_disable_curses OFF)
+set(default_disable_libedit OFF)
-if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
- set(LLDB_DEFAULT_DISABLE_CURSES 1)
-elseif (CMAKE_SYSTEM_NAME MATCHES "Android" )
- set(LLDB_DEFAULT_DISABLE_PYTHON 1)
- set(LLDB_DEFAULT_DISABLE_CURSES 1)
-elseif(IOS)
- set(LLDB_DEFAULT_DISABLE_PYTHON 1)
+if(DEFINED LLVM_ENABLE_LIBEDIT AND NOT LLVM_ENABLE_LIBEDIT)
+ set(default_disable_libedit ON)
endif()
-set(LLDB_DISABLE_PYTHON ${LLDB_DEFAULT_DISABLE_PYTHON} CACHE BOOL
- "Disables the Python scripting integration.")
-set(LLDB_DISABLE_CURSES ${LLDB_DEFAULT_DISABLE_CURSES} CACHE BOOL
- "Disables the Curses integration.")
+if(CMAKE_SYSTEM_NAME MATCHES "Windows")
+ set(default_disable_curses ON)
+ set(default_disable_libedit ON)
+elseif(CMAKE_SYSTEM_NAME MATCHES "Android")
+ set(default_disable_python ON)
+ set(default_disable_curses ON)
+ set(default_disable_libedit ON)
+elseif(IOS)
+ set(default_disable_python ON)
+endif()
-set(LLDB_RELOCATABLE_PYTHON 0 CACHE BOOL
- "Causes LLDB to use the PYTHONHOME environment variable to locate Python.")
+option(LLDB_DISABLE_PYTHON "Disable Python scripting integration." ${default_disable_python})
+option(LLDB_DISABLE_CURSES "Disable Curses integration." ${default_disable_curses})
+option(LLDB_DISABLE_LIBEDIT "Disable the use of editline." ${default_disable_libedit})
+option(LLDB_RELOCATABLE_PYTHON "Use the PYTHONHOME environment variable to locate Python." OFF)
+option(LLDB_USE_SYSTEM_SIX "Use six.py shipped with system and do not install a copy of it" OFF)
+option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON)
+option(LLDB_BUILD_FRAMEWORK "Build LLDB.framework (Darwin only)" OFF)
+option(LLDB_NO_INSTALL_DEFAULT_RPATH "Disable default RPATH settings in binaries" OFF)
+
+if(LLDB_BUILD_FRAMEWORK)
+ if(NOT APPLE)
+ message(FATAL_ERROR "LLDB.framework can only be generated when targeting Apple platforms")
+ endif()
+ # CMake 3.6 did not correctly emit POST_BUILD commands for Apple Framework targets
+ if(CMAKE_VERSION VERSION_LESS 3.7)
+ message(FATAL_ERROR "LLDB_BUILD_FRAMEWORK is not supported on CMake < 3.7")
+ endif()
-set(LLDB_USE_SYSTEM_SIX 0 CACHE BOOL
- "Use six.py shipped with system and do not install a copy of it")
+ set(LLDB_FRAMEWORK_VERSION A CACHE STRING "LLDB.framework version (default is A)")
+ set(LLDB_FRAMEWORK_BUILD_DIR bin CACHE STRING "Output directory for LLDB.framework")
+ set(LLDB_FRAMEWORK_INSTALL_DIR Library/Frameworks CACHE STRING "Install directory for LLDB.framework")
+ set(LLDB_FRAMEWORK_TOOLS darwin-debug;debugserver;lldb-argdumper;lldb-server CACHE INTERNAL
+ "List of tools to include in LLDB.framework/Resources")
+
+ # Set designated directory for all dSYMs. Essentially, this emits the
+ # framework's dSYM outside of the framework directory.
+ if(LLVM_EXTERNALIZE_DEBUGINFO)
+ set(LLVM_EXTERNALIZE_DEBUGINFO_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin CACHE STRING
+ "Directory to emit dSYM files stripped from executables and libraries (Darwin Only)")
+ endif()
+endif()
if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
set(LLDB_EXPORT_ALL_SYMBOLS 0 CACHE BOOL
@@ -243,6 +283,7 @@ if( MSVC )
-wd4018 # Suppress 'warning C4018: '>=' : signed/unsigned mismatch'
-wd4068 # Suppress 'warning C4068: unknown pragma'
-wd4150 # Suppress 'warning C4150: deletion of pointer to incomplete type'
+ -wd4201 # Suppress 'warning C4201: nonstandard extension used: nameless struct/union'
-wd4251 # Suppress 'warning C4251: T must have dll-interface to be used by clients of class U.'
-wd4521 # Suppress 'warning C4521: 'type' : multiple copy constructors specified'
-wd4530 # Suppress 'warning C4530: C++ exception handler used, but unwind semantics are not enabled.'
@@ -254,20 +295,20 @@ if (CMAKE_SYSTEM_NAME MATCHES "Windows")
add_definitions( -D_UNICODE -DUNICODE )
endif()
-set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
-
-if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
- message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
-"the makefiles distributed with LLDB. Please create a directory and run cmake "
-"from there, passing the path to this source directory as the last argument. "
-"This process created the file `CMakeCache.txt' and the directory "
-"`CMakeFiles'. Please delete them.")
+# If LLDB_VERSION_* is specified, use it, if not use LLVM_VERSION_*.
+if(NOT DEFINED LLDB_VERSION_MAJOR)
+ set(LLDB_VERSION_MAJOR ${LLVM_VERSION_MAJOR})
endif()
-
-# Compute the LLDB version from the LLVM version.
-string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLDB_VERSION
- ${PACKAGE_VERSION})
+if(NOT DEFINED LLDB_VERSION_MINOR)
+ set(LLDB_VERSION_MINOR ${LLVM_VERSION_MINOR})
+endif()
+if(NOT DEFINED LLDB_VERSION_PATCH)
+ set(LLDB_VERSION_PATCH ${LLVM_VERSION_PATCH})
+endif()
+if(NOT DEFINED LLDB_VERSION_SUFFIX)
+ set(LLDB_VERSION_SUFFIX ${LLVM_VERSION_SUFFIX})
+endif()
+set(LLDB_VERSION "${LLDB_VERSION_MAJOR}.${LLDB_VERSION_MINOR}.${LLDB_VERSION_PATCH}${LLDB_VERSION_SUFFIX}")
message(STATUS "LLDB version: ${LLDB_VERSION}")
include_directories(BEFORE
@@ -304,11 +345,7 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
endif()
endif()
-if (NOT LIBXML2_FOUND AND NOT (CMAKE_SYSTEM_NAME MATCHES "Windows"))
- # Skip Libxml2 on Windows. In CMake 3.4 and higher, the algorithm for
- # finding libxml2 got "smarter", and it can now locate the version which is
- # in gnuwin32, even though that version does not contain the headers that
- # LLDB uses.
+if (NOT LIBXML2_FOUND)
find_package(LibXml2)
endif()
@@ -323,11 +360,6 @@ if (APPLE)
find_library(CORE_FOUNDATION_LIBRARY CoreFoundation)
find_library(SECURITY_LIBRARY Security)
- set(LLDB_FRAMEWORK_INSTALL_DIR Library/Frameworks CACHE STRING "Output directory for LLDB.framework")
- set(LLDB_FRAMEWORK_VERSION A CACHE STRING "LLDB.framework version (default is A)")
- set(LLDB_FRAMEWORK_RESOURCE_DIR
- LLDB.framework/Versions/${LLDB_FRAMEWORK_VERSION}/Resources)
-
add_definitions( -DLIBXML2_DEFINED )
list(APPEND system_libs xml2
${CURSES_LIBRARIES}
@@ -336,14 +368,11 @@ if (APPLE)
${CORE_SERVICES_LIBRARY}
${SECURITY_LIBRARY}
${DEBUG_SYMBOLS_LIBRARY})
-
-else()
- if (LIBXML2_FOUND)
- add_definitions( -DLIBXML2_DEFINED )
- list(APPEND system_libs ${LIBXML2_LIBRARIES})
- include_directories(${LIBXML2_INCLUDE_DIR})
- endif()
-
+ include_directories(${LIBXML2_INCLUDE_DIR})
+elseif(LIBXML2_FOUND AND LIBXML2_VERSION_STRING VERSION_GREATER 2.8)
+ add_definitions( -DLIBXML2_DEFINED )
+ list(APPEND system_libs ${LIBXML2_LIBRARIES})
+ include_directories(${LIBXML2_INCLUDE_DIR})
endif()
if( WIN32 AND NOT CYGWIN )
@@ -358,6 +387,8 @@ endif()
list(APPEND system_libs ${CMAKE_DL_LIBS})
+SET(SKIP_LLDB_SERVER_BUILD OFF CACHE BOOL "Skip building lldb-server")
+
# Figure out if lldb could use lldb-server. If so, then we'll
# ensure we build lldb-server when an lldb target is being built.
if (CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|FreeBSD|Linux|NetBSD")
diff --git a/cmake/modules/LLDBFramework.cmake b/cmake/modules/LLDBFramework.cmake
index abacee89d9ac..0ccabd12a010 100644
--- a/cmake/modules/LLDBFramework.cmake
+++ b/cmake/modules/LLDBFramework.cmake
@@ -1,44 +1,107 @@
+# Path relative to the root binary directory
+get_filename_component(
+ framework_target_dir ${LLDB_FRAMEWORK_BUILD_DIR} ABSOLUTE
+ BASE_DIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+)
+
+message(STATUS "LLDB.framework: build path is '${framework_target_dir}'")
+message(STATUS "LLDB.framework: install path is '${LLDB_FRAMEWORK_INSTALL_DIR}'")
+message(STATUS "LLDB.framework: resources subdirectory is 'Versions/${LLDB_FRAMEWORK_VERSION}/Resources'")
+
+# Configure liblldb as a framework bundle
+set_target_properties(liblldb PROPERTIES
+ FRAMEWORK ON
+ FRAMEWORK_VERSION ${LLDB_FRAMEWORK_VERSION}
+
+ OUTPUT_NAME LLDB
+ VERSION ${LLDB_VERSION}
+ LIBRARY_OUTPUT_DIRECTORY ${framework_target_dir}
+
+ # Compatibility version
+ SOVERSION "1.0.0"
+
+ MACOSX_FRAMEWORK_IDENTIFIER com.apple.LLDB.framework
+ MACOSX_FRAMEWORK_BUNDLE_VERSION ${LLDB_VERSION}
+ MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${LLDB_VERSION}
+ MACOSX_FRAMEWORK_INFO_PLIST ${LLDB_SOURCE_DIR}/resources/LLDB-Info.plist.in
+)
+
+# Affects the layout of the framework bundle (default is macOS layout).
+if(IOS)
+ set_target_properties(liblldb PROPERTIES
+ XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IPHONEOS_DEPLOYMENT_TARGET}")
+else()
+ set_target_properties(liblldb PROPERTIES
+ XCODE_ATTRIBUTE_MACOSX_DEPLOYMENT_TARGET "${MACOSX_DEPLOYMENT_TARGET}")
+endif()
+
+# Target to capture extra steps for a fully functional framework bundle.
+add_custom_target(lldb-framework)
+add_dependencies(lldb-framework liblldb)
+
+# Dependencies are defined once tools are added (see AddLLDB.cmake)
+if(LLDB_FRAMEWORK_TOOLS)
+ foreach(tool ${LLDB_FRAMEWORK_TOOLS})
+ add_custom_command(TARGET lldb-framework POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${tool}> $<TARGET_FILE_DIR:liblldb>/Resources
+ COMMENT "LLDB.framework: copy additional tool ${tool}"
+ )
+ endforeach()
+else()
+ message(WARNING "LLDB.framework: no additional tools configured (set via LLDB_FRAMEWORK_TOOLS)")
+endif()
+
+# Apart from this one, CMake creates all required symlinks in the framework bundle.
+add_custom_command(TARGET lldb-framework POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E create_symlink
+ Versions/Current/Headers
+ ${framework_target_dir}/LLDB.framework/Headers
+ COMMENT "LLDB.framework: create Headers symlink"
+)
+
+# At configuration time, collect headers for the framework bundle and copy them
+# into a staging directory. Later we can copy over the entire folder.
file(GLOB public_headers ${LLDB_SOURCE_DIR}/include/lldb/API/*.h)
file(GLOB root_public_headers ${LLDB_SOURCE_DIR}/include/lldb/lldb-*.h)
file(GLOB root_private_headers ${LLDB_SOURCE_DIR}/include/lldb/lldb-private*.h)
list(REMOVE_ITEM root_public_headers ${root_private_headers})
+
+set(lldb_header_staging ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders)
foreach(header
${public_headers}
${root_public_headers}
${LLDB_SOURCE_DIR}/include/lldb/Utility/SharingPtr.h)
+
get_filename_component(basename ${header} NAME)
- add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders/${basename}
- DEPENDS ${header}
- COMMAND ${CMAKE_COMMAND} -E copy ${header} ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders/${basename})
- list(APPEND framework_headers ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders/${basename})
+ set(staged_header ${lldb_header_staging}/${basename})
+
+ add_custom_command(
+ DEPENDS ${header} OUTPUT ${staged_header}
+ COMMAND ${CMAKE_COMMAND} -E copy ${header} ${staged_header}
+ COMMENT "LLDB.framework: collect framework header")
+
+ list(APPEND lldb_staged_headers ${staged_header})
endforeach()
-add_custom_target(lldb-framework-headers DEPENDS ${framework_headers})
+# Wrap output in a target, so lldb-framework can depend on it.
+add_custom_target(lldb-framework-headers DEPENDS ${lldb_staged_headers})
+add_dependencies(lldb-framework lldb-framework-headers)
-add_custom_command(TARGET lldb-framework POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_BINARY_DIR}/FrameworkHeaders $<TARGET_FILE_DIR:liblldb>/Headers
+# At build time, copy the staged headers into the framework bundle (and do
+# some post-processing in-place).
+add_custom_command(TARGET lldb-framework-headers POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${lldb_header_staging} $<TARGET_FILE_DIR:liblldb>/Headers
COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.sh $<TARGET_FILE_DIR:liblldb>/Headers ${LLDB_VERSION}
+ COMMENT "LLDB.framework: copy framework headers"
)
-if (NOT IOS)
- if (NOT LLDB_BUILT_STANDALONE)
- add_dependencies(lldb-framework clang-headers)
- endif()
+# Copy vendor-specific headers from clang (without staging).
+if(NOT IOS AND NOT LLDB_BUILT_STANDALONE)
+ add_dependencies(lldb-framework clang-headers)
add_custom_command(TARGET lldb-framework POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E create_symlink Versions/Current/Headers ${LLDB_FRAMEWORK_DIR}/LLDB.framework/Headers
- COMMAND ${CMAKE_COMMAND} -E create_symlink ${LLDB_FRAMEWORK_VERSION} ${LLDB_FRAMEWORK_DIR}/LLDB.framework/Versions/Current
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/clang/${LLDB_VERSION} $<TARGET_FILE_DIR:liblldb>/Resources/Clang
+ COMMAND ${CMAKE_COMMAND} -E copy_directory
+ $<TARGET_PROPERTY:clang-headers,RUNTIME_OUTPUT_DIRECTORY>
+ $<TARGET_FILE_DIR:liblldb>/Resources/Clang/include
+ COMMENT "LLDB.framework: copy clang vendor-specific headers"
)
endif()
-
-set_target_properties(liblldb PROPERTIES
- OUTPUT_NAME LLDB
- FRAMEWORK On
- FRAMEWORK_VERSION ${LLDB_FRAMEWORK_VERSION}
- MACOSX_FRAMEWORK_INFO_PLIST ${LLDB_SOURCE_DIR}/resources/LLDB-Info.plist
- LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${LLDB_FRAMEWORK_INSTALL_DIR}
- PUBLIC_HEADER "${framework_headers}")
-
-add_dependencies(lldb-framework
- lldb-framework-headers
- lldb-suite)
diff --git a/cmake/modules/LLDBStandalone.cmake b/cmake/modules/LLDBStandalone.cmake
index 742c464036a4..e63b2694e6a4 100644
--- a/cmake/modules/LLDBStandalone.cmake
+++ b/cmake/modules/LLDBStandalone.cmake
@@ -83,6 +83,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
endif()
include(AddLLVM)
+ include(TableGen)
include(HandleLLVMOptions)
include(CheckAtomic)
@@ -100,17 +101,15 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
# Import CMake library targets from LLVM and Clang.
include("${LLVM_OBJ_ROOT}/lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm/LLVMConfig.cmake")
- # cmake/clang/ClangConfig.cmake is not created when LLVM and Clang are built together.
if (EXISTS "${LLVM_OBJ_ROOT}/lib${LLVM_LIBDIR_SUFFIX}/cmake/clang/ClangConfig.cmake")
include("${LLVM_OBJ_ROOT}/lib${LLVM_LIBDIR_SUFFIX}/cmake/clang/ClangConfig.cmake")
endif()
set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}")
-
- set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR})
+ set(LLVM_INCLUDE_TESTS ON CACHE INTERNAL "")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
- include_directories("${LLVM_BINARY_DIR}/include" "${LLVM_MAIN_INCLUDE_DIR}")
+ include_directories("${CMAKE_BINARY_DIR}/include" "${LLVM_MAIN_INCLUDE_DIR}")
# Next three include directories are needed when llvm-config is located in build directory.
# LLVM and Clang are assumed to be built together
if (EXISTS "${LLVM_OBJ_ROOT}/include")
diff --git a/cmake/modules/debugserverConfig.cmake b/cmake/modules/debugserverConfig.cmake
new file mode 100644
index 000000000000..3b716ca87716
--- /dev/null
+++ b/cmake/modules/debugserverConfig.cmake
@@ -0,0 +1,3 @@
+# Duplicate options from LLDBConfig that are relevant for debugserver Standalone builds.
+
+option(LLDB_USE_ENTITLEMENTS "When code signing, use entitlements if available" ON)
diff --git a/docs/building-with-debug-llvm.txt b/docs/building-with-debug-llvm.txt
index f59ca410edb0..af1bcf8856b2 100644
--- a/docs/building-with-debug-llvm.txt
+++ b/docs/building-with-debug-llvm.txt
@@ -48,3 +48,4 @@ currently at a shell prompt in a checked-out LLDB repository.
the top left of the Xcode window.
6. Build lldb.xcodeproj.
+
diff --git a/docs/lldb-platform-packets.txt b/docs/lldb-platform-packets.txt
new file mode 100644
index 000000000000..3258e4c0dd88
--- /dev/null
+++ b/docs/lldb-platform-packets.txt
@@ -0,0 +1,404 @@
+Here is a brief overview of the packets that an lldb platform server
+needs to implement for the lldb testsuite to be run on a remote
+target device/system.
+
+These are almost all lldb extensions to the gdb-remote serial
+protocol. Many of the vFile: packets are described to the "Host
+I/O Packets" detailed in the gdb-remote protocol documentation,
+although the lldb platform extensions include packets that are not
+defined there (vFile:size:, vFile:mode:, vFile:symlink, vFile:chmod:).
+Most importantly, the flags that lldb passes to vFile:open: are
+incompatible with the flags that gdb specifies.
+
+
+//----------------------------------------------------------------------
+// QStartNoAckMode
+//
+// BRIEF
+// A request to stop sending ACK packets for each properly formatted packet.
+//
+// EXAMPLE
+// A platform session will typically start like this:
+//
+// receive: +$QStartNoAckMode#b0
+// send: + <-- ACKing the properly formatted QStartNoAckMode packet
+// send: $OK#9a
+// receive: + <-- Our OK packet getting ACKed
+//
+// ACK mode is now disabled.
+
+//----------------------------------------------------------------------
+// qHostInfo
+//
+// BRIEF
+// Describe the hardware and OS of the target system
+//
+// EXAMPLE
+//
+// receive: qHostInfo
+// send: cputype:16777228;cpusubtype:1;ostype:ios;watchpoint_exceptions_received:before;os_version:12.1;vendor:apple;default_packet_timeout:5;
+//
+// All numbers are base 10, os_version is a string that will be parsed as major.minor.patch.
+
+//----------------------------------------------------------------------
+// qModuleInfo
+//
+// BRIEF
+// Report information about a binary on the target system
+//
+// EXAMPLE
+// receive: qModuleInfo:2f62696e2f6c73;
+//
+// FIXME finish this packet description, v. GDBRemoteCommunicationServerCommon::Handle_qModuleInfo
+
+
+//----------------------------------------------------------------------
+// qGetWorkingDir
+//
+// BRIEF
+// Get the current working directory of the platform stub in
+// ASCII hex encoding.
+//
+// EXAMPLE
+//
+// receive: qGetWorkingDir
+// send: 2f4170706c65496e7465726e616c2f6c6c64622f73657474696e67732f342f5465737453657474696e67732e746573745f646973617373656d626c65725f73657474696e6773
+
+
+
+//----------------------------------------------------------------------
+// QSetWorkingDir:
+//
+// BRIEF
+// Set the current working directory of the platform stub in
+// ASCII hex encoding.
+//
+// EXAMPLE
+//
+// receive: QSetWorkingDir:2f4170706c65496e7465726e616c2f6c6c64622f73657474696e67732f342f5465737453657474696e67732e746573745f646973617373656d626c65725f73657474696e6773
+// send: OK
+
+//----------------------------------------------------------------------
+// qPlatform_mkdir:
+//
+// BRIEF
+// Create a directory on the target system.
+//
+// EXAMPLE
+//
+// receive: qPlatform_mkdir:000001fd,2f746d702f6131
+// send: F0
+//
+// request packet has the fields:
+// 1. mode bits in base 16
+// 2. file path in ascii-hex encoding
+//
+// response is F followed by the return value of the mkdir() call,
+// base 10 encoded.
+
+//----------------------------------------------------------------------
+// qPlatform_shell:
+//
+// BRIEF
+// Run a shell command on the target system, return the output.
+//
+// EXAMPLE
+//
+// receive: qPlatform_shell:6c73202f746d702f,0000000a
+// send: F,0,0,<OUTPUT>
+//
+// request packet has the fields:
+// 1. shell command ascii-hex encoded
+// 2. timeout
+// 3. {optional} working directory ascii-hex encoded
+//
+// Response is F followed by the return value of the command (base 16),
+// followed by a another number, followed by the output of the command
+/ in binary-escaped-data encoding.
+
+//----------------------------------------------------------------------
+// qLaunchGDBServer
+//
+// BRIEF
+// Start a gdbserver process (gdbserver, debugserver, lldb-server)
+// on the target system.
+//
+// EXAMPLE
+//
+// receive: qLaunchGDBServer;host:<HOSTNAME_LLDB_IS_ON>;
+// send: pid:1337;port:43001;
+//
+// request packet hostname field is not ascii-hex encoded. Hostnames
+// don't have $ or # characters in them.
+//
+// response to the packet is the pid of the newly launched gdbserver,
+// and the port it is listening for a connection on.
+//
+// When the testsuite is running, lldb may use the pid to kill off a
+// debugserver that doesn't seem to be responding, etc.
+
+//----------------------------------------------------------------------
+// qKillSpawnedProcess:
+//
+// BRIEF
+// Kill a process running on the target system.
+//
+// EXAMPLE
+//
+// receive: qKillSpawnedProcess:1337
+// send: OK
+//
+// The request packet has the process ID in base 10.
+
+//----------------------------------------------------------------------
+// qProcessInfoPID:
+//
+// BRIEF
+// Gather information about a process running on the target
+//
+// EXAMPLE
+//
+// receive: qProcessInfoPID:71964
+// send: pid:71964;name:612e6f7574;
+//
+// The request packet has the pid encoded in base 10.
+//
+// The reply has semicolon-separated name:value fields, two are
+// shown here. pid is base 10 encoded. name is ascii hex encoded.
+// lldb-server can reply with many additional fields, but I think
+// this is enough for the testsuite.
+
+//----------------------------------------------------------------------
+// qfProcessInfo:
+//
+// BRIEF
+// Search the process table for processes matching criteria,
+// respond with them in multiple packets.
+//
+// EXAMPLE
+//
+// receive: qfProcessInfo:name_match:equals;name:6e6f70726f6365737365786973747377697468746869736e616d65;
+// send: pid:3500;name:612e6f7574;
+//
+// The request packet has a criteria to search for, followed by
+// a specific name. Other name_match: values include
+// starts_with, ends_with, contains, regex. You can specify a pid
+// to search for, a uid, all_users, triple, etc etc. The testsuite
+// only ever searches for name_match:equals.
+//
+// The response should include any information about the process that
+// can be retrieved in semicolon-separated name:value fields.
+// In this example, pid is base 10, name is ascii-hex encoded.
+// The testsuite seems to only require these two.
+//
+// This packet only responds with one process. To get further matches to
+// the search, qsProcessInfo should be sent.
+//
+// If no process match is found, Exx should be returned.
+
+//----------------------------------------------------------------------
+// qsProcessInfo
+//
+// BRIEF
+// Return the next process info found by the most recent qfProcessInfo:
+// packet.
+//
+// EXAMPLE
+//
+// Continues to return the results of the qfProcessInfo. Once all matches
+// have been sent, Exx is returned to indicate end of matches.
+
+//----------------------------------------------------------------------
+// vFile:size:
+//
+// BRIEF
+// Get the size of a file on the target system, filename in ASCII hex.
+//
+// EXAMPLE
+//
+// receive: vFile:size:2f746d702f61
+// send: Fc008
+//
+// response is "F" followed by the file size in base 16.
+// "F-1,errno" with the errno if an error occurs.
+
+
+//----------------------------------------------------------------------
+// vFile:mode:
+//
+// BRIEF
+// Get the mode bits of a file on the target system, filename in ASCII hex.
+//
+// EXAMPLE
+//
+// receive: vFile:mode:2f746d702f61
+// send: F1ed
+//
+// response is "F" followed by the mode bits in base 16, this 0x1ed would
+// correspond to 0755 in octal.
+// "F-1,errno" with the errno if an error occurs.
+
+//----------------------------------------------------------------------
+// vFile:unlink:
+//
+// BRIEF
+// Remove a file on the target system.
+//
+// EXAMPLE
+//
+// receive: vFile:unlink:2f746d702f61
+// send: F0
+//
+// Argument is a file path in ascii-hex encoding.
+// Response is "F" plus the return value of unlink(), base 10 encoding.
+
+//----------------------------------------------------------------------
+// vFile:symlink:
+//
+// BRIEF
+// Create a symbolic link (symlink, soft-link) on the target system.
+//
+// EXAMPLE
+//
+// receive: vFile:symlink:<SRC-FILE>,<DST-NAME>
+// send: F0,0
+//
+// Argument file paths are in ascii-hex encoding.
+// Response is "F" plus the return value of symlink(), base 10 encoding, twice.
+
+//----------------------------------------------------------------------
+// vFile:chmod:
+// qPlatform_chmod:
+//
+// BRIEF
+// Change the permission mode bits on a file on the target
+//
+// EXAMPLE
+//
+// receive: vFile:chmod:180,2f746d702f61
+// send: F0
+//
+// Arguments are the mode bits to set, base 16, and a file path in
+// ascii-hex encoding.
+// Response is "F" plus the return value of chmod(), base 10 encoding.
+//
+// I don't know why there are two packets for the same thing, v.
+// vFile:chmod:.
+
+//----------------------------------------------------------------------
+// vFile:chmod:
+//
+// BRIEF
+// Change the permission mode bits on a file on the target
+//
+// EXAMPLE
+//
+// receive: vFile:chmod:180,2f746d702f61
+// send: F0
+//
+// Arguments are the mode bits to set, base 16, and a file path in
+// ascii-hex encoding.
+// Response is "F" plus the return value of chmod(), base 10 encoding.
+
+
+//----------------------------------------------------------------------
+// vFile:open:
+//
+// BRIEF
+// Open a file on the remote system and return the file descriptor of it.
+//
+// EXAMPLE
+//
+// receive: vFile:open:2f746d702f61,00000001,00000180
+// send: F8
+//
+// request packet has the fields:
+// 1. ASCII hex encoded filename
+// 2. flags passed to the open call, base 16.
+// Note that these are not the oflags that open(2) takes, but
+// are the constant values in enum OpenOptions from lldb's File.h
+// 3. mode bits, base 16
+//
+// response is F followed by the opened file descriptor in base 10.
+// "F-1,errno" with the errno if an error occurs.
+//
+// COMPATABILITY
+// The gdb-remote serial protocol documentatio defines a vFile:open:
+// packet which uses incompatible flag values, e.g. 1 means O_WRONLY
+// in gdb's vFile:open:, but it means eOpenOptionRead to lldb's
+// implementation.
+
+//----------------------------------------------------------------------
+// vFile:close:
+//
+// BRIEF
+// Close a previously opened file descriptor.
+//
+// EXAMPLE
+//
+// receive: vFile:close:7
+// send: F0
+//
+// File descriptor is in base 10.
+// "F-1,errno" with the errno if an error occurs.
+
+
+//----------------------------------------------------------------------
+// vFile:pread:
+//
+// BRIEF
+// Read data from an opened file descriptor.
+//
+// EXAMPLE
+//
+// receive: vFile:pread:7,1024,0
+// send: F4;a'b\00
+//
+// request packet has the fields:
+// 1. file descriptor, base 10
+// 2. number of bytes to be read, base 10
+// 3. offset into file to start from, base 10
+//
+// Response is F, followed by the number of bytes read (base 10), a
+// semicolon, followed by the data in the binary-escaped-data encoding.
+
+
+//----------------------------------------------------------------------
+// vFile:pwrite:
+//
+// BRIEF
+// Write data to a previously opened file descriptor.
+//
+// EXAMPLE
+//
+// receive: vFile:pwrite:8,0,\cf\fa\ed\fe\0c\00\00
+// send: F1024
+//
+// request packet has the fields:
+// 1. file descriptor, base 10
+// 2. offset into file to start from, base 10
+// 3. binary-escaped-data to be written
+//
+// Response is F, followed by the number of bytes written (base 10)
+
+
+
+
+
+
+Finally, the platform must be able to launch processes so that debugserver
+can attach to them. To do this, the following packets should be handled:
+
+QSetDisableASLR
+QSetDetachOnError
+QSetSTDOUT
+QSetSTDERR
+QSetSTDIN
+QEnvironment
+QEnvironmentHexEncoded
+A
+qLaunchSuccess
+qProcessInfo
+
+Most of these are documented in the standard gdb-remote protocol
+and/or the lldb-gdb-remote.txt documentation.
diff --git a/examples/darwin/heap_find/heap.py b/examples/darwin/heap_find/heap.py
index 81f36adb9c51..c463380bf49f 100644
--- a/examples/darwin/heap_find/heap.py
+++ b/examples/darwin/heap_find/heap.py
@@ -1036,7 +1036,7 @@ range_callback_t range_callback = [](task_t task, void *baton, unsigned type, ui
callback_baton_t *lldb_info = (callback_baton_t *)baton;
if (lldb_info->cstr_len < ptr_size) {
const char *begin = (const char *)ptr_addr;
- const char *end = begin + ptr_size - info->cstr_len;
+ const char *end = begin + ptr_size - lldb_info->cstr_len;
for (const char *s = begin; s < end; ++s) {
if ((int)memcmp(s, lldb_info->cstr, lldb_info->cstr_len) == 0) {
if (lldb_info->num_matches < MAX_MATCHES) {
diff --git a/examples/interposing/darwin/fd_interposing/FDInterposing.cpp b/examples/interposing/darwin/fd_interposing/FDInterposing.cpp
index 105251c95748..b414064109e4 100644
--- a/examples/interposing/darwin/fd_interposing/FDInterposing.cpp
+++ b/examples/interposing/darwin/fd_interposing/FDInterposing.cpp
@@ -65,7 +65,7 @@
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
-#include <tr1/memory> // for std::tr1::shared_ptr
+#include <tr1/memory>
#include <unistd.h>
#include <vector>
diff --git a/examples/python/bsd.py b/examples/python/bsd.py
index 8218f4ae6323..3e9528c65845 100755
--- a/examples/python/bsd.py
+++ b/examples/python/bsd.py
@@ -1,5 +1,6 @@
#!/usr/bin/python
+import cmd
import optparse
import os
import shlex
@@ -76,6 +77,22 @@ class Object(object):
self.file.seek(saved_pos, 0)
return bytes
+ def save(self, path=None, overwrite=False):
+ '''
+ Save the contents of the object to disk using 'path' argument as
+ the path, or save it to the current working directory using the
+ object name.
+ '''
+
+ if path is None:
+ path = self.name
+ if not overwrite and os.path.exists(path):
+ print('error: outfile "%s" already exists' % (path))
+ return
+ print('Saving "%s" to "%s"...' % (self.name, path))
+ with open(path, 'w') as f:
+ f.write(self.get_bytes())
+
class StringTable(object):
def __init__(self, bytes):
@@ -186,6 +203,67 @@ class Archive(object):
for obj in self.objects:
obj.dump(f=f, flat=flat)
+class Interactive(cmd.Cmd):
+ '''Interactive prompt for exploring contents of BSD archive files, type
+ "help" to see a list of supported commands.'''
+ image_option_parser = None
+
+ def __init__(self, archives):
+ cmd.Cmd.__init__(self)
+ self.use_rawinput = False
+ self.intro = ('Interactive BSD archive prompt, type "help" to see a '
+ 'list of supported commands.')
+ self.archives = archives
+ self.prompt = '% '
+
+ def default(self, line):
+ '''Catch all for unknown command, which will exit the interpreter.'''
+ print("unknown command: %s" % line)
+ return True
+
+ def do_q(self, line):
+ '''Quit command'''
+ return True
+
+ def do_quit(self, line):
+ '''Quit command'''
+ return True
+
+ def do_extract(self, line):
+ args = shlex.split(line)
+ if args:
+ extracted = False
+ for object_name in args:
+ for archive in self.archives:
+ matches = archive.find(object_name)
+ if matches:
+ for object in matches:
+ object.save(overwrite=False)
+ extracted = True
+ if not extracted:
+ print('error: no object matches "%s" in any archives' % (
+ object_name))
+ else:
+ print('error: must specify the name of an object to extract')
+
+ def do_ls(self, line):
+ args = shlex.split(line)
+ if args:
+ for object_name in args:
+ for archive in self.archives:
+ matches = archive.find(object_name)
+ if matches:
+ for object in matches:
+ object.dump(flat=False)
+ else:
+ print('error: no object matches "%s" in "%s"' % (
+ object_name, archive.path))
+ else:
+ for archive in self.archives:
+ archive.dump(flat=True)
+ print('')
+
+
def main():
parser = optparse.OptionParser(
@@ -243,9 +321,24 @@ def main():
'then the extracted object file will be extracted into the '
'current working directory if a file doesn\'t already exist '
'with that name.'))
+ parser.add_option(
+ '-i', '--interactive',
+ action='store_true',
+ dest='interactive',
+ default=False,
+ help=('Enter an interactive shell that allows users to interactively '
+ 'explore contents of .a files.'))
(options, args) = parser.parse_args(sys.argv[1:])
+ if options.interactive:
+ archives = []
+ for path in args:
+ archives.append(Archive(path))
+ interpreter = Interactive(archives)
+ interpreter.cmdloop()
+ return
+
for path in args:
archive = Archive(path)
if options.object_name:
@@ -256,17 +349,7 @@ def main():
if options.extract:
if len(matches) == 1:
dump_all = False
- if options.outfile is None:
- outfile_path = matches[0].name
- else:
- outfile_path = options.outfile
- if os.path.exists(outfile_path):
- print('error: outfile "%s" already exists' % (
- outfile_path))
- else:
- print('Saving file to "%s"...' % (outfile_path))
- with open(outfile_path, 'w') as outfile:
- outfile.write(matches[0].get_bytes())
+ matches[0].save(path=options.outfile, overwrite=False)
else:
print('error: multiple objects match "%s". Specify '
'the modification time using --mtime.' % (
diff --git a/examples/python/crashlog.py b/examples/python/crashlog.py
index 227fce114052..7eb86db7ce09 100755
--- a/examples/python/crashlog.py
+++ b/examples/python/crashlog.py
@@ -94,11 +94,9 @@ class CrashLog(symbolication.Symbolicator):
thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
app_backtrace_regex = re.compile(
'^Application Specific Backtrace ([0-9]+)([^:]*):(.*)')
- frame_regex = re.compile('^([0-9]+)\s+([^ ]+)\s+(0x[0-9a-fA-F]+) +(.*)')
+ frame_regex = re.compile('^([0-9]+)\s+(.+?)\s+(0x[0-9a-fA-F]{7}[0-9a-fA-F]+) +(.*)')
image_regex_uuid = re.compile(
- '(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)')
- image_regex_no_uuid = re.compile(
- '(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)')
+ '(0x[0-9a-fA-F]+)[-\s]+(0x[0-9a-fA-F]+)\s+[+]?(.+?)\s+(\(.+\))?\s?(<([-0-9a-fA-F]+)>)? (.*)')
empty_line_regex = re.compile('^$')
class Thread:
@@ -246,6 +244,25 @@ class CrashLog(symbolication.Symbolicator):
self.identifier = identifier
self.version = version
+ def find_matching_slice(self):
+ dwarfdump_cmd_output = commands.getoutput(
+ 'dwarfdump --uuid "%s"' % self.path)
+ self_uuid = self.get_uuid()
+ for line in dwarfdump_cmd_output.splitlines():
+ match = self.dwarfdump_uuid_regex.search(line)
+ if match:
+ dwarf_uuid_str = match.group(1)
+ dwarf_uuid = uuid.UUID(dwarf_uuid_str)
+ if self_uuid == dwarf_uuid:
+ self.resolved_path = self.path
+ self.arch = match.group(2)
+ return True
+ if not self.resolved_path:
+ self.unavailable = True
+ print("error\n error: unable to locate '%s' with UUID %s"
+ % (self.path, uuid_str))
+ return False
+
def locate_module_and_debug_symbols(self):
# Don't load a module twice...
if self.resolved:
@@ -277,22 +294,25 @@ class CrashLog(symbolication.Symbolicator):
plist['DBGSymbolRichExecutable'])
self.resolved_path = self.path
if not self.resolved_path and os.path.exists(self.path):
- dwarfdump_cmd_output = commands.getoutput(
- 'dwarfdump --uuid "%s"' % self.path)
- self_uuid = self.get_uuid()
- for line in dwarfdump_cmd_output.splitlines():
- match = self.dwarfdump_uuid_regex.search(line)
- if match:
- dwarf_uuid_str = match.group(1)
- dwarf_uuid = uuid.UUID(dwarf_uuid_str)
- if self_uuid == dwarf_uuid:
- self.resolved_path = self.path
- self.arch = match.group(2)
- break
- if not self.resolved_path:
- self.unavailable = True
- print "error\n error: unable to locate '%s' with UUID %s" % (self.path, uuid_str)
+ if not self.find_matching_slice():
return False
+ if not self.resolved_path and not os.path.exists(self.path):
+ try:
+ import subprocess
+ dsym = subprocess.check_output(
+ ["/usr/bin/mdfind",
+ "com_apple_xcode_dsym_uuids == %s"%uuid_str])[:-1]
+ if dsym and os.path.exists(dsym):
+ print('falling back to binary inside "%s"'%dsym)
+ self.symfile = dsym
+ dwarf_dir = os.path.join(dsym, 'Contents/Resources/DWARF')
+ for filename in os.listdir(dwarf_dir):
+ self.path = os.path.join(dwarf_dir, filename)
+ if not self.find_matching_slice():
+ return False
+ break
+ except:
+ pass
if (self.resolved_path and os.path.exists(self.resolved_path)) or (
self.path and os.path.exists(self.path)):
print 'ok'
@@ -455,25 +475,16 @@ class CrashLog(symbolication.Symbolicator):
elif parse_mode == PARSE_MODE_IMAGES:
image_match = self.image_regex_uuid.search(line)
if image_match:
- image = CrashLog.DarwinImage(int(image_match.group(1), 0),
- int(image_match.group(2), 0),
- image_match.group(3).strip(),
- image_match.group(4).strip(),
- uuid.UUID(image_match.group(5)),
- image_match.group(6))
+ (img_lo, img_hi, img_name, img_version,
+ _, img_uuid, img_path) = image_match.groups()
+ image = CrashLog.DarwinImage(int(img_lo, 0), int(img_hi, 0),
+ img_name.strip(),
+ img_version.strip()
+ if img_version else "",
+ uuid.UUID(img_uuid), img_path)
self.images.append(image)
else:
- image_match = self.image_regex_no_uuid.search(line)
- if image_match:
- image = CrashLog.DarwinImage(int(image_match.group(1), 0),
- int(image_match.group(2), 0),
- image_match.group(3).strip(),
- image_match.group(4).strip(),
- None,
- image_match.group(5))
- self.images.append(image)
- else:
- print "error: image regex failed for: %s" % line
+ print "error: image regex failed for: %s" % line
elif parse_mode == PARSE_MODE_THREGS:
stripped_line = line.strip()
diff --git a/examples/python/gdbremote.py b/examples/python/gdbremote.py
index a6ff3f5978e4..4ca8a1b82e84 100755
--- a/examples/python/gdbremote.py
+++ b/examples/python/gdbremote.py
@@ -685,32 +685,33 @@ def rsp_qXfer(options, cmd, cmd_args, rsp):
if extension == '.xml':
response = Packet(rsp)
xml_string = response.get_hex_ascii_str()
- ch = xml_string[0]
- if ch == 'l':
- xml_string = xml_string[1:]
- xml_root = ET.fromstring(xml_string)
- for reg_element in xml_root.findall("./feature/reg"):
- if not 'value_regnums' in reg_element.attrib:
- reg_info = RegisterInfo([])
- if 'name' in reg_element.attrib:
- reg_info.info[
- 'name'] = reg_element.attrib['name']
- else:
- reg_info.info['name'] = 'unspecified'
- if 'encoding' in reg_element.attrib:
- reg_info.info['encoding'] = reg_element.attrib[
- 'encoding']
- else:
- reg_info.info['encoding'] = 'uint'
- if 'offset' in reg_element.attrib:
- reg_info.info[
- 'offset'] = reg_element.attrib['offset']
- if 'bitsize' in reg_element.attrib:
- reg_info.info[
- 'bitsize'] = reg_element.attrib['bitsize']
- g_register_infos.append(reg_info)
- print 'XML for "%s":' % (data[2])
- ET.dump(xml_root)
+ if xml_string:
+ ch = xml_string[0]
+ if ch == 'l':
+ xml_string = xml_string[1:]
+ xml_root = ET.fromstring(xml_string)
+ for reg_element in xml_root.findall("./feature/reg"):
+ if not 'value_regnums' in reg_element.attrib:
+ reg_info = RegisterInfo([])
+ if 'name' in reg_element.attrib:
+ reg_info.info[
+ 'name'] = reg_element.attrib['name']
+ else:
+ reg_info.info['name'] = 'unspecified'
+ if 'encoding' in reg_element.attrib:
+ reg_info.info['encoding'] = reg_element.attrib[
+ 'encoding']
+ else:
+ reg_info.info['encoding'] = 'uint'
+ if 'offset' in reg_element.attrib:
+ reg_info.info[
+ 'offset'] = reg_element.attrib['offset']
+ if 'bitsize' in reg_element.attrib:
+ reg_info.info[
+ 'bitsize'] = reg_element.attrib['bitsize']
+ g_register_infos.append(reg_info)
+ print 'XML for "%s":' % (data[2])
+ ET.dump(xml_root)
def cmd_A(options, cmd, args):
@@ -810,6 +811,14 @@ def cmd_s(options, cmd, args):
return False
+def cmd_qSpeedTest(options, cmd, args):
+ print("qSpeedTest: cmd='%s', args='%s'" % (cmd, args))
+
+
+def rsp_qSpeedTest(options, cmd, cmd_args, rsp):
+ print("qSpeedTest: rsp='%s' cmd='%s', args='%s'" % (rsp, cmd, args))
+
+
def cmd_vCont(options, cmd, args):
if args == '?':
print "%s: get supported extended continue modes" % (cmd)
@@ -861,8 +870,10 @@ def rsp_vCont(options, cmd, cmd_args, rsp):
s += 'step'
elif mode == 'S':
s += 'step with signal'
- else:
- s += 'unrecognized vCont mode: ', mode
+ elif mode == 't':
+ s += 'stop'
+ # else:
+ # s += 'unrecognized vCont mode: ', str(mode)
print s
elif rsp:
if rsp[0] == 'T' or rsp[0] == 'S' or rsp[0] == 'W' or rsp[0] == 'X':
@@ -933,7 +944,7 @@ def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
def rsp_hex_big_endian(options, cmd, cmd_args, rsp):
if rsp == '':
print "%s%s is not supported" % (cmd, cmd_args)
- else:
+ else:
packet = Packet(rsp)
uval = packet.get_hex_uint('big')
print '%s: 0x%x' % (cmd, uval)
@@ -1225,6 +1236,7 @@ gdb_remote_commands = {
'qHostInfo': {'cmd': cmd_query_packet, 'rsp': rsp_dump_key_value_pairs, 'name': "get host information"},
'qC': {'cmd': cmd_qC, 'rsp': rsp_qC, 'name': "return the current thread ID"},
'vCont': {'cmd': cmd_vCont, 'rsp': rsp_vCont, 'name': "extended continue command"},
+ 'qSpeedTest': {'cmd':cmd_qSpeedTest, 'rsp': rsp_qSpeedTest, 'name': 'speed test packdet'},
'vAttach': {'cmd': cmd_vAttach, 'rsp': rsp_stop_reply, 'name': "attach to process"},
'c': {'cmd': cmd_c, 'rsp': rsp_stop_reply, 'name': "continue"},
's': {'cmd': cmd_s, 'rsp': rsp_stop_reply, 'name': "step"},
@@ -1283,6 +1295,49 @@ def parse_gdb_log_file(path, options):
f.close()
+def round_up(n, incr):
+ return float(((int(n) + incr) / incr) * incr)
+
+
+def plot_latencies(sec_times):
+ # import numpy as np
+ import matplotlib.pyplot as plt
+
+ for (i, name) in enumerate(sec_times.keys()):
+ times = sec_times[name]
+ if len(times) <= 1:
+ continue
+ plt.subplot(2, 1, 1)
+ plt.title('Packet "%s" Times' % (name))
+ plt.xlabel('Packet')
+ units = 'ms'
+ adj_times = []
+ max_time = 0.0
+ for time in times:
+ time = time * 1000.0
+ adj_times.append(time)
+ if time > max_time:
+ max_time = time
+ if max_time < 1.0:
+ units = 'us'
+ max_time = 0.0
+ for i in range(len(adj_times)):
+ adj_times[i] *= 1000.0
+ if adj_times[i] > max_time:
+ max_time = adj_times[i]
+ plt.ylabel('Time (%s)' % (units))
+ max_y = None
+ for i in [5.0, 10.0, 25.0, 50.0]:
+ if max_time < i:
+ max_y = round_up(max_time, i)
+ break
+ if max_y is None:
+ max_y = round_up(max_time, 100.0)
+ plt.ylim(0.0, max_y)
+ plt.plot(adj_times, 'o-')
+ plt.show()
+
+
def parse_gdb_log(file, options):
'''Parse a GDB log file that was generated by enabling logging with:
(lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
@@ -1306,10 +1361,11 @@ def parse_gdb_log(file, options):
base_time = 0.0
last_time = 0.0
- packet_send_time = 0.0
+ min_time = 100000000.0
packet_total_times = {}
- packet_times = []
- packet_count = {}
+ all_packet_times = []
+ packet_times = {}
+ packet_counts = {}
lines = file.read().splitlines()
last_command = None
last_command_args = None
@@ -1412,32 +1468,39 @@ def parse_gdb_log(file, options):
curr_time = float(match.group(2))
if last_time and not is_command:
delta = curr_time - last_time
- packet_times.append(delta)
+ all_packet_times.append(delta)
delta = 0.0
if base_time:
delta = curr_time - last_time
else:
base_time = curr_time
- if is_command:
- packet_send_time = curr_time
- elif line.find('read packet: $') >= 0 and packet_name:
- if packet_name in packet_total_times:
- packet_total_times[packet_name] += delta
- packet_count[packet_name] += 1
- else:
- packet_total_times[packet_name] = delta
- packet_count[packet_name] = 1
- packet_name = None
+ if not is_command:
+ if line.find('read packet: $') >= 0 and packet_name:
+ if packet_name in packet_total_times:
+ packet_total_times[packet_name] += delta
+ packet_counts[packet_name] += 1
+ else:
+ packet_total_times[packet_name] = delta
+ packet_counts[packet_name] = 1
+ if packet_name not in packet_times:
+ packet_times[packet_name] = []
+ packet_times[packet_name].append(delta)
+ packet_name = None
+ if min_time > delta:
+ min_time = delta
if not options or not options.quiet:
- print '%s%.6f %+.6f%s' % (match.group(1), curr_time - base_time, delta, match.group(3))
+ print '%s%.6f %+.6f%s' % (match.group(1),
+ curr_time - base_time,
+ delta,
+ match.group(3))
last_time = curr_time
# else:
# print line
- (average, std_dev) = calculate_mean_and_standard_deviation(packet_times)
+ (average, std_dev) = calculate_mean_and_standard_deviation(all_packet_times)
if average and std_dev:
- print '%u packets with average packet time of %f and standard deviation of %f' % (len(packet_times), average, std_dev)
+ print '%u packets with average packet time of %f and standard deviation of %f' % (len(all_packet_times), average, std_dev)
if packet_total_times:
total_packet_time = 0.0
total_packet_count = 0
@@ -1446,19 +1509,21 @@ def parse_gdb_log(file, options):
# print 'value = (%s) %s' % (type(vvv), vvv)
# if type(vvv) == 'float':
total_packet_time += vvv
- for key, vvv in packet_count.items():
+ for key, vvv in packet_counts.items():
total_packet_count += vvv
- print '#---------------------------------------------------'
+ print '#------------------------------------------------------------'
print '# Packet timing summary:'
- print '# Totals: time = %6f, count = %6d' % (total_packet_time, total_packet_count)
- print '#---------------------------------------------------'
- print '# Packet Time (sec) Percent Count '
- print '#------------------------- ---------- ------- ------'
+ print '# Totals: time = %6f, count = %6d' % (total_packet_time,
+ total_packet_count)
+ print '# Min packet time: time = %6f' % (min_time)
+ print '#------------------------------------------------------------'
+ print '# Packet Time (sec) Percent Count Latency'
+ print '#------------------------- ----------- ------- ------ -------'
if options and options.sort_count:
res = sorted(
- packet_count,
- key=packet_count.__getitem__,
+ packet_counts,
+ key=packet_counts.__getitem__,
reverse=True)
else:
res = sorted(
@@ -1471,11 +1536,12 @@ def parse_gdb_log(file, options):
packet_total_time = packet_total_times[item]
packet_percent = (
packet_total_time / total_packet_time) * 100.0
- if packet_percent >= 10.0:
- print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
- else:
- print " %24s %.6f %.2f%% %6d" % (item, packet_total_time, packet_percent, packet_count[item])
-
+ packet_count = packet_counts[item]
+ print " %24s %11.6f %5.2f%% %6d %9.6f" % (
+ item, packet_total_time, packet_percent, packet_count,
+ float(packet_total_time) / float(packet_count))
+ if options.plot:
+ plot_latencies(packet_times)
if __name__ == '__main__':
usage = "usage: gdbremote [options]"
@@ -1492,6 +1558,12 @@ if __name__ == '__main__':
help='display verbose debug info',
default=False)
parser.add_option(
+ '--plot',
+ action='store_true',
+ dest='plot',
+ help='plot packet latencies by packet type',
+ default=False)
+ parser.add_option(
'-q',
'--quiet',
action='store_true',
diff --git a/examples/synthetic/bitfield/program.cpp b/examples/synthetic/bitfield/program.cpp
index 1db4aa4e719e..d14edda30515 100644
--- a/examples/synthetic/bitfield/program.cpp
+++ b/examples/synthetic/bitfield/program.cpp
@@ -53,4 +53,4 @@ int main() {
MaskedData data_5(data_4.apply(), 0xFFAC, eMaskingOperatorNor);
MaskedData data_6(data_5.apply(), 0x0000BEEF, eMaskingOperatorAnd);
return data_6.apply(); // <-- what comes out of here?
-} \ No newline at end of file
+}
diff --git a/include/lldb/API/LLDB.h b/include/lldb/API/LLDB.h
index c51ced893d7a..2b3dd96aef0e 100644
--- a/include/lldb/API/LLDB.h
+++ b/include/lldb/API/LLDB.h
@@ -10,10 +10,6 @@
#ifndef LLDB_LLDB_h_
#define LLDB_LLDB_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBBlock.h"
diff --git a/include/lldb/API/SBAddress.h b/include/lldb/API/SBAddress.h
index 02e847b97aa1..891324254cd6 100644
--- a/include/lldb/API/SBAddress.h
+++ b/include/lldb/API/SBAddress.h
@@ -82,6 +82,7 @@ public:
protected:
friend class SBBlock;
+ friend class SBBreakpoint;
friend class SBBreakpointLocation;
friend class SBFrame;
friend class SBFunction;
diff --git a/include/lldb/API/SBBreakpoint.h b/include/lldb/API/SBBreakpoint.h
index 216d675b9d22..2c93bf103e3e 100644
--- a/include/lldb/API/SBBreakpoint.h
+++ b/include/lldb/API/SBBreakpoint.h
@@ -23,6 +23,8 @@ public:
SBBreakpoint(const lldb::SBBreakpoint &rhs);
+ SBBreakpoint(const lldb::BreakpointSP &bp_sp);
+
~SBBreakpoint();
const lldb::SBBreakpoint &operator=(const lldb::SBBreakpoint &rhs);
@@ -127,14 +129,18 @@ public:
static uint32_t
GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp);
+ bool IsHardware() const;
+
+ // Can only be called from a ScriptedBreakpointResolver...
+ SBError
+ AddLocation(SBAddress &address);
+
private:
friend class SBBreakpointList;
friend class SBBreakpointLocation;
friend class SBBreakpointName;
friend class SBTarget;
- SBBreakpoint(const lldb::BreakpointSP &bp_sp);
-
lldb::BreakpointSP GetSP() const;
lldb::BreakpointWP m_opaque_wp;
diff --git a/include/lldb/API/SBCommandInterpreter.h b/include/lldb/API/SBCommandInterpreter.h
index 8b9f06599366..f98894478811 100644
--- a/include/lldb/API/SBCommandInterpreter.h
+++ b/include/lldb/API/SBCommandInterpreter.h
@@ -10,12 +10,8 @@
#ifndef LLDB_SBCommandInterpreter_h_
#define LLDB_SBCommandInterpreter_h_
-// C Includes
-// C++ Includes
#include <memory>
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBDefines.h"
@@ -45,6 +41,10 @@ public:
void SetEchoCommands(bool);
+ bool GetEchoCommentCommands() const;
+
+ void SetEchoCommentCommands(bool echo);
+
bool GetPrintResults() const;
void SetPrintResults(bool);
@@ -162,6 +162,20 @@ public:
int match_start_point, int max_return_elements,
lldb::SBStringList &matches);
+ // Same as HandleCompletion, but also fills out `descriptions` with
+ // descriptions for each match.
+ int HandleCompletionWithDescriptions(
+ const char *current_line, const char *cursor, const char *last_char,
+ int match_start_point, int max_return_elements,
+ lldb::SBStringList &matches, lldb::SBStringList &descriptions);
+
+ int HandleCompletionWithDescriptions(const char *current_line,
+ uint32_t cursor_pos,
+ int match_start_point,
+ int max_return_elements,
+ lldb::SBStringList &matches,
+ lldb::SBStringList &descriptions);
+
bool WasInterrupted() const;
// Catch commands before they execute by registering a callback that will get
diff --git a/include/lldb/API/SBCommandReturnObject.h b/include/lldb/API/SBCommandReturnObject.h
index a372ea2ad9ee..798aa92a7ef2 100644
--- a/include/lldb/API/SBCommandReturnObject.h
+++ b/include/lldb/API/SBCommandReturnObject.h
@@ -10,14 +10,10 @@
#ifndef LLDB_SBCommandReturnObject_h_
#define LLDB_SBCommandReturnObject_h_
-// C Includes
#include <stdio.h>
-// C++ Includes
#include <memory>
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBDefines.h"
namespace lldb {
diff --git a/include/lldb/API/SBDebugger.h b/include/lldb/API/SBDebugger.h
index a416b460f318..3f31bf16da8d 100644
--- a/include/lldb/API/SBDebugger.h
+++ b/include/lldb/API/SBDebugger.h
@@ -13,6 +13,7 @@
#include <stdio.h>
#include "lldb/API/SBDefines.h"
+#include "lldb/API/SBInitializerOptions.h"
#include "lldb/API/SBPlatform.h"
namespace lldb {
@@ -45,6 +46,7 @@ public:
lldb::SBDebugger &operator=(const lldb::SBDebugger &rhs);
static void Initialize();
+ static lldb::SBError Initialize(SBInitializerOptions &options);
static void Terminate();
@@ -109,7 +111,7 @@ public:
const char *archname);
lldb::SBTarget CreateTarget(const char *filename);
-
+
lldb::SBTarget GetDummyTarget();
// Return true if target is deleted from the target list of the debugger.
@@ -226,6 +228,8 @@ public:
void SetPrompt(const char *prompt);
+ const char *GetReproducerPath() const;
+
lldb::ScriptLanguage GetScriptLanguage() const;
void SetScriptLanguage(lldb::ScriptLanguage script_lang);
diff --git a/include/lldb/API/SBDefines.h b/include/lldb/API/SBDefines.h
index ec92c9196737..c5c9851272f2 100644
--- a/include/lldb/API/SBDefines.h
+++ b/include/lldb/API/SBDefines.h
@@ -10,10 +10,6 @@
#ifndef LLDB_SBDefines_h_
#define LLDB_SBDefines_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
@@ -55,6 +51,7 @@ class LLDB_API SBFileSpecList;
class LLDB_API SBFrame;
class LLDB_API SBFunction;
class LLDB_API SBHostOS;
+class LLDB_API SBInitializerOptions;
class LLDB_API SBInstruction;
class LLDB_API SBInstructionList;
class LLDB_API SBLanguageRuntime;
diff --git a/include/lldb/API/SBExpressionOptions.h b/include/lldb/API/SBExpressionOptions.h
index 1459ba6fee2a..b861436caf98 100644
--- a/include/lldb/API/SBExpressionOptions.h
+++ b/include/lldb/API/SBExpressionOptions.h
@@ -90,6 +90,12 @@ public:
bool GetTopLevel();
void SetTopLevel(bool b = true);
+
+ // Gets whether we will JIT an expression if it cannot be interpreted
+ bool GetAllowJIT();
+
+ // Sets whether we will JIT an expression if it cannot be interpreted
+ void SetAllowJIT(bool allow);
protected:
SBExpressionOptions(
diff --git a/include/lldb/API/SBFileSpec.h b/include/lldb/API/SBFileSpec.h
index 33e48f5c7c41..9ad1a5df0cfa 100644
--- a/include/lldb/API/SBFileSpec.h
+++ b/include/lldb/API/SBFileSpec.h
@@ -59,6 +59,7 @@ private:
friend class SBDeclaration;
friend class SBFileSpecList;
friend class SBHostOS;
+ friend class SBInitializerOptions;
friend class SBLaunchInfo;
friend class SBLineEntry;
friend class SBModule;
@@ -67,8 +68,8 @@ private:
friend class SBProcess;
friend class SBProcessInfo;
friend class SBSourceManager;
- friend class SBThread;
friend class SBTarget;
+ friend class SBThread;
SBFileSpec(const lldb_private::FileSpec &fspec);
diff --git a/include/lldb/API/SBFrame.h b/include/lldb/API/SBFrame.h
index b8953dd13236..1123dade5de2 100644
--- a/include/lldb/API/SBFrame.h
+++ b/include/lldb/API/SBFrame.h
@@ -90,6 +90,10 @@ public:
bool IsInlined() const;
+ bool IsArtificial();
+
+ bool IsArtificial() const;
+
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
lldb::SBValue EvaluateExpression(const char *expr);
diff --git a/include/lldb/API/SBInitializerOptions.h b/include/lldb/API/SBInitializerOptions.h
new file mode 100644
index 000000000000..184c82df4f86
--- /dev/null
+++ b/include/lldb/API/SBInitializerOptions.h
@@ -0,0 +1,43 @@
+//===-- SBInitializerOptions.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_SBInitializerOptuions_h_
+#define LLDB_SBInitializerOptuions_h_
+
+#include "lldb/API/SBDefines.h"
+#include "lldb/API/SBFileSpec.h"
+
+namespace lldb_private {
+struct InitializerOptions;
+}
+
+namespace lldb {
+
+class LLDB_API SBInitializerOptions {
+public:
+ SBInitializerOptions();
+ SBInitializerOptions(const lldb::SBInitializerOptions &rhs);
+ ~SBInitializerOptions();
+ const SBInitializerOptions &operator=(const lldb::SBInitializerOptions &rhs);
+
+ void SetCaptureReproducer(bool b);
+ void SetReplayReproducer(bool b);
+ void SetReproducerPath(const char *path);
+
+ lldb_private::InitializerOptions &ref() const;
+
+private:
+ friend class SBDebugger;
+
+ std::unique_ptr<lldb_private::InitializerOptions> m_opaque_up;
+};
+
+} // namespace lldb
+
+#endif // LLDB_SBInitializerOptuions_h_
diff --git a/include/lldb/API/SBMemoryRegionInfo.h b/include/lldb/API/SBMemoryRegionInfo.h
index 297f877a6341..5675d93b8eaf 100644
--- a/include/lldb/API/SBMemoryRegionInfo.h
+++ b/include/lldb/API/SBMemoryRegionInfo.h
@@ -102,6 +102,7 @@ private:
const lldb_private::MemoryRegionInfo &ref() const;
+ // Unused.
SBMemoryRegionInfo(const lldb_private::MemoryRegionInfo *lldb_object_ptr);
lldb::MemoryRegionInfoUP m_opaque_ap;
diff --git a/include/lldb/API/SBMemoryRegionInfoList.h b/include/lldb/API/SBMemoryRegionInfoList.h
index 883a2224c92d..1e67997cdaf1 100644
--- a/include/lldb/API/SBMemoryRegionInfoList.h
+++ b/include/lldb/API/SBMemoryRegionInfoList.h
@@ -42,6 +42,12 @@ protected:
const MemoryRegionInfoListImpl &operator*() const;
private:
+ friend class SBProcess;
+
+ lldb_private::MemoryRegionInfos &ref();
+
+ const lldb_private::MemoryRegionInfos &ref() const;
+
std::unique_ptr<MemoryRegionInfoListImpl> m_opaque_ap;
};
diff --git a/include/lldb/API/SBModule.h b/include/lldb/API/SBModule.h
index d73267f8af50..7a10e9fc96b3 100644
--- a/include/lldb/API/SBModule.h
+++ b/include/lldb/API/SBModule.h
@@ -309,6 +309,7 @@ public:
lldb::SBFileSpec GetSymbolFileSpec() const;
lldb::SBAddress GetObjectFileHeaderAddress() const;
+ lldb::SBAddress GetObjectFileEntryPointAddress() const;
private:
friend class SBAddress;
diff --git a/include/lldb/API/SBProcess.h b/include/lldb/API/SBProcess.h
index 4ad24f63f076..69cf8b4ce854 100644
--- a/include/lldb/API/SBProcess.h
+++ b/include/lldb/API/SBProcess.h
@@ -318,11 +318,11 @@ public:
/// library name and a list of paths, searching along the list of
/// paths till you find a matching library.
///
- /// @param[in] local_spec
+ /// @param[in] image_spec
/// The name of the shared library that you want to load.
- /// If local_spec is a relative path, the relative path will be
+ /// If image_spec is a relative path, the relative path will be
/// appended to the search paths.
- /// If the local_spec is an absolute path, just the basename is used.
+ /// If the image_spec is an absolute path, just the basename is used.
///
/// @param[in] paths
/// A list of paths to search for the library whose basename is
diff --git a/include/lldb/API/SBStructuredData.h b/include/lldb/API/SBStructuredData.h
index ca8229a574df..629d4f3e35ee 100644
--- a/include/lldb/API/SBStructuredData.h
+++ b/include/lldb/API/SBStructuredData.h
@@ -22,6 +22,8 @@ public:
SBStructuredData(const lldb::SBStructuredData &rhs);
SBStructuredData(const lldb::EventSP &event_sp);
+
+ SBStructuredData(lldb_private::StructuredDataImpl *impl);
~SBStructuredData();
@@ -41,7 +43,7 @@ public:
/// Return the type of data in this data structure
//------------------------------------------------------------------
lldb::StructuredDataType GetType() const;
-
+
//------------------------------------------------------------------
/// Return the size (i.e. number of elements) in this data structure
/// if it is an array or dictionary type. For other types, 0 will be
@@ -50,6 +52,12 @@ public:
size_t GetSize() const;
//------------------------------------------------------------------
+ /// Fill keys with the keys in this object and return true if this data
+ /// structure is a dictionary. Returns false otherwise.
+ //------------------------------------------------------------------
+ bool GetKeys(lldb::SBStringList &keys) const;
+
+ //------------------------------------------------------------------
/// Return the value corresponding to a key if this data structure
/// is a dictionary type.
//------------------------------------------------------------------
diff --git a/include/lldb/API/SBSymbolContext.h b/include/lldb/API/SBSymbolContext.h
index 04ee15e8ecb1..9078b5b789e0 100644
--- a/include/lldb/API/SBSymbolContext.h
+++ b/include/lldb/API/SBSymbolContext.h
@@ -26,6 +26,8 @@ public:
SBSymbolContext(const lldb::SBSymbolContext &rhs);
+ SBSymbolContext(const lldb_private::SymbolContext *sc_ptr);
+
~SBSymbolContext();
bool IsValid() const;
@@ -69,8 +71,6 @@ protected:
lldb_private::SymbolContext *get() const;
- SBSymbolContext(const lldb_private::SymbolContext *sc_ptr);
-
void SetSymbolContext(const lldb_private::SymbolContext *sc_ptr);
private:
diff --git a/include/lldb/API/SBTarget.h b/include/lldb/API/SBTarget.h
index 8d99545902fe..18de267fee00 100644
--- a/include/lldb/API/SBTarget.h
+++ b/include/lldb/API/SBTarget.h
@@ -10,10 +10,6 @@
#ifndef LLDB_SBTarget_h_
#define LLDB_SBTarget_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBAttachInfo.h"
#include "lldb/API/SBBreakpoint.h"
@@ -75,6 +71,31 @@ public:
lldb::SBProcess GetProcess();
+ //------------------------------------------------------------------
+ /// Sets whether we should collect statistics on lldb or not.
+ ///
+ /// @param[in] v
+ /// A boolean to control the collection.
+ /// @return
+ /// void
+ //------------------------------------------------------------------
+ void SetCollectingStats(bool v);
+
+ //------------------------------------------------------------------
+ /// Returns whether statistics collection are enabled.
+ ///
+ /// @return
+ /// true if statistics are currently being collected, false
+ /// otherwise.
+ //------------------------------------------------------------------
+ bool GetCollectingStats();
+
+ //------------------------------------------------------------------
+ /// Returns a dump of the collected statistics.
+ ///
+ /// @return
+ /// A SBStructuredData with the statistics collected.
+ //------------------------------------------------------------------
lldb::SBStructuredData GetStatistics();
//------------------------------------------------------------------
@@ -272,6 +293,10 @@ public:
lldb::SBFileSpec GetExecutable();
+ // Append the path mapping (from -> to) to the target's paths mapping list.
+ void AppendImageSearchPath(const char *from, const char *to,
+ lldb::SBError &error);
+
bool AddModule(lldb::SBModule &module);
lldb::SBModule AddModule(const char *path, const char *triple,
@@ -576,6 +601,11 @@ public:
BreakpointCreateByLocation(const lldb::SBFileSpec &file_spec, uint32_t line,
lldb::addr_t offset, SBFileSpecList &module_list);
+ lldb::SBBreakpoint
+ BreakpointCreateByLocation(const lldb::SBFileSpec &file_spec, uint32_t line,
+ uint32_t column, lldb::addr_t offset,
+ SBFileSpecList &module_list);
+
lldb::SBBreakpoint BreakpointCreateByName(const char *symbol_name,
const char *module_name = nullptr);
@@ -653,6 +683,37 @@ public:
lldb::SBBreakpoint BreakpointCreateByAddress(addr_t address);
lldb::SBBreakpoint BreakpointCreateBySBAddress(SBAddress &address);
+
+ //------------------------------------------------------------------
+ /// Create a breakpoint using a scripted resolver.
+ ///
+ /// @param[in] class_name
+ /// This is the name of the class that implements a scripted resolver.
+ ///
+ /// @param[in] extra_args
+ /// This is an SBStructuredData object that will get passed to the
+ /// constructor of the class in class_name. You can use this to
+ /// reuse the same class, parametrizing with entries from this
+ /// dictionary.
+ ///
+ /// @param module_list
+ /// If this is non-empty, this will be used as the module filter in the
+ /// SearchFilter created for this breakpoint.
+ ///
+ /// @param file_list
+ /// If this is non-empty, this will be used as the comp unit filter in the
+ /// SearchFilter created for this breakpoint.
+ ///
+ /// @return
+ /// An SBBreakpoint that will set locations based on the logic in the
+ /// resolver's search callback.
+ //------------------------------------------------------------------
+ lldb::SBBreakpoint BreakpointCreateFromScript(
+ const char *class_name,
+ SBStructuredData &extra_args,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &file_list,
+ bool request_hardware = false);
//------------------------------------------------------------------
/// Read breakpoints from source_file and return the newly created
@@ -842,6 +903,7 @@ protected:
friend class SBSourceManager;
friend class SBSymbol;
friend class SBValue;
+ friend class SBVariablesOptions;
//------------------------------------------------------------------
// Constructors are private, use static Target::Create function to create an
diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h
index afc05d2c61ad..63816eef51b7 100644
--- a/include/lldb/API/SBThread.h
+++ b/include/lldb/API/SBThread.h
@@ -198,6 +198,10 @@ public:
uint32_t GetExtendedBacktraceOriginatingIndexID();
+ SBValue GetCurrentException();
+
+ SBThread GetCurrentExceptionBacktrace();
+
bool SafeToCallFunctions();
#ifndef SWIG
diff --git a/include/lldb/API/SBThreadPlan.h b/include/lldb/API/SBThreadPlan.h
index abc14bf8fe4a..5084a427e1b8 100644
--- a/include/lldb/API/SBThreadPlan.h
+++ b/include/lldb/API/SBThreadPlan.h
@@ -79,14 +79,28 @@ public:
// plans...
SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address,
lldb::addr_t range_size);
+ SBThreadPlan QueueThreadPlanForStepOverRange(SBAddress &start_address,
+ lldb::addr_t range_size,
+ SBError &error);
SBThreadPlan QueueThreadPlanForStepInRange(SBAddress &start_address,
lldb::addr_t range_size);
+ SBThreadPlan QueueThreadPlanForStepInRange(SBAddress &start_address,
+ lldb::addr_t range_size,
+ SBError &error);
SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
bool first_insn = false);
+ SBThreadPlan QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
+ bool first_insn, SBError &error);
SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address);
+ SBThreadPlan QueueThreadPlanForRunToAddress(SBAddress address,
+ SBError &error);
+
+ SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name);
+ SBThreadPlan QueueThreadPlanForStepScripted(const char *script_class_name,
+ SBError &error);
#ifndef SWIG
lldb_private::ThreadPlan *get();
diff --git a/include/lldb/API/SBVariablesOptions.h b/include/lldb/API/SBVariablesOptions.h
index 756da6439e3b..0059a41129c5 100644
--- a/include/lldb/API/SBVariablesOptions.h
+++ b/include/lldb/API/SBVariablesOptions.h
@@ -33,6 +33,10 @@ public:
void SetIncludeArguments(bool);
+ bool GetIncludeRecognizedArguments(const lldb::SBTarget &) const;
+
+ void SetIncludeRecognizedArguments(bool);
+
bool GetIncludeLocals() const;
void SetIncludeLocals(bool);
diff --git a/include/lldb/Breakpoint/Breakpoint.h b/include/lldb/Breakpoint/Breakpoint.h
index ec4bc946280f..5861a3be36e1 100644
--- a/include/lldb/Breakpoint/Breakpoint.h
+++ b/include/lldb/Breakpoint/Breakpoint.h
@@ -10,23 +10,19 @@
#ifndef liblldb_Breakpoint_h_
#define liblldb_Breakpoint_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Breakpoint/BreakpointLocationList.h"
#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/Stoppoint.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/StructuredData.h"
@@ -503,6 +499,14 @@ public:
size_t GetNumResolvedLocations() const;
//------------------------------------------------------------------
+ /// Return whether this breakpoint has any resolved locations.
+ ///
+ /// @return
+ /// True if GetNumResolvedLocations > 0
+ //------------------------------------------------------------------
+ bool HasResolvedLocations() const;
+
+ //------------------------------------------------------------------
/// Return the number of breakpoint locations.
///
/// @return
diff --git a/include/lldb/Breakpoint/BreakpointID.h b/include/lldb/Breakpoint/BreakpointID.h
index bbad45ca2d8b..5acb942ed2ad 100644
--- a/include/lldb/Breakpoint/BreakpointID.h
+++ b/include/lldb/Breakpoint/BreakpointID.h
@@ -10,10 +10,6 @@
#ifndef liblldb_BreakpointID_h_
#define liblldb_BreakpointID_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Breakpoint/BreakpointIDList.h b/include/lldb/Breakpoint/BreakpointIDList.h
index ec305583e8d9..2820b9fdcaa5 100644
--- a/include/lldb/Breakpoint/BreakpointIDList.h
+++ b/include/lldb/Breakpoint/BreakpointIDList.h
@@ -10,13 +10,9 @@
#ifndef liblldb_BreakpointIDList_h_
#define liblldb_BreakpointIDList_h_
-// C Includes
-// C++ Includes
#include <utility>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/Breakpoint/BreakpointID.h"
diff --git a/include/lldb/Breakpoint/BreakpointList.h b/include/lldb/Breakpoint/BreakpointList.h
index f4c013d41cc2..c4fc650a29f0 100644
--- a/include/lldb/Breakpoint/BreakpointList.h
+++ b/include/lldb/Breakpoint/BreakpointList.h
@@ -10,13 +10,9 @@
#ifndef liblldb_BreakpointList_h_
#define liblldb_BreakpointList_h_
-// C Includes
-// C++ Includes
#include <list>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
namespace lldb_private {
@@ -54,18 +50,6 @@ public:
void Dump(Stream *s) const;
//------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint with id \a breakID.
- ///
- /// @param[in] breakID
- /// The breakpoint ID to seek for.
- ///
- /// @result
- /// A shared pointer to the breakpoint. May contain a NULL pointer if the
- /// breakpoint doesn't exist.
- //------------------------------------------------------------------
- lldb::BreakpointSP FindBreakpointByID(lldb::break_id_t breakID);
-
- //------------------------------------------------------------------
/// Returns a shared pointer to the breakpoint with id \a breakID. Const
/// version.
///
@@ -76,7 +60,7 @@ public:
/// A shared pointer to the breakpoint. May contain a NULL pointer if the
/// breakpoint doesn't exist.
//------------------------------------------------------------------
- const lldb::BreakpointSP FindBreakpointByID(lldb::break_id_t breakID) const;
+ lldb::BreakpointSP FindBreakpointByID(lldb::break_id_t breakID) const;
//------------------------------------------------------------------
/// Returns a shared pointer to the breakpoint with index \a i.
@@ -88,20 +72,7 @@ public:
/// A shared pointer to the breakpoint. May contain a NULL pointer if the
/// breakpoint doesn't exist.
//------------------------------------------------------------------
- lldb::BreakpointSP GetBreakpointAtIndex(size_t i);
-
- //------------------------------------------------------------------
- /// Returns a shared pointer to the breakpoint with index \a i, const
- /// version
- ///
- /// @param[in] i
- /// The breakpoint index to seek for.
- ///
- /// @result
- /// A shared pointer to the breakpoint. May contain a NULL pointer if the
- /// breakpoint doesn't exist.
- //------------------------------------------------------------------
- const lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const;
+ lldb::BreakpointSP GetBreakpointAtIndex(size_t i) const;
//------------------------------------------------------------------
/// Find all the breakpoints with a given name
@@ -201,7 +172,7 @@ public:
void GetListMutex(std::unique_lock<std::recursive_mutex> &lock);
protected:
- typedef std::list<lldb::BreakpointSP> bp_collection;
+ typedef std::vector<lldb::BreakpointSP> bp_collection;
bp_collection::iterator GetBreakpointIDIterator(lldb::break_id_t breakID);
@@ -211,7 +182,7 @@ protected:
std::recursive_mutex &GetMutex() const { return m_mutex; }
mutable std::recursive_mutex m_mutex;
- bp_collection m_breakpoints; // The breakpoint list, currently a list.
+ bp_collection m_breakpoints;
lldb::break_id_t m_next_break_id;
bool m_is_internal;
diff --git a/include/lldb/Breakpoint/BreakpointLocation.h b/include/lldb/Breakpoint/BreakpointLocation.h
index c5911085e61b..6448cb16e927 100644
--- a/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/include/lldb/Breakpoint/BreakpointLocation.h
@@ -10,13 +10,9 @@
#ifndef liblldb_BreakpointLocation_h_
#define liblldb_BreakpointLocation_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/StoppointLocation.h"
#include "lldb/Core/Address.h"
diff --git a/include/lldb/Breakpoint/BreakpointLocationCollection.h b/include/lldb/Breakpoint/BreakpointLocationCollection.h
index 579d468647f3..5a188539622b 100644
--- a/include/lldb/Breakpoint/BreakpointLocationCollection.h
+++ b/include/lldb/Breakpoint/BreakpointLocationCollection.h
@@ -10,13 +10,9 @@
#ifndef liblldb_BreakpointLocationCollection_h_
#define liblldb_BreakpointLocationCollection_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Iterable.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Breakpoint/BreakpointLocationList.h b/include/lldb/Breakpoint/BreakpointLocationList.h
index 4e61abb2838e..01ee5b5dcce9 100644
--- a/include/lldb/Breakpoint/BreakpointLocationList.h
+++ b/include/lldb/Breakpoint/BreakpointLocationList.h
@@ -10,14 +10,10 @@
#ifndef liblldb_BreakpointLocationList_h_
#define liblldb_BreakpointLocationList_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Utility/Iterable.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Breakpoint/BreakpointName.h b/include/lldb/Breakpoint/BreakpointName.h
index 292a0de4f48b..5e5a04fe9117 100644
--- a/include/lldb/Breakpoint/BreakpointName.h
+++ b/include/lldb/Breakpoint/BreakpointName.h
@@ -10,22 +10,18 @@
#ifndef liblldb_Breakpoint_Name_h_
#define liblldb_Breakpoint_Name_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
#include <unordered_set>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Breakpoint/BreakpointLocationList.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/Stoppoint.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/include/lldb/Breakpoint/BreakpointOptions.h b/include/lldb/Breakpoint/BreakpointOptions.h
index 84821817f980..e91df20ed305 100644
--- a/include/lldb/Breakpoint/BreakpointOptions.h
+++ b/include/lldb/Breakpoint/BreakpointOptions.h
@@ -10,13 +10,9 @@
#ifndef liblldb_BreakpointOptions_h_
#define liblldb_BreakpointOptions_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Baton.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/StringList.h"
diff --git a/include/lldb/Breakpoint/BreakpointResolver.h b/include/lldb/Breakpoint/BreakpointResolver.h
index 944741308da6..32008f3dd96f 100644
--- a/include/lldb/Breakpoint/BreakpointResolver.h
+++ b/include/lldb/Breakpoint/BreakpointResolver.h
@@ -10,10 +10,6 @@
#ifndef liblldb_BreakpointResolver_h_
#define liblldb_BreakpointResolver_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/SearchFilter.h"
@@ -158,6 +154,7 @@ public:
AddressResolver, // This is an instance of BreakpointResolverAddress
NameResolver, // This is an instance of BreakpointResolverName
FileRegexResolver,
+ PythonResolver,
ExceptionResolver,
LastKnownResolverType = ExceptionResolver,
UnknownResolver
@@ -200,17 +197,23 @@ protected:
Inlines,
LanguageName,
LineNumber,
+ Column,
ModuleName,
NameMaskArray,
Offset,
+ PythonClassName,
RegexString,
+ ScriptArgs,
SectionName,
+ SearchDepth,
SkipPrologue,
SymbolNameArray,
LastOptionName
};
static const char
*g_option_names[static_cast<uint32_t>(OptionNames::LastOptionName)];
+
+ virtual void NotifyBreakpointSet() {};
public:
static const char *GetKey(OptionNames enum_value) {
@@ -224,8 +227,11 @@ protected:
/// 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.
+ /// When \p column is nonzero the \p line and \p column args are used to
+ /// filter the results to find the first breakpoint >= (line, column).
void SetSCMatchesByLine(SearchFilter &filter, SymbolContextList &sc_list,
- bool skip_prologue, llvm::StringRef log_ident);
+ bool skip_prologue, llvm::StringRef log_ident,
+ uint32_t line = 0, uint32_t column = 0);
void SetSCMatchesByLine(SearchFilter &, SymbolContextList &, bool,
const char *) = delete;
@@ -237,6 +243,10 @@ protected:
// breakpoints we set.
private:
+ /// Helper for \p SetSCMatchesByLine.
+ void AddLocation(SearchFilter &filter, const SymbolContext &sc,
+ bool skip_prologue, llvm::StringRef log_ident);
+
// Subclass identifier (for llvm isa/dyn_cast)
const unsigned char SubclassID;
DISALLOW_COPY_AND_ASSIGN(BreakpointResolver);
diff --git a/include/lldb/Breakpoint/BreakpointResolverAddress.h b/include/lldb/Breakpoint/BreakpointResolverAddress.h
index 5845fe7cabed..5d8c0b6b7530 100644
--- a/include/lldb/Breakpoint/BreakpointResolverAddress.h
+++ b/include/lldb/Breakpoint/BreakpointResolverAddress.h
@@ -10,10 +10,6 @@
#ifndef liblldb_BreakpointResolverAddress_h_
#define liblldb_BreakpointResolverAddress_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Core/ModuleSpec.h"
@@ -51,7 +47,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
diff --git a/include/lldb/Breakpoint/BreakpointResolverFileLine.h b/include/lldb/Breakpoint/BreakpointResolverFileLine.h
index 3464f8ea80d8..8671cd2e5562 100644
--- a/include/lldb/Breakpoint/BreakpointResolverFileLine.h
+++ b/include/lldb/Breakpoint/BreakpointResolverFileLine.h
@@ -10,10 +10,6 @@
#ifndef liblldb_BreakpointResolverFileLine_h_
#define liblldb_BreakpointResolverFileLine_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
namespace lldb_private {
@@ -28,9 +24,9 @@ namespace lldb_private {
class BreakpointResolverFileLine : public BreakpointResolver {
public:
BreakpointResolverFileLine(Breakpoint *bkpt, const FileSpec &resolver,
- uint32_t line_no, lldb::addr_t m_offset,
- bool check_inlines, bool skip_prologue,
- bool exact_match);
+ uint32_t line_no, uint32_t column,
+ lldb::addr_t m_offset, bool check_inlines,
+ bool skip_prologue, bool exact_match);
static BreakpointResolver *
CreateFromStructuredData(Breakpoint *bkpt,
@@ -45,7 +41,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
@@ -65,10 +61,11 @@ protected:
void FilterContexts(SymbolContextList &sc_list, bool is_relative);
friend class Breakpoint;
- FileSpec m_file_spec; // This is the file spec we are looking for.
- uint32_t m_line_number; // This is the line number that we are looking for.
- bool m_inlines; // This determines whether the resolver looks for inlined
- // functions or not.
+ FileSpec m_file_spec; ///< This is the file spec we are looking for.
+ uint32_t m_line_number; ///< This is the line number that we are looking for.
+ uint32_t m_column; ///< This is the column that we are looking for.
+ bool m_inlines; ///< This determines whether the resolver looks for inlined
+ ///< functions or not.
bool m_skip_prologue;
bool m_exact_match;
diff --git a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
index c1a7a15566a5..db4f67cf3951 100644
--- a/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
+++ b/include/lldb/Breakpoint/BreakpointResolverFileRegex.h
@@ -11,11 +11,7 @@
#ifndef liblldb_BreakpointResolverFileRegex_h_
#define liblldb_BreakpointResolverFileRegex_h_
-// C Includes
-// C++ Includes
#include <set>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Utility/ConstString.h"
@@ -47,7 +43,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
diff --git a/include/lldb/Breakpoint/BreakpointResolverName.h b/include/lldb/Breakpoint/BreakpointResolverName.h
index 794ea67bb721..416e1aa301b1 100644
--- a/include/lldb/Breakpoint/BreakpointResolverName.h
+++ b/include/lldb/Breakpoint/BreakpointResolverName.h
@@ -10,13 +10,9 @@
#ifndef liblldb_BreakpointResolverName_h_
#define liblldb_BreakpointResolverName_h_
-// C Includes
-// C++ Includes
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Core/Module.h"
@@ -31,20 +27,23 @@ namespace lldb_private {
class BreakpointResolverName : public BreakpointResolver {
public:
BreakpointResolverName(Breakpoint *bkpt, const char *name,
- uint32_t name_type_mask, lldb::LanguageType language,
+ lldb::FunctionNameType name_type_mask,
+ lldb::LanguageType language,
Breakpoint::MatchType type, lldb::addr_t offset,
bool skip_prologue);
// This one takes an array of names. It is always MatchType = Exact.
BreakpointResolverName(Breakpoint *bkpt, const char *names[],
- size_t num_names, uint32_t name_type_mask,
+ size_t num_names,
+ lldb::FunctionNameType name_type_mask,
lldb::LanguageType language, lldb::addr_t offset,
bool skip_prologue);
// This one takes a C++ array of names. It is always MatchType = Exact.
BreakpointResolverName(Breakpoint *bkpt, std::vector<std::string> names,
- uint32_t name_type_mask, lldb::LanguageType language,
- lldb::addr_t offset, bool skip_prologue);
+ lldb::FunctionNameType name_type_mask,
+ lldb::LanguageType language, lldb::addr_t offset,
+ bool skip_prologue);
// Creates a function breakpoint by regular expression. Takes over control
// of the lifespan of func_regex.
@@ -65,7 +64,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
@@ -89,7 +88,8 @@ protected:
lldb::LanguageType m_language;
bool m_skip_prologue;
- void AddNameLookup(const ConstString &name, uint32_t name_type_mask);
+ void AddNameLookup(const ConstString &name,
+ lldb::FunctionNameType name_type_mask);
};
} // namespace lldb_private
diff --git a/include/lldb/Breakpoint/BreakpointResolverScripted.h b/include/lldb/Breakpoint/BreakpointResolverScripted.h
new file mode 100644
index 000000000000..aaa9cbe4d354
--- /dev/null
+++ b/include/lldb/Breakpoint/BreakpointResolverScripted.h
@@ -0,0 +1,81 @@
+//===-- BreakpointResolverScripted.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_BreakpointResolverScripted_h_
+#define liblldb_BreakpointResolverScripted_h_
+
+#include "lldb/lldb-forward.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Core/ModuleSpec.h"
+
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class BreakpointResolverScripted BreakpointResolverScripted.h
+/// "lldb/Breakpoint/BreakpointResolverScripted.h" This class sets breakpoints
+/// on a given Address. This breakpoint only takes once, and then it won't
+/// attempt to reset itself.
+//----------------------------------------------------------------------
+
+class BreakpointResolverScripted : public BreakpointResolver {
+public:
+ BreakpointResolverScripted(Breakpoint *bkpt,
+ const llvm::StringRef class_name,
+ lldb::SearchDepth depth,
+ StructuredDataImpl *args_data,
+ ScriptInterpreter &script_interp);
+
+ ~BreakpointResolverScripted() override;
+
+ static BreakpointResolver *
+ CreateFromStructuredData(Breakpoint *bkpt,
+ const StructuredData::Dictionary &options_dict,
+ Status &error);
+
+ StructuredData::ObjectSP SerializeToStructuredData() override;
+
+ Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
+ SymbolContext &context, Address *addr,
+ bool containing) override;
+
+ lldb::SearchDepth GetDepth() override;
+
+ void GetDescription(Stream *s) override;
+
+ void Dump(Stream *s) const override;
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ static inline bool classof(const BreakpointResolverScripted *) { return true; }
+ static inline bool classof(const BreakpointResolver *V) {
+ return V->getResolverID() == BreakpointResolver::PythonResolver;
+ }
+
+ lldb::BreakpointResolverSP CopyForBreakpoint(Breakpoint &breakpoint) override;
+
+protected:
+ void NotifyBreakpointSet() override;
+private:
+ void CreateImplementationIfNeeded();
+ ScriptInterpreter *GetScriptInterpreter();
+
+ std::string m_class_name;
+ lldb::SearchDepth m_depth;
+ StructuredDataImpl *m_args_ptr; // We own this, but the implementation
+ // has to manage the UP (since that is
+ // how it gets stored in the
+ // SBStructuredData).
+ StructuredData::GenericSP m_implementation_sp;
+
+ DISALLOW_COPY_AND_ASSIGN(BreakpointResolverScripted);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_BreakpointResolverScripted_h_
diff --git a/include/lldb/Breakpoint/BreakpointSite.h b/include/lldb/Breakpoint/BreakpointSite.h
index c9bd883ca738..8d1d69076b1c 100644
--- a/include/lldb/Breakpoint/BreakpointSite.h
+++ b/include/lldb/Breakpoint/BreakpointSite.h
@@ -10,15 +10,11 @@
#ifndef liblldb_BreakpointSite_h_
#define liblldb_BreakpointSite_h_
-// C Includes
-// C++ Includes
#include <list>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Breakpoint/StoppointLocation.h"
#include "lldb/Utility/UserID.h"
diff --git a/include/lldb/Breakpoint/BreakpointSiteList.h b/include/lldb/Breakpoint/BreakpointSiteList.h
index d6530c170430..2f2e31cd3126 100644
--- a/include/lldb/Breakpoint/BreakpointSiteList.h
+++ b/include/lldb/Breakpoint/BreakpointSiteList.h
@@ -10,14 +10,10 @@
#ifndef liblldb_BreakpointSiteList_h_
#define liblldb_BreakpointSiteList_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <map>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointSite.h"
namespace lldb_private {
diff --git a/include/lldb/Breakpoint/Stoppoint.h b/include/lldb/Breakpoint/Stoppoint.h
index 3195ef942d9e..78baa6ce6cbb 100644
--- a/include/lldb/Breakpoint/Stoppoint.h
+++ b/include/lldb/Breakpoint/Stoppoint.h
@@ -10,10 +10,6 @@
#ifndef liblldb_Stoppoint_h_
#define liblldb_Stoppoint_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Breakpoint/StoppointLocation.h b/include/lldb/Breakpoint/StoppointLocation.h
index 5c717bbc3b0f..5c78d2e3d659 100644
--- a/include/lldb/Breakpoint/StoppointLocation.h
+++ b/include/lldb/Breakpoint/StoppointLocation.h
@@ -10,10 +10,6 @@
#ifndef liblldb_StoppointLocation_h_
#define liblldb_StoppointLocation_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
// #include "lldb/Breakpoint/BreakpointOptions.h"
diff --git a/include/lldb/Breakpoint/Watchpoint.h b/include/lldb/Breakpoint/Watchpoint.h
index 10df18a5c266..2aaae37eb095 100644
--- a/include/lldb/Breakpoint/Watchpoint.h
+++ b/include/lldb/Breakpoint/Watchpoint.h
@@ -10,13 +10,9 @@
#ifndef liblldb_Watchpoint_h_
#define liblldb_Watchpoint_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/StoppointLocation.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Symbol/CompilerType.h"
diff --git a/include/lldb/Breakpoint/WatchpointList.h b/include/lldb/Breakpoint/WatchpointList.h
index d5e0da444afb..9bfa817456bc 100644
--- a/include/lldb/Breakpoint/WatchpointList.h
+++ b/include/lldb/Breakpoint/WatchpointList.h
@@ -10,14 +10,10 @@
#ifndef liblldb_WatchpointList_h_
#define liblldb_WatchpointList_h_
-// C Includes
-// C++ Includes
#include <list>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Breakpoint/WatchpointOptions.h b/include/lldb/Breakpoint/WatchpointOptions.h
index 8cb3b97f3a62..0f4f399b5e4d 100644
--- a/include/lldb/Breakpoint/WatchpointOptions.h
+++ b/include/lldb/Breakpoint/WatchpointOptions.h
@@ -10,13 +10,9 @@
#ifndef liblldb_WatchpointOptions_h_
#define liblldb_WatchpointOptions_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Baton.h"
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Core/Address.h b/include/lldb/Core/Address.h
index 617aaefe91c9..a02a0d45a082 100644
--- a/include/lldb/Core/Address.h
+++ b/include/lldb/Core/Address.h
@@ -10,13 +10,13 @@
#ifndef liblldb_Address_h_
#define liblldb_Address_h_
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-forward.h" // for SectionWP, SectionSP, ModuleSP
-#include "lldb/lldb-private-enumerations.h" // for AddressClass
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, UINT32_MAX, int64_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class Block;
@@ -508,9 +508,9 @@ public:
///
/// @see SymbolContextScope::CalculateSymbolContext(SymbolContext*)
//------------------------------------------------------------------
- uint32_t CalculateSymbolContext(
- SymbolContext *sc,
- uint32_t resolve_scope = lldb::eSymbolContextEverything) const;
+ uint32_t CalculateSymbolContext(SymbolContext *sc,
+ lldb::SymbolContextItem resolve_scope =
+ lldb::eSymbolContextEverything) const;
lldb::ModuleSP CalculateSymbolContextModule() const;
diff --git a/include/lldb/Core/AddressRange.h b/include/lldb/Core/AddressRange.h
index 9f69c87ee354..e3c820782aaf 100644
--- a/include/lldb/Core/AddressRange.h
+++ b/include/lldb/Core/AddressRange.h
@@ -11,10 +11,10 @@
#define liblldb_AddressRange_h_
#include "lldb/Core/Address.h"
-#include "lldb/lldb-forward.h" // for SectionSP
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class SectionList;
diff --git a/include/lldb/Core/AddressResolver.h b/include/lldb/Core/AddressResolver.h
index cfd103e0be01..32751d64d6b4 100644
--- a/include/lldb/Core/AddressResolver.h
+++ b/include/lldb/Core/AddressResolver.h
@@ -12,9 +12,9 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/SearchFilter.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
+#include "lldb/lldb-defines.h"
-#include <stddef.h> // for size_t
+#include <stddef.h>
#include <vector>
namespace lldb_private {
diff --git a/include/lldb/Core/AddressResolverFileLine.h b/include/lldb/Core/AddressResolverFileLine.h
index e434a62e0319..bee72245ee6b 100644
--- a/include/lldb/Core/AddressResolverFileLine.h
+++ b/include/lldb/Core/AddressResolverFileLine.h
@@ -11,11 +11,11 @@
#define liblldb_AddressResolverFileLine_h_
#include "lldb/Core/AddressResolver.h"
-#include "lldb/Core/SearchFilter.h" // for Searcher, Searcher::CallbackR...
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/lldb-defines.h"
-#include <stdint.h> // for uint32_t
+#include <stdint.h>
namespace lldb_private {
class Address;
@@ -47,7 +47,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
diff --git a/include/lldb/Core/AddressResolverName.h b/include/lldb/Core/AddressResolverName.h
index 49a805f2115a..b4291938b290 100644
--- a/include/lldb/Core/AddressResolverName.h
+++ b/include/lldb/Core/AddressResolverName.h
@@ -11,10 +11,10 @@
#define liblldb_AddressResolverName_h_
#include "lldb/Core/AddressResolver.h"
-#include "lldb/Core/SearchFilter.h" // for Searcher, Searcher::Call...
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
+#include "lldb/lldb-defines.h"
namespace lldb_private {
class Address;
@@ -52,7 +52,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
diff --git a/include/lldb/Core/Architecture.h b/include/lldb/Core/Architecture.h
index 3a5a9789223d..20537d67b02c 100644
--- a/include/lldb/Core/Architecture.h
+++ b/include/lldb/Core/Architecture.h
@@ -67,6 +67,51 @@ public:
virtual void AdjustBreakpointAddress(const Symbol &func,
Address &addr) const {}
+
+ //------------------------------------------------------------------
+ /// Get \a load_addr as a callable code load address for this target
+ ///
+ /// Take \a load_addr and potentially add any address bits that are
+ /// needed to make the address callable. For ARM this can set bit
+ /// zero (if it already isn't) if \a load_addr is a thumb function.
+ /// If \a addr_class is set to AddressClass::eInvalid, then the address
+ /// adjustment will always happen. If it is set to an address class
+ /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+ /// returned.
+ //------------------------------------------------------------------
+ virtual lldb::addr_t GetCallableLoadAddress(
+ lldb::addr_t addr, AddressClass addr_class = AddressClass::eInvalid) const {
+ return addr;
+ }
+
+ //------------------------------------------------------------------
+ /// Get \a load_addr as an opcode for this target.
+ ///
+ /// Take \a load_addr and potentially strip any address bits that are
+ /// needed to make the address point to an opcode. For ARM this can
+ /// clear bit zero (if it already isn't) if \a load_addr is a
+ /// thumb function and load_addr is in code.
+ /// If \a addr_class is set to AddressClass::eInvalid, then the address
+ /// adjustment will always happen. If it is set to an address class
+ /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+ /// returned.
+ //------------------------------------------------------------------
+
+ virtual lldb::addr_t GetOpcodeLoadAddress(
+ lldb::addr_t addr, AddressClass addr_class = AddressClass::eInvalid) const {
+ return addr;
+ }
+
+ // Get load_addr as breakable load address for this target. Take a addr and
+ // check if for any reason there is a better address than this to put a
+ // breakpoint on. If there is then return that address. For MIPS, if
+ // instruction at addr is a delay slot instruction then this method will find
+ // the address of its previous instruction and return that address.
+ virtual lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr,
+ Target &target) const {
+ return addr;
+ }
+
private:
Architecture(const Architecture &) = delete;
void operator=(const Architecture &) = delete;
diff --git a/include/lldb/Core/ClangForward.h b/include/lldb/Core/ClangForward.h
index b3cab8a22f21..3fc12a555301 100644
--- a/include/lldb/Core/ClangForward.h
+++ b/include/lldb/Core/ClangForward.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ClangForward_h_
#define liblldb_ClangForward_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#if defined(__cplusplus)
diff --git a/include/lldb/Core/Communication.h b/include/lldb/Core/Communication.h
index 3e29307039e4..f129b8f879d0 100644
--- a/include/lldb/Core/Communication.h
+++ b/include/lldb/Core/Communication.h
@@ -10,21 +10,21 @@
#ifndef liblldb_Communication_h_
#define liblldb_Communication_h_
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Host/HostThread.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Timeout.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ConnectionStatus, FLAGS_ANONYMOU...
-#include "lldb/lldb-forward.h" // for ConnectionSP
-#include "lldb/lldb-types.h" // for thread_arg_t, thread_result_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
#include <atomic>
#include <mutex>
-#include <ratio> // for micro
+#include <ratio>
#include <string>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint8_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class Connection;
diff --git a/include/lldb/Core/Debugger.h b/include/lldb/Core/Debugger.h
index cc7176e5c95d..09f75ef0f8c6 100644
--- a/include/lldb/Core/Debugger.h
+++ b/include/lldb/Core/Debugger.h
@@ -10,44 +10,40 @@
#ifndef liblldb_Debugger_h_
#define liblldb_Debugger_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <memory>
#include <vector>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Terminal.h"
-#include "lldb/Target/ExecutionContext.h" // for ExecutionContext
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/TargetList.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/Utility/Status.h" // for Status
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Status.h"
#include "lldb/Utility/UserID.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ScriptLanguage, Langua...
-#include "lldb/lldb-forward.h" // for StreamFileSP, DebuggerSP
-#include "lldb/lldb-private-enumerations.h" // for VarSetOperationType
-#include "lldb/lldb-private-types.h" // for LoadPluginCallbackType
-#include "lldb/lldb-types.h" // for LogOutputCallback, thr...
-
-#include "llvm/ADT/ArrayRef.h" // for ArrayRef
-#include "llvm/ADT/StringMap.h" // for StringMap
-#include "llvm/ADT/StringRef.h" // for StringRef
-#include "llvm/Support/DynamicLibrary.h" // for DynamicLibrary
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-private-types.h"
+#include "lldb/lldb-types.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Threading.h"
-#include <assert.h> // for assert
-#include <stddef.h> // for size_t
+#include <assert.h>
+#include <stddef.h>
#include <stdio.h>
namespace lldb_private {
@@ -192,7 +188,8 @@ public:
lldb::StreamFileSP &out,
lldb::StreamFileSP &err);
- void PushIOHandler(const lldb::IOHandlerSP &reader_sp);
+ void PushIOHandler(const lldb::IOHandlerSP &reader_sp,
+ bool cancel_top_handler = true);
bool PopIOHandler(const lldb::IOHandlerSP &reader_sp);
@@ -264,6 +261,8 @@ public:
void SetPrompt(llvm::StringRef p);
void SetPrompt(const char *) = delete;
+ llvm::StringRef GetReproducerPath() const;
+
bool GetUseExternalEditor() const;
bool SetUseExternalEditor(bool use_external_editor_p);
@@ -272,11 +271,13 @@ public:
bool SetUseColor(bool use_color);
+ bool GetHighlightSource() const;
+
lldb::StopShowColumn GetStopShowColumn() const;
- const FormatEntity::Entry *GetStopShowColumnAnsiPrefix() const;
+ llvm::StringRef GetStopShowColumnAnsiPrefix() const;
- const FormatEntity::Entry *GetStopShowColumnAnsiSuffix() const;
+ llvm::StringRef GetStopShowColumnAnsiSuffix() const;
uint32_t GetStopSourceLineCount(bool before) const;
diff --git a/include/lldb/Core/Disassembler.h b/include/lldb/Core/Disassembler.h
index ef1f2ee54dd1..7cec837e71f8 100644
--- a/include/lldb/Core/Disassembler.h
+++ b/include/lldb/Core/Disassembler.h
@@ -12,32 +12,32 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/FormatEntity.h" // for FormatEntity
+#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Opcode.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Symbol/LineEntry.h"
-#include "lldb/Target/ExecutionContext.h" // for ExecutionContext
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-forward.h" // for InstructionSP, DisassemblerSP
-#include "lldb/lldb-private-enumerations.h" // for AddressClass
-#include "lldb/lldb-types.h" // for addr_t, offset_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
-#include <functional> // for function
+#include <functional>
#include <map>
-#include <memory> // for enable_shared_from_this
+#include <memory>
#include <set>
#include <string>
#include <vector>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, int64_t
-#include <stdio.h> // for FILE
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
namespace lldb_private {
class AddressRange;
diff --git a/include/lldb/Core/DumpDataExtractor.h b/include/lldb/Core/DumpDataExtractor.h
index 46e676c239d1..88446d48fa64 100644
--- a/include/lldb/Core/DumpDataExtractor.h
+++ b/include/lldb/Core/DumpDataExtractor.h
@@ -10,11 +10,11 @@
#ifndef LLDB_CORE_DUMPDATAEXTRACTOR_H
#define LLDB_CORE_DUMPDATAEXTRACTOR_H
-#include "lldb/lldb-enumerations.h" // for Format
+#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-types.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/Core/EmulateInstruction.h b/include/lldb/Core/EmulateInstruction.h
index 5d23bcd7b96e..5198f3eac922 100644
--- a/include/lldb/Core/EmulateInstruction.h
+++ b/include/lldb/Core/EmulateInstruction.h
@@ -12,18 +12,18 @@
#include <string>
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Utility/ArchSpec.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for RegisterKind, ByteOrder
-#include "lldb/lldb-private-enumerations.h" // for InstructionType
-#include "lldb/lldb-private-types.h" // for RegisterInfo
-#include "lldb/lldb-types.h" // for addr_t
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t, int64_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-private-types.h"
+#include "lldb/lldb-types.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class OptionValueDictionary;
}
diff --git a/include/lldb/Core/FileLineResolver.h b/include/lldb/Core/FileLineResolver.h
index 855d749ed5d4..6de99bc0c4dc 100644
--- a/include/lldb/Core/FileLineResolver.h
+++ b/include/lldb/Core/FileLineResolver.h
@@ -10,12 +10,12 @@
#ifndef liblldb_FileLineResolver_h_
#define liblldb_FileLineResolver_h_
-#include "lldb/Core/SearchFilter.h" // for Searcher, Searcher::CallbackR...
+#include "lldb/Core/SearchFilter.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/lldb-defines.h"
-#include <stdint.h> // for uint32_t, UINT32_MAX
+#include <stdint.h>
namespace lldb_private {
class Address;
@@ -48,7 +48,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
void GetDescription(Stream *s) override;
diff --git a/include/lldb/Core/FileSpecList.h b/include/lldb/Core/FileSpecList.h
index 713ed2aaffc6..db6490ef7133 100644
--- a/include/lldb/Core/FileSpecList.h
+++ b/include/lldb/Core/FileSpecList.h
@@ -15,7 +15,7 @@
#include <vector>
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class Stream;
diff --git a/include/lldb/Core/FormatEntity.h b/include/lldb/Core/FormatEntity.h
index 93c7b3a94e4e..b58f3b104e46 100644
--- a/include/lldb/Core/FormatEntity.h
+++ b/include/lldb/Core/FormatEntity.h
@@ -11,13 +11,13 @@
#define liblldb_FormatEntity_h_
#include "lldb/Utility/CompletionRequest.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
-#include "lldb/lldb-enumerations.h" // for Format::eFormatDefault, Format
-#include "lldb/lldb-types.h" // for addr_t
-#include <algorithm> // for min
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
+#include <algorithm>
+#include <stddef.h>
+#include <stdint.h>
#include <string>
#include <vector>
@@ -88,6 +88,7 @@ public:
FrameRegisterFP,
FrameRegisterFlags,
FrameRegisterByName,
+ FrameIsArtificial,
ScriptFrame,
FunctionID,
FunctionDidChange,
@@ -104,6 +105,7 @@ public:
FunctionIsOptimized,
LineEntryFile,
LineEntryLineNumber,
+ LineEntryColumn,
LineEntryStartAddress,
LineEntryEndAddress,
CurrentPCArrow
diff --git a/include/lldb/Core/Highlighter.h b/include/lldb/Core/Highlighter.h
new file mode 100644
index 000000000000..220557c1f032
--- /dev/null
+++ b/include/lldb/Core/Highlighter.h
@@ -0,0 +1,165 @@
+//===-- Highlighter.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_Highlighter_h_
+#define liblldb_Highlighter_h_
+
+#include <utility>
+#include <vector>
+
+#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// Represents style that the highlighter should apply to the given source code.
+/// Stores information about how every kind of token should be annotated.
+//----------------------------------------------------------------------
+struct HighlightStyle {
+
+ //----------------------------------------------------------------------
+ /// A pair of strings that should be placed around a certain token. Usually
+ /// stores color codes in these strings (the suffix string is often used for
+ /// resetting the terminal attributes back to normal).
+ //----------------------------------------------------------------------
+ class ColorStyle {
+ std::string m_prefix;
+ std::string m_suffix;
+
+ public:
+ ColorStyle() = default;
+ ColorStyle(llvm::StringRef prefix, llvm::StringRef suffix) {
+ Set(prefix, suffix);
+ }
+
+ /// Applies this style to the given value.
+ /// \param s
+ /// The stream to which the result should be appended.
+ /// \param value
+ /// The value that we should place our strings around.
+ void Apply(Stream &s, llvm::StringRef value) const;
+
+ /// Sets the prefix and suffix strings.
+ /// @param prefix
+ /// @param suffix
+ void Set(llvm::StringRef prefix, llvm::StringRef suffix);
+ };
+
+ /// The style for the token which is below the cursor of the user. Note that
+ /// this style is overwritten by the SourceManager with the values of
+ /// stop-show-column-ansi-prefix/stop-show-column-ansi-suffix.
+ ColorStyle selected;
+
+ /// Matches identifiers to variable or functions.
+ ColorStyle identifier;
+ /// Matches any string or character literals in the language: "foo" or 'f'
+ ColorStyle string_literal;
+ /// Matches scalar value literals like '42' or '0.1'.
+ ColorStyle scalar_literal;
+ /// Matches all reserved keywords in the language.
+ ColorStyle keyword;
+ /// Matches any comments in the language.
+ ColorStyle comment;
+ /// Matches commas: ','
+ ColorStyle comma;
+ /// Matches one colon: ':'
+ ColorStyle colon;
+ /// Matches any semicolon: ';'
+ ColorStyle semicolons;
+ /// Matches operators like '+', '-', '%', '&', '='
+ ColorStyle operators;
+
+ /// Matches '{' or '}'
+ ColorStyle braces;
+ /// Matches '[' or ']'
+ ColorStyle square_brackets;
+ /// Matches '(' or ')'
+ ColorStyle parentheses;
+
+ //-----------------------------------------------------------------------
+ // C language specific options
+ //-----------------------------------------------------------------------
+
+ /// Matches directives to a preprocessor (if the language has any).
+ ColorStyle pp_directive;
+
+ /// Returns a HighlightStyle that is based on vim's default highlight style.
+ static HighlightStyle MakeVimStyle();
+};
+
+//----------------------------------------------------------------------
+/// Annotates source code with color attributes.
+//----------------------------------------------------------------------
+class Highlighter {
+public:
+ Highlighter() = default;
+ virtual ~Highlighter() = default;
+ DISALLOW_COPY_AND_ASSIGN(Highlighter);
+
+ /// Returns a human readable name for the selected highlighter.
+ virtual llvm::StringRef GetName() const = 0;
+
+ /// Highlights the given line
+ /// \param options
+ /// \param line
+ /// The user supplied line that needs to be highlighted.
+ /// \param cursor_pos
+ /// The cursor position of the user in this line, starting at 0 (which
+ /// means the cursor is on the first character in 'line').
+ /// \param previous_lines
+ /// Any previous lines the user has written which we should only use
+ /// for getting the context of the Highlighting right.
+ /// \param s
+ /// The stream to which the highlighted version of the user string should
+ /// be written.
+ virtual void Highlight(const HighlightStyle &options, llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines, Stream &s) const = 0;
+
+ /// Utility method for calling Highlight without a stream.
+ std::string Highlight(const HighlightStyle &options, llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines = "") const;
+};
+
+/// A default highlighter that only highlights the user cursor, but doesn't
+/// do any other highlighting.
+class DefaultHighlighter : public Highlighter {
+public:
+ llvm::StringRef GetName() const override { return "none"; }
+
+ void Highlight(const HighlightStyle &options, llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines, Stream &s) const override;
+};
+
+/// Manages the available highlighters.
+class HighlighterManager {
+ DefaultHighlighter m_default;
+
+public:
+ /// Queries all known highlighter for one that can highlight some source code.
+ /// \param language_type
+ /// The language type that the caller thinks the source code was given in.
+ /// \param path
+ /// The path to the file the source code is from. Used as a fallback when
+ /// the user can't provide a language.
+ /// \return
+ /// The highlighter that wants to highlight the source code. Could be an
+ /// empty highlighter that does nothing.
+ const Highlighter &getHighlighterFor(lldb::LanguageType language_type,
+ llvm::StringRef path) const;
+ const Highlighter &getDefaultHighlighter() const { return m_default; }
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Highlighter_h_
diff --git a/include/lldb/Core/IOHandler.h b/include/lldb/Core/IOHandler.h
index 2170ad10674e..4bd577390b2c 100644
--- a/include/lldb/Core/IOHandler.h
+++ b/include/lldb/Core/IOHandler.h
@@ -11,22 +11,22 @@
#define liblldb_IOHandler_h_
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Flags.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-forward.h" // for IOHandlerSP, StreamFileSP
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/StringRef.h"
#include <memory>
#include <mutex>
#include <string>
#include <vector>
-#include <stdint.h> // for uint32_t
-#include <stdio.h> // for FILE
+#include <stdint.h>
+#include <stdio.h>
namespace lldb_private {
class Debugger;
@@ -205,7 +205,7 @@ public:
virtual int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
const char *cursor, const char *last_char,
int skip_first_n_matches, int max_matches,
- StringList &matches);
+ StringList &matches, StringList &descriptions);
virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; }
@@ -430,7 +430,8 @@ private:
static int AutoCompleteCallback(const char *current_line, const char *cursor,
const char *last_char,
int skip_first_n_matches, int max_matches,
- StringList &matches, void *baton);
+ StringList &matches, StringList &descriptions,
+ void *baton);
#endif
protected:
@@ -464,7 +465,7 @@ public:
int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
const char *cursor, const char *last_char,
int skip_first_n_matches, int max_matches,
- StringList &matches) override;
+ StringList &matches, StringList &descriptions) override;
void IOHandlerInputComplete(IOHandler &io_handler,
std::string &data) override;
diff --git a/include/lldb/Core/LoadedModuleInfoList.h b/include/lldb/Core/LoadedModuleInfoList.h
index 6554c64fa870..5ef0f8929b89 100644
--- a/include/lldb/Core/LoadedModuleInfoList.h
+++ b/include/lldb/Core/LoadedModuleInfoList.h
@@ -10,14 +10,11 @@
#ifndef liblldb_LoadedModuleInfoList_h_
#define liblldb_LoadedModuleInfoList_h_
-// C Includes
-// C++ Includes
#include <cassert>
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/lldb-types.h"
diff --git a/include/lldb/Core/Mangled.h b/include/lldb/Core/Mangled.h
index d263297ecfc6..12edf8200e43 100644
--- a/include/lldb/Core/Mangled.h
+++ b/include/lldb/Core/Mangled.h
@@ -11,18 +11,15 @@
#define liblldb_Mangled_h_
#if defined(__cplusplus)
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+
#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-enumerations.h" // for LanguageType
-#include "llvm/ADT/StringRef.h" // for StringRef
-#include <stddef.h> // for size_t
+#include "llvm/ADT/StringRef.h"
-namespace lldb_private {
-class RegularExpression;
-}
-namespace lldb_private {
-class Stream;
-}
+#include <memory>
+#include <stddef.h>
namespace lldb_private {
@@ -238,7 +235,6 @@ public:
return true;
return GetDemangledName(language) == name;
}
-
bool NameMatches(const RegularExpression &regex,
lldb::LanguageType language) const;
@@ -300,6 +296,36 @@ public:
//----------------------------------------------------------------------
lldb::LanguageType GuessLanguage() const;
+ /// Function signature for filtering mangled names.
+ using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);
+
+ //----------------------------------------------------------------------
+ /// Trigger explicit demangling to obtain rich mangling information. This is
+ /// optimized for batch processing while populating a name index. To get the
+ /// pure demangled name string for a single entity, use GetDemangledName()
+ /// instead.
+ ///
+ /// For names that match the Itanium mangling scheme, this uses LLVM's
+ /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
+ /// parser currently.
+ ///
+ /// This function is thread-safe when used with different \a context
+ /// instances in different threads.
+ ///
+ /// @param[in] context
+ /// The context for this function. A single instance can be stack-
+ /// allocated in the caller's frame and used for multiple calls.
+ ///
+ /// @param[in] skip_mangled_name
+ /// A filtering function for skipping entities based on name and mangling
+ /// scheme. This can be null if unused.
+ ///
+ /// @return
+ /// True on success, false otherwise.
+ //----------------------------------------------------------------------
+ bool DemangleWithRichManglingInfo(RichManglingContext &context,
+ SkipMangledNameFn *skip_mangled_name);
+
private:
//----------------------------------------------------------------------
/// Mangled member variables.
diff --git a/include/lldb/Core/MappedHash.h b/include/lldb/Core/MappedHash.h
index 1bdf59c73649..8d9a91e69079 100644
--- a/include/lldb/Core/MappedHash.h
+++ b/include/lldb/Core/MappedHash.h
@@ -10,18 +10,14 @@
#ifndef liblldb_MappedHash_h_
#define liblldb_MappedHash_h_
-// C Includes
#include <assert.h>
#include <stdint.h>
-// C++ Includes
#include <algorithm>
#include <functional>
#include <map>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Stream.h"
#include "llvm/Support/DJB.h"
diff --git a/include/lldb/Core/Module.h b/include/lldb/Core/Module.h
index 83d5f519f086..270a401172fa 100644
--- a/include/lldb/Core/Module.h
+++ b/include/lldb/Core/Module.h
@@ -10,31 +10,31 @@
#ifndef liblldb_Module_h_
#define liblldb_Module_h_
-#include "lldb/Core/Address.h" // for Address
-#include "lldb/Core/ModuleSpec.h" // for ModuleSpec
-#include "lldb/Symbol/ObjectFile.h" // for ObjectFile
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContextScope.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/Status.h" // for Status
+#include "lldb/Utility/Status.h"
#include "lldb/Utility/UUID.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for LanguageType, SymbolType
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h" // for addr_t, offset_t
+#include "lldb/lldb-types.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Chrono.h"
#include <atomic>
-#include <memory> // for enable_shared_from_this
+#include <memory>
#include <mutex>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include <stddef.h>
+#include <stdint.h>
#include <string>
#include <vector>
@@ -168,10 +168,11 @@ public:
// Once we get the object file, update our module with the object file's
// architecture since it might differ in vendor/os if some parts were
// unknown.
- if (!module_sp->m_objfile_sp->GetArchitecture(module_sp->m_arch))
- return nullptr;
-
- return module_sp;
+ if (ArchSpec arch = module_sp->m_objfile_sp->GetArchitecture()) {
+ module_sp->m_arch = arch;
+ return module_sp;
+ }
+ return nullptr;
}
//------------------------------------------------------------------
@@ -380,7 +381,7 @@ public:
//------------------------------------------------------------------
size_t FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool symbols_ok,
+ lldb::FunctionNameType name_type_mask, bool symbols_ok,
bool inlines_ok, bool append,
SymbolContextList &sc_list);
@@ -498,10 +499,6 @@ public:
/// have to specify complete scoping on all expressions, but it also allows
/// for exact matching when required.
///
- /// @param[in] sc
- /// A symbol context that scopes where to extract a type list
- /// from.
- ///
/// @param[in] type_name
/// The name of the type we are looking for that is a fully
/// or partially qualified type name.
@@ -520,8 +517,7 @@ public:
/// The number of matches added to \a type_list.
//------------------------------------------------------------------
size_t
- FindTypes(const SymbolContext &sc, const ConstString &type_name,
- bool exact_match, size_t max_matches,
+ FindTypes(const ConstString &type_name, bool exact_match, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeList &types);
@@ -533,10 +529,6 @@ public:
/// expression parser when searches need to happen in an exact namespace
/// scope.
///
- /// @param[in] sc
- /// A symbol context that scopes where to extract a type list
- /// from.
- ///
/// @param[in] type_name
/// The name of a type within a namespace that should not include
/// any qualifying namespaces (just a type basename).
@@ -550,8 +542,7 @@ public:
/// @return
/// The number of matches added to \a type_list.
//------------------------------------------------------------------
- size_t FindTypesInNamespace(const SymbolContext &sc,
- const ConstString &type_name,
+ size_t FindTypesInNamespace(const ConstString &type_name,
const CompilerDeclContext *parent_decl_ctx,
size_t max_matches, TypeList &type_list);
@@ -816,10 +807,9 @@ public:
///
/// @see SymbolContext::Scope
//------------------------------------------------------------------
- uint32_t
- ResolveSymbolContextForAddress(const Address &so_addr, uint32_t resolve_scope,
- SymbolContext &sc,
- bool resolve_tail_call_address = false);
+ uint32_t ResolveSymbolContextForAddress(
+ const Address &so_addr, lldb::SymbolContextItem resolve_scope,
+ SymbolContext &sc, bool resolve_tail_call_address = false);
//------------------------------------------------------------------
/// Resolve items in the symbol context for a given file and line.
@@ -862,10 +852,9 @@ public:
///
/// @see SymbolContext::Scope
//------------------------------------------------------------------
- uint32_t ResolveSymbolContextForFilePath(const char *file_path, uint32_t line,
- bool check_inlines,
- uint32_t resolve_scope,
- SymbolContextList &sc_list);
+ uint32_t ResolveSymbolContextForFilePath(
+ const char *file_path, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list);
//------------------------------------------------------------------
/// Resolve items in the symbol context for a given file and line.
@@ -909,10 +898,9 @@ public:
///
/// @see SymbolContext::Scope
//------------------------------------------------------------------
- uint32_t ResolveSymbolContextsForFileSpec(const FileSpec &file_spec,
- uint32_t line, bool check_inlines,
- uint32_t resolve_scope,
- SymbolContextList &sc_list);
+ uint32_t ResolveSymbolContextsForFileSpec(
+ const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list);
void SetFileSpecAndObjectName(const FileSpec &file,
const ConstString &object_name);
@@ -1031,9 +1019,10 @@ public:
public:
LookupInfo()
: m_name(), m_lookup_name(), m_language(lldb::eLanguageTypeUnknown),
- m_name_type_mask(0), m_match_name_after_lookup(false) {}
+ m_name_type_mask(lldb::eFunctionNameTypeNone),
+ m_match_name_after_lookup(false) {}
- LookupInfo(const ConstString &name, uint32_t name_type_mask,
+ LookupInfo(const ConstString &name, lldb::FunctionNameType name_type_mask,
lldb::LanguageType language);
const ConstString &GetName() const { return m_name; }
@@ -1044,24 +1033,31 @@ public:
void SetLookupName(const ConstString &name) { m_lookup_name = name; }
- uint32_t GetNameTypeMask() const { return m_name_type_mask; }
+ lldb::FunctionNameType GetNameTypeMask() const { return m_name_type_mask; }
- void SetNameTypeMask(uint32_t mask) { m_name_type_mask = mask; }
+ void SetNameTypeMask(lldb::FunctionNameType mask) {
+ m_name_type_mask = mask;
+ }
void Prune(SymbolContextList &sc_list, size_t start_idx) const;
protected:
- ConstString m_name; ///< What the user originally typed
- ConstString m_lookup_name; ///< The actual name will lookup when calling in
- ///the object or symbol file
- lldb::LanguageType
- m_language; ///< Limit matches to only be for this language
- uint32_t m_name_type_mask; ///< One or more bits from lldb::FunctionNameType
- ///that indicate what kind of names we are
- ///looking for
- bool m_match_name_after_lookup; ///< If \b true, then demangled names that
- ///match will need to contain "m_name" in
- ///order to be considered a match
+ /// What the user originally typed
+ ConstString m_name;
+
+ /// The actual name will lookup when calling in the object or symbol file
+ ConstString m_lookup_name;
+
+ /// Limit matches to only be for this language
+ lldb::LanguageType m_language;
+
+ /// One or more bits from lldb::FunctionNameType that indicate what kind of
+ /// names we are looking for
+ lldb::FunctionNameType m_name_type_mask;
+
+ ///< If \b true, then demangled names that match will need to contain
+ ///< "m_name" in order to be considered a match
+ bool m_match_name_after_lookup;
};
protected:
@@ -1155,7 +1151,7 @@ protected:
//------------------------------------------------------------------
uint32_t ResolveSymbolContextForAddress(lldb::addr_t vm_addr,
bool vm_addr_is_file_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
Address &so_addr, SymbolContext &sc);
void SymbolIndicesToSymbolContextList(Symtab *symtab,
@@ -1176,9 +1172,8 @@ private:
Module(); // Only used internally by CreateJITModule ()
size_t FindTypes_Impl(
- const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
- size_t max_matches,
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types);
diff --git a/include/lldb/Core/ModuleList.h b/include/lldb/Core/ModuleList.h
index e1d8a9a7fb85..a28d97113d63 100644
--- a/include/lldb/Core/ModuleList.h
+++ b/include/lldb/Core/ModuleList.h
@@ -10,12 +10,12 @@
#ifndef liblldb_ModuleList_h_
#define liblldb_ModuleList_h_
-#include "lldb/Core/Address.h" // for Address
-#include "lldb/Core/ModuleSpec.h" // for ModuleSpec
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/UserSettingsController.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Iterable.h"
-#include "lldb/Utility/Status.h" // for Status
+#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
@@ -27,8 +27,8 @@
#include <mutex>
#include <vector>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class ConstString;
@@ -300,14 +300,16 @@ public:
//------------------------------------------------------------------
/// @see Module::FindFunctions ()
//------------------------------------------------------------------
- size_t FindFunctions(const ConstString &name, uint32_t name_type_mask,
+ size_t FindFunctions(const ConstString &name,
+ lldb::FunctionNameType name_type_mask,
bool include_symbols, bool include_inlines, bool append,
SymbolContextList &sc_list) const;
//------------------------------------------------------------------
/// @see Module::FindFunctionSymbols ()
//------------------------------------------------------------------
- size_t FindFunctionSymbols(const ConstString &name, uint32_t name_type_mask,
+ size_t FindFunctionSymbols(const ConstString &name,
+ lldb::FunctionNameType name_type_mask,
SymbolContextList &sc_list);
//------------------------------------------------------------------
@@ -415,9 +417,9 @@ public:
//------------------------------------------------------------------
/// Find types by name.
///
- /// @param[in] sc
- /// A symbol context that scopes where to extract a type list
- /// from.
+ /// @param[in] search_first
+ /// If non-null, this module will be searched before any other
+ /// modules.
///
/// @param[in] name
/// The name of the type we are looking for.
@@ -445,7 +447,7 @@ public:
/// @return
/// The number of matches added to \a type_list.
//------------------------------------------------------------------
- size_t FindTypes(const SymbolContext &sc, const ConstString &name,
+ size_t FindTypes(Module *search_first, const ConstString &name,
bool name_is_fully_qualified, size_t max_matches,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeList &types) const;
@@ -495,26 +497,24 @@ public:
/// &,uint32_t,SymbolContext&)
//------------------------------------------------------------------
uint32_t ResolveSymbolContextForAddress(const Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContext &sc) const;
//------------------------------------------------------------------
/// @copydoc Module::ResolveSymbolContextForFilePath (const char
/// *,uint32_t,bool,uint32_t,SymbolContextList&)
//------------------------------------------------------------------
- uint32_t ResolveSymbolContextForFilePath(const char *file_path, uint32_t line,
- bool check_inlines,
- uint32_t resolve_scope,
- SymbolContextList &sc_list) const;
+ uint32_t ResolveSymbolContextForFilePath(
+ const char *file_path, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const;
//------------------------------------------------------------------
/// @copydoc Module::ResolveSymbolContextsForFileSpec (const FileSpec
/// &,uint32_t,bool,uint32_t,SymbolContextList&)
//------------------------------------------------------------------
- uint32_t ResolveSymbolContextsForFileSpec(const FileSpec &file_spec,
- uint32_t line, bool check_inlines,
- uint32_t resolve_scope,
- SymbolContextList &sc_list) const;
+ uint32_t ResolveSymbolContextsForFileSpec(
+ const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const;
//------------------------------------------------------------------
/// Gets the size of the module list.
diff --git a/include/lldb/Core/ModuleSpec.h b/include/lldb/Core/ModuleSpec.h
index 16a35a187780..ae772c2a1efe 100644
--- a/include/lldb/Core/ModuleSpec.h
+++ b/include/lldb/Core/ModuleSpec.h
@@ -10,18 +10,15 @@
#ifndef liblldb_ModuleSpec_h_
#define liblldb_ModuleSpec_h_
-// Project includes
+#include "lldb/Host/FileSystem.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/UUID.h"
-// Other libraries and framework includes
#include "llvm/Support/Chrono.h"
-// C Includes
-// C++ Includes
#include <mutex>
#include <vector>
@@ -34,15 +31,17 @@ public:
m_object_name(), m_object_offset(0), m_object_size(0),
m_source_mappings() {}
- ModuleSpec(const FileSpec &file_spec, const UUID& uuid = UUID())
+ ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID())
: m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(),
m_uuid(uuid), m_object_name(), m_object_offset(0),
- m_object_size(file_spec.GetByteSize()), m_source_mappings() {}
+ m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
+ m_source_mappings() {}
ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch)
: m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch),
m_uuid(), m_object_name(), m_object_offset(0),
- m_object_size(file_spec.GetByteSize()), m_source_mappings() {}
+ m_object_size(FileSystem::Instance().GetByteSize(file_spec)),
+ m_source_mappings() {}
ModuleSpec(const ModuleSpec &rhs)
: m_file(rhs.m_file), m_platform_file(rhs.m_platform_file),
@@ -256,20 +255,20 @@ public:
if (match_module_spec.GetFileSpecPtr()) {
const FileSpec &fspec = match_module_spec.GetFileSpec();
if (!FileSpec::Equal(fspec, GetFileSpec(),
- fspec.GetDirectory().IsEmpty() == false))
+ !fspec.GetDirectory().IsEmpty()))
return false;
}
if (GetPlatformFileSpec() && match_module_spec.GetPlatformFileSpecPtr()) {
const FileSpec &fspec = match_module_spec.GetPlatformFileSpec();
if (!FileSpec::Equal(fspec, GetPlatformFileSpec(),
- fspec.GetDirectory().IsEmpty() == false))
+ !fspec.GetDirectory().IsEmpty()))
return false;
}
// Only match the symbol file spec if there is one in this ModuleSpec
if (GetSymbolFileSpec() && match_module_spec.GetSymbolFileSpecPtr()) {
const FileSpec &fspec = match_module_spec.GetSymbolFileSpec();
if (!FileSpec::Equal(fspec, GetSymbolFileSpec(),
- fspec.GetDirectory().IsEmpty() == false))
+ !fspec.GetDirectory().IsEmpty()))
return false;
}
if (match_module_spec.GetArchitecturePtr()) {
diff --git a/include/lldb/Core/Opcode.h b/include/lldb/Core/Opcode.h
index 33857457b2c4..fb6cc825abd2 100644
--- a/include/lldb/Core/Opcode.h
+++ b/include/lldb/Core/Opcode.h
@@ -11,12 +11,12 @@
#define lldb_Opcode_h
#include "lldb/Utility/Endian.h"
-#include "lldb/lldb-enumerations.h" // for ByteOrder, ByteOrder::eByteOrde...
+#include "lldb/lldb-enumerations.h"
#include "llvm/Support/MathExtras.h"
-#include <assert.h> // for assert
-#include <stdint.h> // for uint32_t, uint8_t, uint16_t
+#include <assert.h>
+#include <stdint.h>
#include <string.h>
namespace lldb_private {
diff --git a/include/lldb/Core/PluginInterface.h b/include/lldb/Core/PluginInterface.h
index edda15a1ace0..24f53c62ab09 100644
--- a/include/lldb/Core/PluginInterface.h
+++ b/include/lldb/Core/PluginInterface.h
@@ -10,10 +10,6 @@
#ifndef liblldb_PluginInterface_h_
#define liblldb_PluginInterface_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
diff --git a/include/lldb/Core/PluginManager.h b/include/lldb/Core/PluginManager.h
index b782294f1f60..598ee9a8d8e3 100644
--- a/include/lldb/Core/PluginManager.h
+++ b/include/lldb/Core/PluginManager.h
@@ -12,14 +12,14 @@
#include "lldb/Core/Architecture.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-enumerations.h" // for ScriptLanguage
-#include "lldb/lldb-forward.h" // for OptionValuePropertiesSP
-#include "lldb/lldb-private-interfaces.h" // for DebuggerInitializeCallback
-#include "llvm/ADT/StringRef.h" // for StringRef
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-interfaces.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class CommandInterpreter;
diff --git a/include/lldb/Core/RangeMap.h b/include/lldb/Core/RangeMap.h
index 45bda26e2659..5a75a24f7f61 100644
--- a/include/lldb/Core/RangeMap.h
+++ b/include/lldb/Core/RangeMap.h
@@ -10,15 +10,11 @@
#ifndef liblldb_RangeMap_h_
#define liblldb_RangeMap_h_
-// C Includes
-// C++ Includes
#include <algorithm>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/SmallVector.h"
-// Project includes
#include "lldb/lldb-private.h"
// Uncomment to make sure all Range objects are sorted when needed
@@ -169,8 +165,6 @@ public:
#ifdef ASSERT_RANGEMAP_ARE_SORTED
bool IsSorted() const {
typename Collection::const_iterator pos, end, prev;
- // First we determine if we can combine any of the Entry objects so we
- // don't end up allocating and making a new collection for no reason
for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
prev = pos++) {
if (prev != end && *pos < *prev)
@@ -639,201 +633,12 @@ struct RangeData : public Range<B, S> {
}
};
-template <typename B, typename S, typename T, unsigned N> class RangeDataArray {
+template <typename B, typename S, typename T, unsigned N = 0>
+class RangeDataVector {
public:
typedef RangeData<B, S, T> Entry;
typedef llvm::SmallVector<Entry, N> Collection;
- RangeDataArray() = default;
-
- ~RangeDataArray() = default;
-
- void Append(const Entry &entry) { m_entries.push_back(entry); }
-
- void Sort() {
- if (m_entries.size() > 1)
- std::stable_sort(m_entries.begin(), m_entries.end());
- }
-
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- bool IsSorted() const {
- typename Collection::const_iterator pos, end, prev;
- // First we determine if we can combine any of the Entry objects so we
- // don't end up allocating and making a new collection for no reason
- for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
- prev = pos++) {
- if (prev != end && *pos < *prev)
- return false;
- }
- return true;
- }
-#endif
-
- void CombineConsecutiveEntriesWithEqualData() {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- typename Collection::iterator pos;
- typename Collection::iterator end;
- typename Collection::iterator prev;
- bool can_combine = false;
- // First we determine if we can combine any of the Entry objects so we
- // don't end up allocating and making a new collection for no reason
- for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end;
- prev = pos++) {
- if (prev != end && prev->data == pos->data) {
- can_combine = true;
- break;
- }
- }
-
- // We we can combine at least one entry, then we make a new collection and
- // populate it accordingly, and then swap it into place.
- if (can_combine) {
- Collection minimal_ranges;
- for (pos = m_entries.begin(), end = m_entries.end(), prev = end;
- pos != end; prev = pos++) {
- if (prev != end && prev->data == pos->data)
- minimal_ranges.back().SetRangeEnd(pos->GetRangeEnd());
- else
- minimal_ranges.push_back(*pos);
- }
- // Use the swap technique in case our new vector is much smaller. We must
- // swap when using the STL because std::vector objects never release or
- // reduce the memory once it has been allocated/reserved.
- m_entries.swap(minimal_ranges);
- }
- }
-
- void Clear() { m_entries.clear(); }
-
- bool IsEmpty() const { return m_entries.empty(); }
-
- size_t GetSize() const { return m_entries.size(); }
-
- const Entry *GetEntryAtIndex(size_t i) const {
- return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
- }
-
- // Clients must ensure that "i" is a valid index prior to calling this
- // function
- const Entry &GetEntryRef(size_t i) const { return m_entries[i]; }
-
- static bool BaseLessThan(const Entry &lhs, const Entry &rhs) {
- return lhs.GetRangeBase() < rhs.GetRangeBase();
- }
-
- uint32_t FindEntryIndexThatContains(B addr) const {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- Entry entry(addr, 1);
- typename Collection::const_iterator begin = m_entries.begin();
- 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 std::distance(begin, pos);
- } else if (pos != begin) {
- --pos;
- if (pos->Contains(addr))
- return std::distance(begin, pos);
- }
- }
- return UINT32_MAX;
- }
-
- Entry *FindEntryThatContains(B addr) {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- Entry entry;
- entry.SetRangeBase(addr);
- entry.SetByteSize(1);
- 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);
-
- if (pos != end && pos->Contains(addr)) {
- return &(*pos);
- } else if (pos != begin) {
- --pos;
- if (pos->Contains(addr)) {
- return &(*pos);
- }
- }
- }
- return nullptr;
- }
-
- const Entry *FindEntryThatContains(B addr) const {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- Entry entry;
- entry.SetRangeBase(addr);
- entry.SetByteSize(1);
- typename Collection::const_iterator begin = m_entries.begin();
- 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) {
- --pos;
- if (pos->Contains(addr)) {
- return &(*pos);
- }
- }
- }
- return nullptr;
- }
-
- const Entry *FindEntryThatContains(const Entry &range) const {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- typename Collection::const_iterator begin = m_entries.begin();
- 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) {
- --pos;
- if (pos->Contains(range)) {
- return &(*pos);
- }
- }
- }
- return nullptr;
- }
-
- Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); }
-
- const Entry *Back() const {
- return (m_entries.empty() ? nullptr : &m_entries.back());
- }
-
-protected:
- Collection m_entries;
-};
-
-// Same as RangeDataArray, but uses std::vector as to not require static
-// storage of N items in the class itself
-template <typename B, typename S, typename T> class RangeDataVector {
-public:
- typedef RangeData<B, S, T> Entry;
- typedef std::vector<Entry> Collection;
-
RangeDataVector() = default;
~RangeDataVector() = default;
@@ -895,38 +700,8 @@ public:
}
}
- // Calculate the byte size of ranges with zero byte sizes by finding the next
- // entry with a base address > the current base address
- void CalculateSizesOfZeroByteSizeRanges(S full_size = 0) {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- typename Collection::iterator pos;
- typename Collection::iterator end;
- typename Collection::iterator next;
- for (pos = m_entries.begin(), end = m_entries.end(); pos != end; ++pos) {
- if (pos->GetByteSize() == 0) {
- // Watch out for multiple entries with same address and make sure we
- // find an entry that is greater than the current base address before
- // we use that for the size
- auto curr_base = pos->GetRangeBase();
- for (next = pos + 1; next != end; ++next) {
- auto next_base = next->GetRangeBase();
- if (next_base > curr_base) {
- pos->SetByteSize(next_base - curr_base);
- break;
- }
- }
- if (next == end && full_size > curr_base)
- pos->SetByteSize(full_size - curr_base);
- }
- }
- }
-
void Clear() { m_entries.clear(); }
- void Reserve(typename Collection::size_type size) { m_entries.resize(size); }
-
bool IsEmpty() const { return m_entries.empty(); }
size_t GetSize() const { return m_entries.size(); }
@@ -948,22 +723,9 @@ public:
}
uint32_t FindEntryIndexThatContains(B addr) const {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- Entry entry(addr, 1);
- typename Collection::const_iterator begin = m_entries.begin();
- 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);
- }
+ const Entry *entry = FindEntryThatContains(addr);
+ if (entry)
+ return std::distance(m_entries.begin(), entry);
return UINT32_MAX;
}
@@ -983,47 +745,13 @@ public:
}
Entry *FindEntryThatContains(B addr) {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- Entry entry;
- entry.SetRangeBase(addr);
- entry.SetByteSize(1);
- 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);
- }
- return nullptr;
+ return const_cast<Entry *>(
+ static_cast<const RangeDataVector *>(this)->FindEntryThatContains(
+ addr));
}
const Entry *FindEntryThatContains(B addr) const {
-#ifdef ASSERT_RANGEMAP_ARE_SORTED
- assert(IsSorted());
-#endif
- if (!m_entries.empty()) {
- Entry entry;
- entry.SetRangeBase(addr);
- entry.SetByteSize(1);
- typename Collection::const_iterator begin = m_entries.begin();
- 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 &(*pos);
- }
- return nullptr;
+ return FindEntryThatContains(Entry(addr, 1));
}
const Entry *FindEntryThatContains(const Entry &range) const {
diff --git a/include/lldb/Core/RichManglingContext.h b/include/lldb/Core/RichManglingContext.h
new file mode 100644
index 000000000000..30841bfb2668
--- /dev/null
+++ b/include/lldb/Core/RichManglingContext.h
@@ -0,0 +1,108 @@
+//===-- RichManglingContext.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_RichManglingContext_h_
+#define liblldb_RichManglingContext_h_
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+
+#include "lldb/Utility/ConstString.h"
+
+#include "llvm/ADT/Any.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Demangle/Demangle.h"
+
+namespace lldb_private {
+
+/// Uniform wrapper for access to rich mangling information from different
+/// providers. See Mangled::DemangleWithRichManglingInfo()
+class RichManglingContext {
+public:
+ RichManglingContext() : m_provider(None), m_ipd_buf_size(2048) {
+ m_ipd_buf = static_cast<char *>(std::malloc(m_ipd_buf_size));
+ m_ipd_buf[0] = '\0';
+ }
+
+ ~RichManglingContext() { std::free(m_ipd_buf); }
+
+ /// Use the ItaniumPartialDemangler to obtain rich mangling information from
+ /// the given mangled name.
+ bool FromItaniumName(const ConstString &mangled);
+
+ /// Use the legacy language parser implementation to obtain rich mangling
+ /// information from the given demangled name.
+ bool FromCxxMethodName(const ConstString &demangled);
+
+ /// If this symbol describes a constructor or destructor.
+ bool IsCtorOrDtor() const;
+
+ /// If this symbol describes a function.
+ bool IsFunction() const;
+
+ /// Get the base name of a function. This doesn't include trailing template
+ /// arguments, ie "a::b<int>" gives "b". The result will overwrite the
+ /// internal buffer. It can be obtained via GetBufferRef().
+ void ParseFunctionBaseName();
+
+ /// Get the context name for a function. For "a::b::c", this function returns
+ /// "a::b". The result will overwrite the internal buffer. It can be obtained
+ /// via GetBufferRef().
+ void ParseFunctionDeclContextName();
+
+ /// Get the entire demangled name. The result will overwrite the internal
+ /// buffer. It can be obtained via GetBufferRef().
+ void ParseFullName();
+
+ /// Obtain a StringRef to the internal buffer that holds the result of the
+ /// most recent ParseXy() operation. The next ParseXy() call invalidates it.
+ llvm::StringRef GetBufferRef() const {
+ assert(m_provider != None && "Initialize a provider first");
+ return m_buffer;
+ }
+
+private:
+ enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage };
+
+ /// Selects the rich mangling info provider.
+ InfoProvider m_provider;
+
+ /// Reference to the buffer used for results of ParseXy() operations.
+ llvm::StringRef m_buffer;
+
+ /// Members for ItaniumPartialDemangler
+ llvm::ItaniumPartialDemangler m_ipd;
+ char *m_ipd_buf;
+ size_t m_ipd_buf_size;
+
+ /// Members for PluginCxxLanguage
+ /// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The
+ /// respective header is in Plugins and including it from here causes cyclic
+ /// dependency. Instead keep a llvm::Any and cast it on-access in the cpp.
+ llvm::Any m_cxx_method_parser;
+
+ /// Clean up memory and set a new info provider for this instance.
+ void ResetProvider(InfoProvider new_provider);
+
+ /// Uniform handling of string buffers for ItaniumPartialDemangler.
+ void processIPDStrResult(char *ipd_res, size_t res_len);
+
+ /// Cast the given parser to the given type. Ideally we would have a type
+ /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we
+ /// can't access CPlusPlusLanguage::MethodName from within the header.
+ template <class ParserT> static ParserT *get(llvm::Any parser) {
+ assert(parser.hasValue());
+ assert(llvm::any_isa<ParserT *>(parser));
+ return llvm::any_cast<ParserT *>(parser);
+ }
+};
+
+} // namespace lldb_private
+
+#endif
diff --git a/include/lldb/Core/STLUtils.h b/include/lldb/Core/STLUtils.h
index 55f1ac05c975..0ed354fa4e32 100644
--- a/include/lldb/Core/STLUtils.h
+++ b/include/lldb/Core/STLUtils.h
@@ -10,16 +10,12 @@
#ifndef liblldb_STLUtils_h_
#define liblldb_STLUtils_h_
-// C Includes
#include <string.h>
-// C++ Includes
#include <map>
#include <ostream>
#include <vector>
-// Other libraries and framework includes
-// Project includes
//----------------------------------------------------------------------
// C string less than compare function object
diff --git a/include/lldb/Core/SearchFilter.h b/include/lldb/Core/SearchFilter.h
index 2e641983dc73..f53ef658fd3f 100644
--- a/include/lldb/Core/SearchFilter.h
+++ b/include/lldb/Core/SearchFilter.h
@@ -13,10 +13,10 @@
#include "lldb/Core/FileSpecList.h"
#include "lldb/Utility/StructuredData.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/lldb-forward.h" // for SearchFilterSP, TargetSP, Modu...
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/lldb-forward.h"
-#include <stdint.h> // for uint32_t
+#include <stdint.h>
namespace lldb_private {
class Address;
@@ -70,15 +70,6 @@ public:
eCallbackReturnPop // Pop one level up and continue iterating
} CallbackReturn;
- typedef enum {
- eDepthTarget,
- eDepthModule,
- eDepthCompUnit,
- eDepthFunction,
- eDepthBlock,
- eDepthAddress
- } Depth;
-
Searcher();
virtual ~Searcher();
@@ -87,7 +78,7 @@ public:
SymbolContext &context, Address *addr,
bool complete) = 0;
- virtual Depth GetDepth() = 0;
+ virtual lldb::SearchDepth GetDepth() = 0;
//------------------------------------------------------------------
/// Prints a canonical description for the searcher to the stream \a s.
@@ -193,6 +184,18 @@ public:
virtual bool CompUnitPasses(CompileUnit &compUnit);
//------------------------------------------------------------------
+ /// Call this method with a Function to see if \a function passes the
+ /// filter.
+ ///
+ /// @param[in] function
+ /// The Functions to check against the filter.
+ ///
+ /// @return
+ /// \b true if \a function passes, and \b false otherwise.
+ //------------------------------------------------------------------
+ virtual bool FunctionPasses(Function &function);
+
+ //------------------------------------------------------------------
/// Call this method to do the search using the Searcher.
///
/// @param[in] searcher
diff --git a/include/lldb/Core/Section.h b/include/lldb/Core/Section.h
index 8e275ce3199e..4157bb877b4c 100644
--- a/include/lldb/Core/Section.h
+++ b/include/lldb/Core/Section.h
@@ -14,16 +14,16 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Flags.h"
#include "lldb/Utility/UserID.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for SectionType
-#include "lldb/lldb-forward.h" // for SectionSP, ModuleSP, SectionWP
-#include "lldb/lldb-types.h" // for addr_t, offset_t, user_id_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
-#include <memory> // for enable_shared_from_this
-#include <vector> // for vector
+#include <memory>
+#include <vector>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, UINT32_MAX
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class Address;
diff --git a/include/lldb/Core/SourceManager.h b/include/lldb/Core/SourceManager.h
index ef652531244d..d31ba037c5d6 100644
--- a/include/lldb/Core/SourceManager.h
+++ b/include/lldb/Core/SourceManager.h
@@ -11,16 +11,16 @@
#define liblldb_SourceManager_h_
#include "lldb/Utility/FileSpec.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-forward.h" // for DebuggerSP, DebuggerWP, DataBufferSP
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
#include "llvm/Support/Chrono.h"
-#include <cstdint> // for uint32_t, UINT32_MAX
+#include <cstdint>
#include <map>
#include <memory>
-#include <stddef.h> // for size_t
-#include <string> // for string
+#include <stddef.h>
+#include <string>
#include <vector>
namespace lldb_private {
@@ -52,7 +52,7 @@ public:
void UpdateIfNeeded();
- size_t DisplaySourceLines(uint32_t line, uint32_t column,
+ size_t DisplaySourceLines(uint32_t line, llvm::Optional<size_t> column,
uint32_t context_before, uint32_t context_after,
Stream *s);
void FindLinesMatchingRegex(RegularExpression &regex, uint32_t start_line,
diff --git a/include/lldb/Core/StreamAsynchronousIO.h b/include/lldb/Core/StreamAsynchronousIO.h
index 29b109757da7..89667be05878 100644
--- a/include/lldb/Core/StreamAsynchronousIO.h
+++ b/include/lldb/Core/StreamAsynchronousIO.h
@@ -14,7 +14,7 @@
#include <string>
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class Debugger;
@@ -30,7 +30,8 @@ public:
void Flush() override;
- size_t Write(const void *src, size_t src_len) override;
+protected:
+ size_t WriteImpl(const void *src, size_t src_len) override;
private:
Debugger &m_debugger;
diff --git a/include/lldb/Core/StreamBuffer.h b/include/lldb/Core/StreamBuffer.h
index 307dc7e18a5e..7b2468330ad2 100644
--- a/include/lldb/Core/StreamBuffer.h
+++ b/include/lldb/Core/StreamBuffer.h
@@ -30,12 +30,6 @@ public:
// Nothing to do when flushing a buffer based stream...
}
- virtual size_t Write(const void *s, size_t length) {
- if (s && length)
- m_packet.append((const char *)s, ((const char *)s) + length);
- return length;
- }
-
void Clear() { m_packet.clear(); }
// Beware, this might not be NULL terminated as you can expect from
@@ -48,6 +42,12 @@ public:
protected:
llvm::SmallVector<char, N> m_packet;
+
+ virtual size_t WriteImpl(const void *s, size_t length) {
+ if (s && length)
+ m_packet.append((const char *)s, ((const char *)s) + length);
+ return length;
+ }
};
} // namespace lldb_private
diff --git a/include/lldb/Core/StreamFile.h b/include/lldb/Core/StreamFile.h
index a26ae84c7be5..86db3e4ae487 100644
--- a/include/lldb/Core/StreamFile.h
+++ b/include/lldb/Core/StreamFile.h
@@ -12,11 +12,11 @@
#include "lldb/Host/File.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for FilePermissions::eFilePermission...
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
-#include <stdint.h> // for uint32_t
-#include <stdio.h> // for size_t, FILE
+#include <stdint.h>
+#include <stdio.h>
namespace lldb_private {
@@ -46,13 +46,13 @@ public:
void Flush() override;
- size_t Write(const void *s, size_t length) override;
protected:
//------------------------------------------------------------------
// Classes that inherit from StreamFile can see and modify these
//------------------------------------------------------------------
File m_file;
+ size_t WriteImpl(const void *s, size_t length) override;
private:
DISALLOW_COPY_AND_ASSIGN(StreamFile);
diff --git a/include/lldb/Core/StructuredDataImpl.h b/include/lldb/Core/StructuredDataImpl.h
index 819d1d9e5d2f..2912f4ec7de0 100644
--- a/include/lldb/Core/StructuredDataImpl.h
+++ b/include/lldb/Core/StructuredDataImpl.h
@@ -10,8 +10,8 @@
#ifndef liblldb_StructuredDataImpl_h_
#define liblldb_StructuredDataImpl_h_
-#include "lldb/Core/Event.h"
#include "lldb/Target/StructuredDataPlugin.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/include/lldb/Core/ThreadSafeDenseMap.h b/include/lldb/Core/ThreadSafeDenseMap.h
index 9b52e0355314..2fc428c4f7d4 100644
--- a/include/lldb/Core/ThreadSafeDenseMap.h
+++ b/include/lldb/Core/ThreadSafeDenseMap.h
@@ -11,14 +11,10 @@
#ifndef liblldb_ThreadSafeDenseMap_h_
#define liblldb_ThreadSafeDenseMap_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
-// Project includes
namespace lldb_private {
diff --git a/include/lldb/Core/ThreadSafeDenseSet.h b/include/lldb/Core/ThreadSafeDenseSet.h
index 44ec2464385f..74a010544705 100644
--- a/include/lldb/Core/ThreadSafeDenseSet.h
+++ b/include/lldb/Core/ThreadSafeDenseSet.h
@@ -11,14 +11,10 @@
#ifndef liblldb_ThreadSafeDenseSet_h_
#define liblldb_ThreadSafeDenseSet_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "llvm/ADT/DenseSet.h"
-// Project includes
namespace lldb_private {
diff --git a/include/lldb/Core/ThreadSafeSTLMap.h b/include/lldb/Core/ThreadSafeSTLMap.h
index 5520920c4559..4058fdfe15a8 100644
--- a/include/lldb/Core/ThreadSafeSTLMap.h
+++ b/include/lldb/Core/ThreadSafeSTLMap.h
@@ -10,13 +10,9 @@
#ifndef liblldb_ThreadSafeSTLMap_h_
#define liblldb_ThreadSafeSTLMap_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
namespace lldb_private {
diff --git a/include/lldb/Core/ThreadSafeSTLVector.h b/include/lldb/Core/ThreadSafeSTLVector.h
index 466f4309c2d5..b65936f81fec 100644
--- a/include/lldb/Core/ThreadSafeSTLVector.h
+++ b/include/lldb/Core/ThreadSafeSTLVector.h
@@ -11,13 +11,9 @@
#ifndef liblldb_ThreadSafeSTLVector_h_
#define liblldb_ThreadSafeSTLVector_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
namespace lldb_private {
diff --git a/include/lldb/Core/ThreadSafeValue.h b/include/lldb/Core/ThreadSafeValue.h
index 10ef8fa41d0c..35424a1791e6 100644
--- a/include/lldb/Core/ThreadSafeValue.h
+++ b/include/lldb/Core/ThreadSafeValue.h
@@ -10,13 +10,9 @@
#ifndef liblldb_ThreadSafeValue_h_
#define liblldb_ThreadSafeValue_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
namespace lldb_private {
diff --git a/include/lldb/Core/UniqueCStringMap.h b/include/lldb/Core/UniqueCStringMap.h
index fe3e831a6045..cfb84b4c2160 100644
--- a/include/lldb/Core/UniqueCStringMap.h
+++ b/include/lldb/Core/UniqueCStringMap.h
@@ -10,13 +10,9 @@
#ifndef liblldb_UniqueCStringMap_h_
#define liblldb_UniqueCStringMap_h_
-// C Includes
-// C++ Includes
#include <algorithm>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
@@ -221,7 +217,7 @@ public:
// }
// my_map.Sort();
//------------------------------------------------------------------
- void Sort() { std::sort(m_map.begin(), m_map.end()); }
+ void Sort() { llvm::sort(m_map.begin(), m_map.end()); }
//------------------------------------------------------------------
// Since we are using a vector to contain our items it will always double its
diff --git a/include/lldb/Core/UserSettingsController.h b/include/lldb/Core/UserSettingsController.h
index aefd42e751ab..350b5babb47b 100644
--- a/include/lldb/Core/UserSettingsController.h
+++ b/include/lldb/Core/UserSettingsController.h
@@ -10,16 +10,16 @@
#ifndef liblldb_UserSettingsController_h_
#define liblldb_UserSettingsController_h_
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-forward.h" // for OptionValuePropertiesSP
-#include "lldb/lldb-private-enumerations.h" // for VarSetOperationType
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include <vector>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class CommandInterpreter;
diff --git a/include/lldb/Core/Value.h b/include/lldb/Core/Value.h
index 801e818c6f5c..249adb24fbc9 100644
--- a/include/lldb/Core/Value.h
+++ b/include/lldb/Core/Value.h
@@ -10,20 +10,20 @@
#ifndef liblldb_Value_h_
#define liblldb_Value_h_
-#include "lldb/Core/Scalar.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
-#include "lldb/lldb-enumerations.h" // for ByteOrder, ByteOrder::eB...
-#include "lldb/lldb-private-enumerations.h" // for AddressType
-#include "lldb/lldb-private-types.h" // for type128, RegisterInfo
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-private-types.h"
-#include "llvm/ADT/APInt.h" // for APInt
+#include "llvm/ADT/APInt.h"
#include <vector>
-#include <stdint.h> // for uint8_t, uint32_t, uint64_t
-#include <string.h> // for size_t, memcpy
+#include <stdint.h>
+#include <string.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/Core/ValueObject.h b/include/lldb/Core/ValueObject.h
index fddc06413196..cb6de7b41807 100644
--- a/include/lldb/Core/ValueObject.h
+++ b/include/lldb/Core/ValueObject.h
@@ -12,7 +12,7 @@
#include "lldb/Core/Value.h"
#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/Type.h" // for TypeImpl
+#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
@@ -20,26 +20,26 @@
#include "lldb/Utility/SharedCluster.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/UserID.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID...
-#include "lldb/lldb-enumerations.h" // for DynamicValue...
-#include "lldb/lldb-forward.h" // for ValueObjectSP
-#include "lldb/lldb-private-enumerations.h" // for AddressType
-#include "lldb/lldb-types.h" // for addr_t, offs...
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include <functional>
#include <initializer_list>
#include <map>
-#include <mutex> // for recursive_mutex
-#include <string> // for string
-#include <utility> // for pair
+#include <mutex>
+#include <string>
+#include <utility>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class Declaration;
}
@@ -635,9 +635,6 @@ public:
virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS,
AddressType address_type = eAddressTypeLoad) {}
- // Find the address of the C++ vtable pointer
- virtual lldb::addr_t GetCPPVTableAddress(AddressType &address_type);
-
virtual lldb::ValueObjectSP Cast(const CompilerType &compiler_type);
virtual lldb::ValueObjectSP CastPointerType(const char *name,
diff --git a/include/lldb/Core/ValueObjectCast.h b/include/lldb/Core/ValueObjectCast.h
index aaa1ecb67db8..34814d9b17bb 100644
--- a/include/lldb/Core/ValueObjectCast.h
+++ b/include/lldb/Core/ValueObjectCast.h
@@ -11,13 +11,13 @@
#define liblldb_ValueObjectCast_h_
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ValueType
-#include "lldb/lldb-forward.h" // for ValueObjectSP
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class ConstString;
diff --git a/include/lldb/Core/ValueObjectChild.h b/include/lldb/Core/ValueObjectChild.h
index ec8c9e805cdf..6800775dc8f9 100644
--- a/include/lldb/Core/ValueObjectChild.h
+++ b/include/lldb/Core/ValueObjectChild.h
@@ -12,17 +12,17 @@
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ValueType
-#include "lldb/lldb-private-enumerations.h" // for LazyBool, AddressType
-#include "lldb/lldb-types.h" // for offset_t
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
#include "llvm/ADT/Optional.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t, int32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
diff --git a/include/lldb/Core/ValueObjectConstResult.h b/include/lldb/Core/ValueObjectConstResult.h
index 1f56129df24a..c1c56d8dcb22 100644
--- a/include/lldb/Core/ValueObjectConstResult.h
+++ b/include/lldb/Core/ValueObjectConstResult.h
@@ -10,20 +10,20 @@
#ifndef liblldb_ValueObjectConstResult_h_
#define liblldb_ValueObjectConstResult_h_
-#include "lldb/Core/Value.h" // for Value
+#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResultImpl.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-enumerations.h" // for ByteOrder, Dynamic...
-#include "lldb/lldb-forward.h" // for ValueObjectSP, Dat...
-#include "lldb/lldb-private-enumerations.h" // for AddressType, Addre...
-#include "lldb/lldb-types.h" // for addr_t
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/Core/ValueObjectConstResultCast.h b/include/lldb/Core/ValueObjectConstResultCast.h
index 442cce420855..bb2b4e6f092f 100644
--- a/include/lldb/Core/ValueObjectConstResultCast.h
+++ b/include/lldb/Core/ValueObjectConstResultCast.h
@@ -12,14 +12,14 @@
#include "lldb/Core/ValueObjectCast.h"
#include "lldb/Core/ValueObjectConstResultImpl.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_...
-#include "lldb/lldb-forward.h" // for ValueObjectSP
-#include "lldb/lldb-types.h" // for addr_t
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, int32_t
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/Core/ValueObjectConstResultChild.h b/include/lldb/Core/ValueObjectConstResultChild.h
index a74da0013aba..f14fb75640e6 100644
--- a/include/lldb/Core/ValueObjectConstResultChild.h
+++ b/include/lldb/Core/ValueObjectConstResultChild.h
@@ -12,14 +12,14 @@
#include "lldb/Core/ValueObjectChild.h"
#include "lldb/Core/ValueObjectConstResultImpl.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_...
-#include "lldb/lldb-forward.h" // for ValueObjectSP
-#include "lldb/lldb-types.h" // for addr_t
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, int32_t
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
}
@@ -63,6 +63,9 @@ public:
lldb::ValueObjectSP AddressOf(Status &error) override;
+ lldb::addr_t GetAddressOf(bool scalar_is_load_address = true,
+ AddressType *address_type = nullptr) override;
+
size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0,
uint32_t item_count = 1) override;
diff --git a/include/lldb/Core/ValueObjectConstResultImpl.h b/include/lldb/Core/ValueObjectConstResultImpl.h
index d86f25e30579..5ea47bb3b3fa 100644
--- a/include/lldb/Core/ValueObjectConstResultImpl.h
+++ b/include/lldb/Core/ValueObjectConstResultImpl.h
@@ -10,14 +10,14 @@
#ifndef liblldb_ValueObjectConstResultImpl_h_
#define liblldb_ValueObjectConstResultImpl_h_
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-forward.h" // for ValueObjectSP
-#include "lldb/lldb-private-enumerations.h" // for AddressType, AddressType...
-#include "lldb/lldb-types.h" // for addr_t
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, int32_t
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class CompilerType;
}
diff --git a/include/lldb/Core/ValueObjectDynamicValue.h b/include/lldb/Core/ValueObjectDynamicValue.h
index 018ee2c764bf..0c9ec8cce06e 100644
--- a/include/lldb/Core/ValueObjectDynamicValue.h
+++ b/include/lldb/Core/ValueObjectDynamicValue.h
@@ -10,20 +10,20 @@
#ifndef liblldb_ValueObjectDynamicValue_h_
#define liblldb_ValueObjectDynamicValue_h_
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Type.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/SharingPtr.h" // for operator==
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for DynamicValueType, Langua...
-#include "lldb/lldb-forward.h" // for ValueObjectSP, VariableSP
-#include "lldb/lldb-private-enumerations.h" // for LazyBool, LazyBool::eLaz...
-
-#include <assert.h> // for assert
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint64_t, uint32_t
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/SharingPtr.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/Core/ValueObjectList.h b/include/lldb/Core/ValueObjectList.h
index a0d2e681dedb..d17510f7f581 100644
--- a/include/lldb/Core/ValueObjectList.h
+++ b/include/lldb/Core/ValueObjectList.h
@@ -10,12 +10,12 @@
#ifndef liblldb_ValueObjectList_h_
#define liblldb_ValueObjectList_h_
-#include "lldb/lldb-forward.h" // for ValueObjectSP
-#include "lldb/lldb-types.h" // for user_id_t
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
#include <vector>
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class ValueObject;
diff --git a/include/lldb/Core/ValueObjectMemory.h b/include/lldb/Core/ValueObjectMemory.h
index 8bb649cc3c52..c4b946af98ce 100644
--- a/include/lldb/Core/ValueObjectMemory.h
+++ b/include/lldb/Core/ValueObjectMemory.h
@@ -10,17 +10,17 @@
#ifndef liblldb_ValueObjectMemory_h_
#define liblldb_ValueObjectMemory_h_
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ValueType
-#include "lldb/lldb-forward.h" // for TypeSP, ValueObjectSP, ModuleSP
-#include "llvm/ADT/StringRef.h" // for StringRef
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class ExecutionContextScope;
diff --git a/include/lldb/Core/ValueObjectRegister.h b/include/lldb/Core/ValueObjectRegister.h
index 2aaef9bee99e..fb10c259e7d0 100644
--- a/include/lldb/Core/ValueObjectRegister.h
+++ b/include/lldb/Core/ValueObjectRegister.h
@@ -10,17 +10,17 @@
#ifndef liblldb_ValueObjectRegister_h_
#define liblldb_ValueObjectRegister_h_
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ValueType, ValueType::eValueTy...
-#include "lldb/lldb-forward.h" // for RegisterContextSP, ValueObjectSP
-#include "lldb/lldb-private-types.h" // for RegisterInfo, RegisterSet (ptr...
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t, int32_t
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-types.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/Core/ValueObjectSyntheticFilter.h b/include/lldb/Core/ValueObjectSyntheticFilter.h
index b3af6c0ae827..9495d4ca5e25 100644
--- a/include/lldb/Core/ValueObjectSyntheticFilter.h
+++ b/include/lldb/Core/ValueObjectSyntheticFilter.h
@@ -13,17 +13,17 @@
#include "lldb/Core/ThreadSafeSTLMap.h"
#include "lldb/Core/ThreadSafeSTLVector.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for ThreadSafeSTLMap::operator=
-#include "lldb/lldb-enumerations.h" // for DynamicValueType, Langua...
-#include "lldb/lldb-forward.h" // for ValueObjectSP, Synthetic...
-#include "lldb/lldb-private-enumerations.h" // for LazyBool, LazyBool::eLaz...
-
-#include <cstdint> // for uint32_t, uint64_t
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+
+#include <cstdint>
#include <memory>
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class Declaration;
diff --git a/include/lldb/Core/ValueObjectVariable.h b/include/lldb/Core/ValueObjectVariable.h
index 9dd140a84f45..81a8eabdacbb 100644
--- a/include/lldb/Core/ValueObjectVariable.h
+++ b/include/lldb/Core/ValueObjectVariable.h
@@ -12,15 +12,15 @@
#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/Value.h" // for Value
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ValueType
-#include "lldb/lldb-forward.h" // for VariableSP, ModuleSP, ValueObj...
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include "lldb/Core/Value.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class DataExtractor;
diff --git a/include/lldb/DataFormatters/DataVisualization.h b/include/lldb/DataFormatters/DataVisualization.h
index 369fa686a9ff..9ca2e95cd9cb 100644
--- a/include/lldb/DataFormatters/DataVisualization.h
+++ b/include/lldb/DataFormatters/DataVisualization.h
@@ -10,11 +10,7 @@
#ifndef lldb_DataVisualization_h_
#define lldb_DataVisualization_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Utility/ConstString.h"
diff --git a/include/lldb/DataFormatters/DumpValueObjectOptions.h b/include/lldb/DataFormatters/DumpValueObjectOptions.h
index 00baea77f793..113c48afa6f8 100644
--- a/include/lldb/DataFormatters/DumpValueObjectOptions.h
+++ b/include/lldb/DataFormatters/DumpValueObjectOptions.h
@@ -10,12 +10,8 @@
#ifndef lldb_DumpValueObjectOptions_h_
#define lldb_DumpValueObjectOptions_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/FormatCache.h b/include/lldb/DataFormatters/FormatCache.h
index 9901ec91ebd2..2c09b65a420a 100644
--- a/include/lldb/DataFormatters/FormatCache.h
+++ b/include/lldb/DataFormatters/FormatCache.h
@@ -11,13 +11,9 @@
#ifndef lldb_FormatCache_h_
#define lldb_FormatCache_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/FormatClasses.h b/include/lldb/DataFormatters/FormatClasses.h
index 458477578d3f..1f08485d0292 100644
--- a/include/lldb/DataFormatters/FormatClasses.h
+++ b/include/lldb/DataFormatters/FormatClasses.h
@@ -10,15 +10,11 @@
#ifndef lldb_FormatClasses_h_
#define lldb_FormatClasses_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/TypeFormat.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
diff --git a/include/lldb/DataFormatters/FormatManager.h b/include/lldb/DataFormatters/FormatManager.h
index e973c8b3e849..9046ccf2e0bb 100644
--- a/include/lldb/DataFormatters/FormatManager.h
+++ b/include/lldb/DataFormatters/FormatManager.h
@@ -10,16 +10,12 @@
#ifndef lldb_FormatManager_h_
#define lldb_FormatManager_h_
-// C Includes
-// C++ Includes
#include <atomic>
#include <initializer_list>
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/FormattersContainer.h b/include/lldb/DataFormatters/FormattersContainer.h
index df88e88011fe..dd8995d81132 100644
--- a/include/lldb/DataFormatters/FormattersContainer.h
+++ b/include/lldb/DataFormatters/FormattersContainer.h
@@ -10,16 +10,12 @@
#ifndef lldb_FormattersContainer_h_
#define lldb_FormattersContainer_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <map>
#include <memory>
#include <mutex>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/ValueObject.h"
diff --git a/include/lldb/DataFormatters/FormattersHelpers.h b/include/lldb/DataFormatters/FormattersHelpers.h
index 14ba5e48feb4..028d5cc27688 100644
--- a/include/lldb/DataFormatters/FormattersHelpers.h
+++ b/include/lldb/DataFormatters/FormattersHelpers.h
@@ -11,10 +11,6 @@
#ifndef lldb_FormattersHelpers_h_
#define lldb_FormattersHelpers_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
diff --git a/include/lldb/DataFormatters/LanguageCategory.h b/include/lldb/DataFormatters/LanguageCategory.h
index e94429407837..f2ac628636d4 100644
--- a/include/lldb/DataFormatters/LanguageCategory.h
+++ b/include/lldb/DataFormatters/LanguageCategory.h
@@ -11,11 +11,7 @@
#ifndef lldb_LanguageCategory_h_
#define lldb_LanguageCategory_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormatCache.h"
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/StringPrinter.h b/include/lldb/DataFormatters/StringPrinter.h
index 18207921bb71..38033f915bf9 100644
--- a/include/lldb/DataFormatters/StringPrinter.h
+++ b/include/lldb/DataFormatters/StringPrinter.h
@@ -10,13 +10,9 @@
#ifndef liblldb_StringPrinter_h_
#define liblldb_StringPrinter_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-forward.h"
#include "lldb/Utility/DataExtractor.h"
diff --git a/include/lldb/DataFormatters/TypeCategory.h b/include/lldb/DataFormatters/TypeCategory.h
index 0a5b09baa624..177e602e6ec3 100644
--- a/include/lldb/DataFormatters/TypeCategory.h
+++ b/include/lldb/DataFormatters/TypeCategory.h
@@ -10,16 +10,12 @@
#ifndef lldb_TypeCategory_h_
#define lldb_TypeCategory_h_
-// C Includes
-// C++ Includes
#include <initializer_list>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
@@ -348,7 +344,7 @@ public:
bool IsEnabled() const { return m_enabled; }
uint32_t GetEnabledPosition() {
- if (m_enabled == false)
+ if (!m_enabled)
return UINT32_MAX;
else
return m_enabled_position;
diff --git a/include/lldb/DataFormatters/TypeCategoryMap.h b/include/lldb/DataFormatters/TypeCategoryMap.h
index f767c985ff34..0ff078edf51b 100644
--- a/include/lldb/DataFormatters/TypeCategoryMap.h
+++ b/include/lldb/DataFormatters/TypeCategoryMap.h
@@ -10,15 +10,11 @@
#ifndef lldb_TypeCategoryMap_h_
#define lldb_TypeCategoryMap_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <list>
#include <map>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/TypeFormat.h b/include/lldb/DataFormatters/TypeFormat.h
index 77e3542f5522..57ef0cf942cb 100644
--- a/include/lldb/DataFormatters/TypeFormat.h
+++ b/include/lldb/DataFormatters/TypeFormat.h
@@ -11,16 +11,12 @@
#ifndef lldb_TypeFormat_h_
#define lldb_TypeFormat_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <string>
#include <unordered_map>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/TypeSummary.h b/include/lldb/DataFormatters/TypeSummary.h
index 17cd61ae8c1e..78947728be29 100644
--- a/include/lldb/DataFormatters/TypeSummary.h
+++ b/include/lldb/DataFormatters/TypeSummary.h
@@ -10,16 +10,12 @@
#ifndef lldb_TypeSummary_h_
#define lldb_TypeSummary_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <functional>
#include <memory>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/TypeSynthetic.h b/include/lldb/DataFormatters/TypeSynthetic.h
index 07dacd670a62..a9025fdb5397 100644
--- a/include/lldb/DataFormatters/TypeSynthetic.h
+++ b/include/lldb/DataFormatters/TypeSynthetic.h
@@ -10,18 +10,14 @@
#ifndef lldb_TypeSynthetic_h_
#define lldb_TypeSynthetic_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <functional>
#include <initializer_list>
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/TypeValidator.h b/include/lldb/DataFormatters/TypeValidator.h
index fa2a89148118..a50949cf22fe 100644
--- a/include/lldb/DataFormatters/TypeValidator.h
+++ b/include/lldb/DataFormatters/TypeValidator.h
@@ -11,15 +11,11 @@
#ifndef lldb_TypeValidator_h_
#define lldb_TypeValidator_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/DataFormatters/ValueObjectPrinter.h b/include/lldb/DataFormatters/ValueObjectPrinter.h
index 67048a4932cf..13124c9210c8 100644
--- a/include/lldb/DataFormatters/ValueObjectPrinter.h
+++ b/include/lldb/DataFormatters/ValueObjectPrinter.h
@@ -11,11 +11,7 @@
#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"
@@ -24,10 +20,6 @@
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Symbol/CompilerType.h"
-//#include <functional>
-//#include <memory>
-//#include <set>
-
namespace lldb_private {
class ValueObjectPrinter {
diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h
index b4bd9697da58..cdede56d86d9 100644
--- a/include/lldb/Expression/DWARFExpression.h
+++ b/include/lldb/Expression/DWARFExpression.h
@@ -12,8 +12,8 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private.h"
#include <functional>
@@ -40,7 +40,10 @@ public:
enum LocationListFormat : uint8_t {
NonLocationList, // Not a location list
RegularLocationList, // Location list format used in non-split dwarf files
- SplitDwarfLocationList, // Location list format used in split dwarf files
+ SplitDwarfLocationList, // Location list format used in pre-DWARF v5 split
+ // dwarf files (.debug_loc.dwo)
+ LocLists, // Location list format used in DWARF v5
+ // (.debug_loclists/.debug_loclists.dwo).
};
//------------------------------------------------------------------
@@ -153,6 +156,8 @@ public:
bool Update_DW_OP_addr(lldb::addr_t file_addr);
+ void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
+
bool ContainsThreadLocalStorage() const;
bool LinkThreadLocalStorage(
diff --git a/include/lldb/Expression/Expression.h b/include/lldb/Expression/Expression.h
index 6b9363864722..162dcd3e4672 100644
--- a/include/lldb/Expression/Expression.h
+++ b/include/lldb/Expression/Expression.h
@@ -10,14 +10,10 @@
#ifndef liblldb_Expression_h_
#define liblldb_Expression_h_
-// C Includes
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/ExpressionTypeSystemHelper.h"
#include "lldb/lldb-forward.h"
diff --git a/include/lldb/Expression/ExpressionParser.h b/include/lldb/Expression/ExpressionParser.h
index 66957926650a..7d337bd00ca6 100644
--- a/include/lldb/Expression/ExpressionParser.h
+++ b/include/lldb/Expression/ExpressionParser.h
@@ -10,6 +10,7 @@
#ifndef liblldb_ExpressionParser_h_
#define liblldb_ExpressionParser_h_
+#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-public.h"
@@ -50,6 +51,41 @@ public:
virtual ~ExpressionParser(){};
//------------------------------------------------------------------
+ /// Attempts to find possible command line completions for the given
+ /// expression.
+ ///
+ /// @param[out] request
+ /// The completion request to fill out. The completion should be a string
+ /// that would complete the current token at the cursor position.
+ /// Note that the string in the list replaces the current token
+ /// in the command line.
+ ///
+ /// @param[in] line
+ /// The line with the completion cursor inside the expression as a string.
+ /// The first line in the expression has the number 0.
+ ///
+ /// @param[in] pos
+ /// The character position in the line with the completion cursor.
+ /// If the value is 0, then the cursor is on top of the first character
+ /// in the line (i.e. the user has requested completion from the start of
+ /// the expression).
+ ///
+ /// @param[in] typed_pos
+ /// The cursor position in the line as typed by the user. If the user
+ /// expression has not been transformed in some form (e.g. wrapping it
+ /// in a function body for C languages), then this is equal to the
+ /// 'pos' parameter. The semantics of this value are otherwise equal to
+ /// 'pos' (e.g. a value of 0 means the cursor is at start of the
+ /// expression).
+ ///
+ /// @return
+ /// True if we added any completion results to the output;
+ /// false otherwise.
+ //------------------------------------------------------------------
+ virtual bool Complete(CompletionRequest &request, unsigned line, unsigned pos,
+ unsigned typed_pos) = 0;
+
+ //------------------------------------------------------------------
/// Parse a single expression and convert it to IR using Clang. Don't wrap
/// the expression in anything at all.
///
diff --git a/include/lldb/Expression/ExpressionVariable.h b/include/lldb/Expression/ExpressionVariable.h
index 89b0500faf9c..01e9c416e7c0 100644
--- a/include/lldb/Expression/ExpressionVariable.h
+++ b/include/lldb/Expression/ExpressionVariable.h
@@ -10,15 +10,11 @@
#ifndef liblldb_ExpressionVariable_h_
#define liblldb_ExpressionVariable_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
-// Project includes
#include "lldb/Core/ValueObject.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/Expression/FunctionCaller.h b/include/lldb/Expression/FunctionCaller.h
index c36263e34240..0ec7e202dac9 100644
--- a/include/lldb/Expression/FunctionCaller.h
+++ b/include/lldb/Expression/FunctionCaller.h
@@ -10,15 +10,11 @@
#ifndef liblldb_FunctionCaller_h_
#define liblldb_FunctionCaller_h_
-// C Includes
-// C++ Includes
#include <list>
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/Expression.h"
diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h
index e73f8956d955..b966d135deab 100644
--- a/include/lldb/Expression/IRExecutionUnit.h
+++ b/include/lldb/Expression/IRExecutionUnit.h
@@ -10,18 +10,14 @@
#ifndef liblldb_IRExecutionUnit_h_
#define liblldb_IRExecutionUnit_h_
-// C Includes
-// C++ Includes
#include <atomic>
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/Module.h"
-// Project includes
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -112,7 +108,7 @@ public:
void PopulateSectionList(lldb_private::ObjectFile *obj_file,
lldb_private::SectionList &section_list) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ ArchSpec GetArchitecture() override;
lldb::ModuleSP GetJITModule();
diff --git a/include/lldb/Expression/IRMemoryMap.h b/include/lldb/Expression/IRMemoryMap.h
index df8a03f4763f..026ca6b98110 100644
--- a/include/lldb/Expression/IRMemoryMap.h
+++ b/include/lldb/Expression/IRMemoryMap.h
@@ -39,7 +39,7 @@ public:
IRMemoryMap(lldb::TargetSP target_sp);
~IRMemoryMap();
- enum AllocationPolicy {
+ enum AllocationPolicy : uint8_t {
eAllocationPolicyInvalid =
0, ///< It is an error for an allocation to have this policy.
eAllocationPolicyHostOnly, ///< This allocation was created in the host and
@@ -91,32 +91,32 @@ protected:
private:
struct Allocation {
lldb::addr_t
- m_process_alloc; ///< The (unaligned) base for the remote allocation
+ m_process_alloc; ///< The (unaligned) base for the remote allocation.
lldb::addr_t
- m_process_start; ///< The base address of the allocation in the process
- size_t m_size; ///< The size of the requested allocation
- uint32_t m_permissions; ///< The access permissions on the memory in the
- ///process. In the host, the memory is always
- ///read/write.
- uint8_t m_alignment; ///< The alignment of the requested allocation
+ m_process_start; ///< The base address of the allocation in the process.
+ size_t m_size; ///< The size of the requested allocation.
DataBufferHeap m_data;
- ///< Flags
+ /// Flags. Keep these grouped together to avoid structure padding.
AllocationPolicy m_policy;
bool m_leak;
+ uint8_t m_permissions; ///< The access permissions on the memory in the
+ /// process. In the host, the memory is always
+ /// read/write.
+ uint8_t m_alignment; ///< The alignment of the requested allocation.
public:
Allocation(lldb::addr_t process_alloc, lldb::addr_t process_start,
size_t size, uint32_t permissions, uint8_t alignment,
AllocationPolicy m_policy);
- Allocation()
- : m_process_alloc(LLDB_INVALID_ADDRESS),
- m_process_start(LLDB_INVALID_ADDRESS), m_size(0), m_permissions(0),
- m_alignment(0), m_data(), m_policy(eAllocationPolicyInvalid),
- m_leak(false) {}
+ DISALLOW_COPY_AND_ASSIGN(Allocation);
};
+ static_assert(sizeof(Allocation) <=
+ (4 * sizeof(lldb::addr_t)) + sizeof(DataBufferHeap),
+ "IRMemoryMap::Allocation is larger than expected");
+
lldb::ProcessWP m_process_wp;
lldb::TargetWP m_target_wp;
typedef std::map<lldb::addr_t, Allocation> AllocationMap;
diff --git a/include/lldb/Expression/LLVMUserExpression.h b/include/lldb/Expression/LLVMUserExpression.h
index a2f87e8a6e25..1ba822265fca 100644
--- a/include/lldb/Expression/LLVMUserExpression.h
+++ b/include/lldb/Expression/LLVMUserExpression.h
@@ -10,16 +10,12 @@
#ifndef liblldb_LLVMUserExpression_h
#define liblldb_LLVMUserExpression_h
-// C Includes
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "llvm/IR/LegacyPassManager.h"
-// Project includes
#include "lldb/Expression/UserExpression.h"
namespace lldb_private {
diff --git a/include/lldb/Expression/Materializer.h b/include/lldb/Expression/Materializer.h
index b86bc656d6b5..0bdfd372e921 100644
--- a/include/lldb/Expression/Materializer.h
+++ b/include/lldb/Expression/Materializer.h
@@ -10,13 +10,9 @@
#ifndef liblldb_Materializer_h
#define liblldb_Materializer_h
-// C Includes
-// C++ Includes
#include <memory>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/StackFrame.h"
diff --git a/include/lldb/Expression/REPL.h b/include/lldb/Expression/REPL.h
index 0c1e97fec259..f7780772cbea 100644
--- a/include/lldb/Expression/REPL.h
+++ b/include/lldb/Expression/REPL.h
@@ -10,12 +10,8 @@
#ifndef lldb_REPL_h
#define lldb_REPL_h
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/../../source/Commands/CommandObjectExpression.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
@@ -117,7 +113,7 @@ public:
int IOHandlerComplete(IOHandler &io_handler, const char *current_line,
const char *cursor, const char *last_char,
int skip_first_n_matches, int max_matches,
- StringList &matches) override;
+ StringList &matches, StringList &descriptions) override;
protected:
static int CalculateActualIndentation(const StringList &lines);
diff --git a/include/lldb/Expression/UserExpression.h b/include/lldb/Expression/UserExpression.h
index 96ca80c882e5..812d7e9a0eac 100644
--- a/include/lldb/Expression/UserExpression.h
+++ b/include/lldb/Expression/UserExpression.h
@@ -10,14 +10,10 @@
#ifndef liblldb_UserExpression_h_
#define liblldb_UserExpression_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Expression/Materializer.h"
@@ -98,6 +94,34 @@ public:
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory, bool generate_debug_info) = 0;
+ //------------------------------------------------------------------
+ /// Attempts to find possible command line completions for the given
+ /// (possible incomplete) user expression.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when looking up entities that
+ /// are needed for parsing and completing (locations of functions, types
+ /// of variables, persistent variables, etc.)
+ ///
+ /// @param[out] request
+ /// The completion request to fill out. The completion should be a string
+ /// that would complete the current token at the cursor position.
+ /// Note that the string in the list replaces the current token
+ /// in the command line.
+ ///
+ /// @param[in] complete_pos
+ /// The position of the cursor inside the user expression string.
+ /// The completion process starts on the token that the cursor is in.
+ ///
+ /// @return
+ /// True if we added any completion results to the output;
+ /// false otherwise.
+ //------------------------------------------------------------------
+ virtual bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request,
+ unsigned complete_pos) {
+ return false;
+ }
+
virtual bool CanInterpret() = 0;
bool MatchesContext(ExecutionContext &exe_ctx);
diff --git a/include/lldb/Expression/UtilityFunction.h b/include/lldb/Expression/UtilityFunction.h
index 5d4bc8676b95..4c87f4d10479 100644
--- a/include/lldb/Expression/UtilityFunction.h
+++ b/include/lldb/Expression/UtilityFunction.h
@@ -11,13 +11,9 @@
#ifndef liblldb_UtilityFunction_h_
#define liblldb_UtilityFunction_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/Expression.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Host/Debug.h b/include/lldb/Host/Debug.h
index ed8e633c113f..d88725cf4e2e 100644
--- a/include/lldb/Host/Debug.h
+++ b/include/lldb/Host/Debug.h
@@ -10,12 +10,8 @@
#ifndef liblldb_Debug_h_
#define liblldb_Debug_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
diff --git a/include/lldb/Host/Editline.h b/include/lldb/Host/Editline.h
index beb96e7c4924..51d6e58c1e7a 100644
--- a/include/lldb/Host/Editline.h
+++ b/include/lldb/Host/Editline.h
@@ -54,8 +54,8 @@
#include <vector>
#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Predicate.h"
namespace lldb_private {
namespace line_editor {
@@ -101,7 +101,8 @@ typedef int (*FixIndentationCallbackType)(Editline *editline,
typedef int (*CompleteCallbackType)(const char *current_line,
const char *cursor, const char *last_char,
int skip_first_n_matches, int max_matches,
- StringList &matches, void *baton);
+ StringList &matches,
+ StringList &descriptions, void *baton);
/// Status used to decide when and how to start editing another line in
/// multi-line sessions
diff --git a/include/lldb/Host/File.h b/include/lldb/Host/File.h
index d240f810bc8b..69ae2004e422 100644
--- a/include/lldb/Host/File.h
+++ b/include/lldb/Host/File.h
@@ -33,6 +33,8 @@ public:
static int kInvalidDescriptor;
static FILE *kInvalidStream;
+ // NB this enum is used in the lldb platform gdb-remote packet
+ // vFile:open: and existing values cannot be modified.
enum OpenOptions {
eOpenOptionRead = (1u << 0), // Open file for reading
eOpenOptionWrite = (1u << 1), // Open file for writing
@@ -54,57 +56,15 @@ public:
: IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
m_stream(kInvalidStream), m_options(0), m_own_stream(false),
m_is_interactive(eLazyBoolCalculate),
- m_is_real_terminal(eLazyBoolCalculate) {}
+ m_is_real_terminal(eLazyBoolCalculate),
+ m_supports_colors(eLazyBoolCalculate) {}
File(FILE *fh, bool transfer_ownership)
: IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
m_stream(fh), m_options(0), m_own_stream(transfer_ownership),
m_is_interactive(eLazyBoolCalculate),
- m_is_real_terminal(eLazyBoolCalculate) {}
-
- //------------------------------------------------------------------
- /// Constructor with path.
- ///
- /// Takes a path to a file which can be just a filename, or a full path. If
- /// \a path is not nullptr or empty, this function will call File::Open
- /// (const char *path, uint32_t options, uint32_t permissions).
- ///
- /// @param[in] path
- /// The full or partial path to a 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 char *path, uint32_t options,
- uint32_t permissions = lldb::eFilePermissionsFileDefault);
-
- //------------------------------------------------------------------
- /// 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 nullptr or empty, this function will call
- /// File::Open (const char *path, uint32_t options, uint32_t permissions).
- ///
- /// @param[in] filespec
- /// 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 = lldb::eFilePermissionsFileDefault);
+ m_is_real_terminal(eLazyBoolCalculate),
+ m_supports_colors(eLazyBoolCalculate) {}
File(int fd, bool transfer_ownership)
: IOObject(eFDTypeFile, transfer_ownership), m_descriptor(fd),
@@ -167,23 +127,6 @@ public:
//------------------------------------------------------------------
Status GetFileSpec(FileSpec &file_spec) const;
- //------------------------------------------------------------------
- /// Open a file for read/writing with the specified options.
- ///
- /// Takes a path to a file which can be just a filename, or a full path.
- ///
- /// @param[in] path
- /// The full or partial path to a file.
- ///
- /// @param[in] options
- /// Options to use when opening (see File::OpenOptions)
- ///
- /// @param[in] permissions
- /// Options to use when opening (see File::Permissions)
- //------------------------------------------------------------------
- Status Open(const char *path, uint32_t options,
- uint32_t permissions = lldb::eFilePermissionsFileDefault);
-
Status Close() override;
void Clear();
@@ -417,8 +360,6 @@ public:
//------------------------------------------------------------------
uint32_t GetPermissions(Status &error) const;
- static uint32_t GetPermissions(const FileSpec &file_spec, Status &error);
-
//------------------------------------------------------------------
/// Return true if this file is interactive.
///
@@ -461,8 +402,10 @@ public:
void SetOptions(uint32_t options) { m_options = options; }
+ static bool DescriptorIsValid(int descriptor) { return descriptor >= 0; };
+
protected:
- bool DescriptorIsValid() const { return m_descriptor >= 0; }
+ bool DescriptorIsValid() const { return DescriptorIsValid(m_descriptor); }
bool StreamIsValid() const { return m_stream != kInvalidStream; }
diff --git a/include/lldb/Host/FileSystem.h b/include/lldb/Host/FileSystem.h
index c13d5c84c631..9e36649b0046 100644
--- a/include/lldb/Host/FileSystem.h
+++ b/include/lldb/Host/FileSystem.h
@@ -10,9 +10,14 @@
#ifndef liblldb_Host_FileSystem_h
#define liblldb_Host_FileSystem_h
+#include "lldb/Host/File.h"
+#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
+
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Chrono.h"
+#include "llvm/Support/VirtualFileSystem.h"
#include "lldb/lldb-types.h"
@@ -26,17 +31,147 @@ public:
static const char *DEV_NULL;
static const char *PATH_CONVERSION_ERROR;
- static Status Symlink(const FileSpec &src, const FileSpec &dst);
- static Status Readlink(const FileSpec &src, FileSpec &dst);
+ FileSystem() : m_fs(llvm::vfs::getRealFileSystem()) {}
+ FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs) : m_fs(fs) {}
+
+ FileSystem(const FileSystem &fs) = delete;
+ FileSystem &operator=(const FileSystem &fs) = delete;
+
+ static FileSystem &Instance();
+
+ static void Initialize();
+ static void Initialize(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
+ static void Terminate();
+
+ Status Symlink(const FileSpec &src, const FileSpec &dst);
+ Status Readlink(const FileSpec &src, FileSpec &dst);
+
+ Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst);
+
+ /// Wraps ::fopen in a platform-independent way.
+ FILE *Fopen(const char *path, const char *mode);
+
+ /// Wraps ::open in a platform-independent way.
+ int Open(const char *path, int flags, int mode);
+
+ Status Open(File &File, const FileSpec &file_spec, uint32_t options,
+ uint32_t permissions = lldb::eFilePermissionsFileDefault);
+
+ /// Get a directory iterator.
+ /// @{
+ llvm::vfs::directory_iterator DirBegin(const FileSpec &file_spec,
+ std::error_code &ec);
+ llvm::vfs::directory_iterator DirBegin(const llvm::Twine &dir,
+ std::error_code &ec);
+ /// @}
+
+ /// Returns the Status object for the given file.
+ /// @{
+ llvm::ErrorOr<llvm::vfs::Status> GetStatus(const FileSpec &file_spec) const;
+ llvm::ErrorOr<llvm::vfs::Status> GetStatus(const llvm::Twine &path) const;
+ /// @}
+
+ /// Returns the modification time of the given file.
+ /// @{
+ llvm::sys::TimePoint<> GetModificationTime(const FileSpec &file_spec) const;
+ llvm::sys::TimePoint<> GetModificationTime(const llvm::Twine &path) const;
+ /// @}
+
+ /// Returns the on-disk size of the given file in bytes.
+ /// @{
+ uint64_t GetByteSize(const FileSpec &file_spec) const;
+ uint64_t GetByteSize(const llvm::Twine &path) const;
+ /// @}
+
+ /// Return the current permissions of the given file.
+ ///
+ /// Returns a bitmask for the current permissions of the file (zero or more
+ /// of the permission bits defined in File::Permissions).
+ /// @{
+ uint32_t GetPermissions(const FileSpec &file_spec) const;
+ uint32_t GetPermissions(const llvm::Twine &path) const;
+ uint32_t GetPermissions(const FileSpec &file_spec, std::error_code &ec) const;
+ uint32_t GetPermissions(const llvm::Twine &path, std::error_code &ec) const;
+ /// @}
+
+ /// Returns whether the given file exists.
+ /// @{
+ bool Exists(const FileSpec &file_spec) const;
+ bool Exists(const llvm::Twine &path) const;
+ /// @}
+
+ /// Returns whether the given file is readable.
+ /// @{
+ bool Readable(const FileSpec &file_spec) const;
+ bool Readable(const llvm::Twine &path) const;
+ /// @}
+
+ /// Returns whether the given path is a directory.
+ /// @{
+ bool IsDirectory(const FileSpec &file_spec) const;
+ bool IsDirectory(const llvm::Twine &path) const;
+ /// @}
+
+ /// Returns whether the given path is local to the file system.
+ /// @{
+ bool IsLocal(const FileSpec &file_spec) const;
+ bool IsLocal(const llvm::Twine &path) const;
+ /// @}
+
+ /// Make the given file path absolute.
+ /// @{
+ std::error_code MakeAbsolute(llvm::SmallVectorImpl<char> &path) const;
+ std::error_code MakeAbsolute(FileSpec &file_spec) const;
+ /// @}
+
+ /// Resolve path to make it canonical.
+ /// @{
+ void Resolve(llvm::SmallVectorImpl<char> &path);
+ void Resolve(FileSpec &file_spec);
+ /// @}
+
+ //// Create memory buffer from path.
+ /// @{
+ std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const llvm::Twine &path,
+ uint64_t size = 0,
+ uint64_t offset = 0);
+ std::shared_ptr<DataBufferLLVM> CreateDataBuffer(const FileSpec &file_spec,
+ uint64_t size = 0,
+ uint64_t offset = 0);
+ /// @}
+
+ /// Call into the Host to see if it can help find the file.
+ bool ResolveExecutableLocation(FileSpec &file_spec);
+
+ enum EnumerateDirectoryResult {
+ /// Enumerate next entry in the current directory.
+ eEnumerateDirectoryResultNext,
+ /// Recurse into the current entry if it is a directory or symlink, or next
+ /// if not.
+ eEnumerateDirectoryResultEnter,
+ /// Stop directory enumerations at any level.
+ eEnumerateDirectoryResultQuit
+ };
+
+ typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)(
+ void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef);
+
+ typedef std::function<EnumerateDirectoryResult(
+ llvm::sys::fs::file_type file_type, llvm::StringRef)>
+ DirectoryCallback;
- static Status ResolveSymbolicLink(const FileSpec &src, FileSpec &dst);
+ void EnumerateDirectory(llvm::Twine path, bool find_directories,
+ bool find_files, bool find_other,
+ EnumerateDirectoryCallbackType callback,
+ void *callback_baton);
- /// Wraps ::fopen in a platform-independent way. Once opened, FILEs can be
- /// manipulated and closed with the normal ::fread, ::fclose, etc. functions.
- static FILE *Fopen(const char *path, const char *mode);
+ std::error_code GetRealPath(const llvm::Twine &path,
+ llvm::SmallVectorImpl<char> &output) const;
- static llvm::sys::TimePoint<> GetModificationTime(const FileSpec &file_spec);
+private:
+ static llvm::Optional<FileSystem> &InstanceImpl();
+ llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
};
-}
+} // namespace lldb_private
#endif
diff --git a/include/lldb/Host/HostInfoBase.h b/include/lldb/Host/HostInfoBase.h
index b2567b296277..f3e49c8f25d7 100644
--- a/include/lldb/Host/HostInfoBase.h
+++ b/include/lldb/Host/HostInfoBase.h
@@ -75,10 +75,6 @@ public:
/// member of the FileSpec is filled in.
static FileSpec GetHeaderDir();
- /// Returns the directory containing the python modules. Only the directory
- /// member of the FileSpec is filled in.
- static FileSpec GetPythonDir();
-
/// Returns the directory containing the system plugins. Only the directory
/// member of the FileSpec is filled in.
static FileSpec GetSystemPluginDir();
diff --git a/include/lldb/Host/HostNativeThreadBase.h b/include/lldb/Host/HostNativeThreadBase.h
index f1f89f3b75fe..326a9c6c793f 100644
--- a/include/lldb/Host/HostNativeThreadBase.h
+++ b/include/lldb/Host/HostNativeThreadBase.h
@@ -35,6 +35,7 @@ public:
virtual Status Cancel() = 0;
virtual bool IsJoinable() const;
virtual void Reset();
+ virtual bool EqualsThread(lldb::thread_t thread) const;
lldb::thread_t Release();
lldb::thread_t GetSystemHandle() const;
diff --git a/include/lldb/Host/MonitoringProcessLauncher.h b/include/lldb/Host/MonitoringProcessLauncher.h
index 341284800a4e..179823efb966 100644
--- a/include/lldb/Host/MonitoringProcessLauncher.h
+++ b/include/lldb/Host/MonitoringProcessLauncher.h
@@ -10,11 +10,7 @@
#ifndef lldb_Host_MonitoringProcessLauncher_h_
#define lldb_Host_MonitoringProcessLauncher_h_
-// C Includes
-// C++ Includes
#include <memory>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/ProcessLauncher.h"
namespace lldb_private {
diff --git a/include/lldb/Host/PipeBase.h b/include/lldb/Host/PipeBase.h
index ad62072c7ba5..88bd703960c4 100644
--- a/include/lldb/Host/PipeBase.h
+++ b/include/lldb/Host/PipeBase.h
@@ -41,6 +41,9 @@ public:
virtual bool CanRead() const = 0;
virtual bool CanWrite() const = 0;
+ virtual lldb::pipe_t GetReadPipe() const = 0;
+ virtual lldb::pipe_t GetWritePipe() const = 0;
+
virtual int GetReadFileDescriptor() const = 0;
virtual int GetWriteFileDescriptor() const = 0;
virtual int ReleaseReadFileDescriptor() = 0;
diff --git a/include/lldb/Host/ProcessRunLock.h b/include/lldb/Host/ProcessRunLock.h
index 6f39eea716e8..272772fedce1 100644
--- a/include/lldb/Host/ProcessRunLock.h
+++ b/include/lldb/Host/ProcessRunLock.h
@@ -10,13 +10,9 @@
#ifndef liblldb_ProcessRunLock_h_
#define liblldb_ProcessRunLock_h_
-// C Includes
#include <stdint.h>
#include <time.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
//----------------------------------------------------------------------
diff --git a/include/lldb/Utility/SafeMachO.h b/include/lldb/Host/SafeMachO.h
index 1565b313f42b..1565b313f42b 100644
--- a/include/lldb/Utility/SafeMachO.h
+++ b/include/lldb/Host/SafeMachO.h
diff --git a/include/lldb/Host/Socket.h b/include/lldb/Host/Socket.h
index f6e51fd45679..8b7f9fa4ed93 100644
--- a/include/lldb/Host/Socket.h
+++ b/include/lldb/Host/Socket.h
@@ -15,9 +15,9 @@
#include "lldb/lldb-private.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Host/SocketAddress.h"
#include "lldb/Utility/IOObject.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
#ifdef _WIN32
diff --git a/include/lldb/Host/SocketAddress.h b/include/lldb/Host/SocketAddress.h
index 749a9c664c81..5e54ef1d8e0c 100644
--- a/include/lldb/Host/SocketAddress.h
+++ b/include/lldb/Host/SocketAddress.h
@@ -10,7 +10,6 @@
#ifndef liblldb_SocketAddress_h_
#define liblldb_SocketAddress_h_
-// C Includes
#include <stdint.h>
#ifdef _WIN32
@@ -28,9 +27,6 @@ typedef ADDRESS_FAMILY sa_family_t;
#include <sys/types.h>
#endif
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include <string>
#include <vector>
diff --git a/include/lldb/Host/StringConvert.h b/include/lldb/Host/StringConvert.h
index d197df10d79e..1a85471a20c2 100644
--- a/include/lldb/Host/StringConvert.h
+++ b/include/lldb/Host/StringConvert.h
@@ -10,13 +10,9 @@
#ifndef liblldb_StringConvert_h_
#define liblldb_StringConvert_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
namespace lldb_private {
diff --git a/include/lldb/Host/Symbols.h b/include/lldb/Host/Symbols.h
index ce95d91497f8..8b00900d3321 100644
--- a/include/lldb/Host/Symbols.h
+++ b/include/lldb/Host/Symbols.h
@@ -10,12 +10,8 @@
#ifndef liblldb_Symbols_h_
#define liblldb_Symbols_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/FileSpec.h"
namespace lldb_private {
diff --git a/include/lldb/Host/TaskPool.h b/include/lldb/Host/TaskPool.h
index fe1714151076..4001d187a2a9 100644
--- a/include/lldb/Host/TaskPool.h
+++ b/include/lldb/Host/TaskPool.h
@@ -11,12 +11,12 @@
#define utility_TaskPool_h_
#include "llvm/ADT/STLExtras.h"
-#include <functional> // for bind, function
+#include <functional>
#include <future>
#include <list>
-#include <memory> // for make_shared
-#include <mutex> // for mutex, unique_lock, condition_variable
-#include <type_traits> // for forward, result_of, move
+#include <memory>
+#include <mutex>
+#include <type_traits>
namespace lldb_private {
diff --git a/include/lldb/Host/XML.h b/include/lldb/Host/XML.h
index 5088f1f25b0d..57e300752003 100644
--- a/include/lldb/Host/XML.h
+++ b/include/lldb/Host/XML.h
@@ -10,20 +10,16 @@
#ifndef liblldb_XML_h_
#define liblldb_XML_h_
-// C Includes
#if defined(LIBXML2_DEFINED)
#include <libxml/xmlreader.h>
#endif
-// C++ Includes
#include <functional>
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Host/common/NativeBreakpoint.h b/include/lldb/Host/common/NativeBreakpoint.h
deleted file mode 100644
index 681570aadef0..000000000000
--- a/include/lldb/Host/common/NativeBreakpoint.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===-- NativeBreakpoint.h --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_NativeBreakpoint_h_
-#define liblldb_NativeBreakpoint_h_
-
-#include "lldb/lldb-types.h"
-
-namespace lldb_private {
-class NativeBreakpointList;
-
-class NativeBreakpoint {
- friend class NativeBreakpointList;
-
-public:
- // The assumption is that derived breakpoints are enabled when created.
- NativeBreakpoint(lldb::addr_t addr);
-
- virtual ~NativeBreakpoint();
-
- Status Enable();
-
- Status Disable();
-
- lldb::addr_t GetAddress() const { return m_addr; }
-
- bool IsEnabled() const { return m_enabled; }
-
- virtual bool IsSoftwareBreakpoint() const = 0;
-
-protected:
- const lldb::addr_t m_addr;
- int32_t m_ref_count;
-
- virtual Status DoEnable() = 0;
-
- virtual Status DoDisable() = 0;
-
-private:
- bool m_enabled;
-
- // ----------------------------------------------------------- interface for
- // NativeBreakpointList
- // -----------------------------------------------------------
- void AddRef();
- int32_t DecRef();
-};
-}
-
-#endif // ifndef liblldb_NativeBreakpoint_h_
diff --git a/include/lldb/Host/common/NativeBreakpointList.h b/include/lldb/Host/common/NativeBreakpointList.h
index ffa659fdd869..b57174e51564 100644
--- a/include/lldb/Host/common/NativeBreakpointList.h
+++ b/include/lldb/Host/common/NativeBreakpointList.h
@@ -10,13 +10,9 @@
#ifndef liblldb_NativeBreakpointList_h_
#define liblldb_NativeBreakpointList_h_
-#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-forward.h"
-// #include "lldb/Host/NativeBreakpoint.h"
-
-#include <functional>
+#include "lldb/lldb-types.h"
#include <map>
-#include <mutex>
namespace lldb_private {
@@ -26,35 +22,6 @@ struct HardwareBreakpoint {
};
using HardwareBreakpointMap = std::map<lldb::addr_t, HardwareBreakpoint>;
-
-class NativeBreakpointList {
-public:
- typedef std::function<Status(lldb::addr_t addr, size_t size_hint,
- bool hardware,
- NativeBreakpointSP &breakpoint_sp)>
- CreateBreakpointFunc;
-
- NativeBreakpointList();
-
- Status AddRef(lldb::addr_t addr, size_t size_hint, bool hardware,
- CreateBreakpointFunc create_func);
-
- Status DecRef(lldb::addr_t addr);
-
- Status EnableBreakpoint(lldb::addr_t addr);
-
- Status DisableBreakpoint(lldb::addr_t addr);
-
- Status GetBreakpoint(lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp);
-
- Status RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const;
-
-private:
- typedef std::map<lldb::addr_t, NativeBreakpointSP> BreakpointMap;
-
- std::recursive_mutex m_mutex;
- BreakpointMap m_breakpoints;
-};
}
#endif // ifndef liblldb_NativeBreakpointList_h_
diff --git a/include/lldb/Host/common/NativeProcessProtocol.h b/include/lldb/Host/common/NativeProcessProtocol.h
index d96835d75839..cb3b18eb0a3d 100644
--- a/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/include/lldb/Host/common/NativeProcessProtocol.h
@@ -25,6 +25,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
+#include <mutex>
+#include <unordered_map>
#include <vector>
namespace lldb_private {
@@ -35,8 +37,6 @@ class ResumeActionList;
// NativeProcessProtocol
//------------------------------------------------------------------
class NativeProcessProtocol {
- friend class SoftwareBreakpoint;
-
public:
virtual ~NativeProcessProtocol() {}
@@ -84,8 +84,8 @@ public:
virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size,
size_t &bytes_read) = 0;
- virtual Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
- size_t size, size_t &bytes_read) = 0;
+ Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read);
virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
size_t &bytes_written) = 0;
@@ -111,10 +111,6 @@ public:
virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false);
- virtual Status EnableBreakpoint(lldb::addr_t addr);
-
- virtual Status DisableBreakpoint(lldb::addr_t addr);
-
//----------------------------------------------------------------------
// Hardware Breakpoint functions
//----------------------------------------------------------------------
@@ -402,6 +398,13 @@ public:
}
protected:
+ struct SoftwareBreakpoint {
+ uint32_t ref_count;
+ llvm::SmallVector<uint8_t, 4> saved_opcodes;
+ llvm::ArrayRef<uint8_t> breakpoint_opcodes;
+ };
+
+ std::unordered_map<lldb::addr_t, SoftwareBreakpoint> m_software_breakpoints;
lldb::pid_t m_pid;
std::vector<std::unique_ptr<NativeThreadProtocol>> m_threads;
@@ -415,7 +418,6 @@ protected:
std::recursive_mutex m_delegates_mutex;
std::vector<NativeDelegate *> m_delegates;
- NativeBreakpointList m_breakpoint_list;
NativeWatchpointList m_watchpoint_list;
HardwareBreakpointMap m_hw_breakpoints_map;
int m_terminal_fd;
@@ -446,12 +448,23 @@ protected:
// ----------------------------------------------------------- Internal
// interface for software breakpoints
// -----------------------------------------------------------
+
Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
+ Status RemoveSoftwareBreakpoint(lldb::addr_t addr);
+
+ virtual llvm::Expected<llvm::ArrayRef<uint8_t>>
+ GetSoftwareBreakpointTrapOpcode(size_t size_hint);
+
+ /// Return the offset of the PC relative to the software breakpoint that was hit. If an
+ /// architecture (e.g. arm) reports breakpoint hits before incrementing the PC, this offset
+ /// will be 0. If an architecture (e.g. intel) reports breakpoints hits after incrementing the
+ /// PC, this offset will be the size of the breakpoint opcode.
+ virtual size_t GetSoftwareBreakpointPCOffset();
- virtual Status
- GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes) = 0;
+ // Adjust the thread's PC after hitting a software breakpoint. On
+ // architectures where the PC points after the breakpoint instruction, this
+ // resets it to point to the breakpoint itself.
+ void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread);
// -----------------------------------------------------------
/// Notify the delegate that an exec occurred.
@@ -465,6 +478,8 @@ protected:
private:
void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
+ llvm::Expected<SoftwareBreakpoint>
+ EnableSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint);
};
} // namespace lldb_private
diff --git a/include/lldb/Host/common/NativeRegisterContext.h b/include/lldb/Host/common/NativeRegisterContext.h
index 26458db153c1..268e0f2473fd 100644
--- a/include/lldb/Host/common/NativeRegisterContext.h
+++ b/include/lldb/Host/common/NativeRegisterContext.h
@@ -10,10 +10,6 @@
#ifndef liblldb_NativeRegisterContext_h_
#define liblldb_NativeRegisterContext_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/common/NativeWatchpointList.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Host/common/SoftwareBreakpoint.h b/include/lldb/Host/common/SoftwareBreakpoint.h
deleted file mode 100644
index e0f235fecd93..000000000000
--- a/include/lldb/Host/common/SoftwareBreakpoint.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===-- SoftwareBreakpoint.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_SoftwareBreakpoint_h_
-#define liblldb_SoftwareBreakpoint_h_
-
-#include "NativeBreakpoint.h"
-#include "lldb/lldb-private-forward.h"
-
-namespace lldb_private {
-class SoftwareBreakpoint : public NativeBreakpoint {
- friend class NativeBreakpointList;
-
-public:
- static Status CreateSoftwareBreakpoint(NativeProcessProtocol &process,
- lldb::addr_t addr, size_t size_hint,
- NativeBreakpointSP &breakpoint_spn);
-
- SoftwareBreakpoint(NativeProcessProtocol &process, lldb::addr_t addr,
- const uint8_t *saved_opcodes, const uint8_t *trap_opcodes,
- size_t opcode_size);
-
-protected:
- Status DoEnable() override;
-
- Status DoDisable() override;
-
- bool IsSoftwareBreakpoint() const override;
-
-private:
- /// Max number of bytes that a software trap opcode sequence can occupy.
- static const size_t MAX_TRAP_OPCODE_SIZE = 8;
-
- NativeProcessProtocol &m_process;
- uint8_t m_saved_opcodes[MAX_TRAP_OPCODE_SIZE];
- uint8_t m_trap_opcodes[MAX_TRAP_OPCODE_SIZE];
- const size_t m_opcode_size;
-
- static Status EnableSoftwareBreakpoint(NativeProcessProtocol &process,
- lldb::addr_t addr,
- size_t bp_opcode_size,
- const uint8_t *bp_opcode_bytes,
- uint8_t *saved_opcode_bytes);
-};
-}
-
-#endif // #ifndef liblldb_SoftwareBreakpoint_h_
diff --git a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
index 0d125ca2c813..e44737e481e6 100644
--- a/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
+++ b/include/lldb/Host/posix/ConnectionFileDescriptorPosix.h
@@ -10,19 +10,16 @@
#ifndef liblldb_Host_posix_ConnectionFileDescriptorPosix_h_
#define liblldb_Host_posix_ConnectionFileDescriptorPosix_h_
-// C++ Includes
#include <atomic>
#include <memory>
#include <mutex>
#include "lldb/lldb-forward.h"
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/Pipe.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Utility/Connection.h"
#include "lldb/Utility/IOObject.h"
+#include "lldb/Utility/Predicate.h"
namespace lldb_private {
diff --git a/include/lldb/Host/posix/HostProcessPosix.h b/include/lldb/Host/posix/HostProcessPosix.h
index 0a6d8822d44f..2cbd4871dd6a 100644
--- a/include/lldb/Host/posix/HostProcessPosix.h
+++ b/include/lldb/Host/posix/HostProcessPosix.h
@@ -10,10 +10,6 @@
#ifndef lldb_Host_HostProcesPosix_h_
#define lldb_Host_HostProcesPosix_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/HostNativeProcessBase.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-types.h"
diff --git a/include/lldb/Host/posix/PipePosix.h b/include/lldb/Host/posix/PipePosix.h
index bb65a56abd00..30d19d97152b 100644
--- a/include/lldb/Host/posix/PipePosix.h
+++ b/include/lldb/Host/posix/PipePosix.h
@@ -27,7 +27,7 @@ public:
static int kInvalidDescriptor;
PipePosix();
- PipePosix(int read_fd, int write_fd);
+ PipePosix(lldb::pipe_t read, lldb::pipe_t write);
PipePosix(const PipePosix &) = delete;
PipePosix(PipePosix &&pipe_posix);
PipePosix &operator=(const PipePosix &) = delete;
@@ -49,6 +49,13 @@ public:
bool CanRead() const override;
bool CanWrite() const override;
+ lldb::pipe_t GetReadPipe() const override {
+ return lldb::pipe_t(GetReadFileDescriptor());
+ }
+ lldb::pipe_t GetWritePipe() const override {
+ return lldb::pipe_t(GetWriteFileDescriptor());
+ }
+
int GetReadFileDescriptor() const override;
int GetWriteFileDescriptor() const override;
int ReleaseReadFileDescriptor() override;
diff --git a/include/lldb/Host/windows/HostThreadWindows.h b/include/lldb/Host/windows/HostThreadWindows.h
index 35d83c0ba2b2..8d5972e88fbc 100644
--- a/include/lldb/Host/windows/HostThreadWindows.h
+++ b/include/lldb/Host/windows/HostThreadWindows.h
@@ -29,6 +29,7 @@ public:
virtual Status Join(lldb::thread_result_t *result);
virtual Status Cancel();
virtual void Reset();
+ virtual bool EqualsThread(lldb::thread_t thread) const;
lldb::tid_t GetThreadId() const;
diff --git a/include/lldb/Host/windows/PipeWindows.h b/include/lldb/Host/windows/PipeWindows.h
index e309c421a71c..1ae780ccc0b6 100644
--- a/include/lldb/Host/windows/PipeWindows.h
+++ b/include/lldb/Host/windows/PipeWindows.h
@@ -24,10 +24,18 @@ namespace lldb_private {
//----------------------------------------------------------------------
class PipeWindows : public PipeBase {
public:
+ static const int kInvalidDescriptor = -1;
+
+public:
PipeWindows();
+ PipeWindows(lldb::pipe_t read, lldb::pipe_t write);
~PipeWindows() override;
+ // Create an unnamed pipe.
Status CreateNew(bool child_process_inherit) override;
+
+ // Create a named pipe.
+ Status CreateNewNamed(bool child_process_inherit);
Status CreateNew(llvm::StringRef name, bool child_process_inherit) override;
Status CreateWithUniqueName(llvm::StringRef prefix,
bool child_process_inherit,
@@ -41,6 +49,9 @@ public:
bool CanRead() const override;
bool CanWrite() const override;
+ lldb::pipe_t GetReadPipe() const { return lldb::pipe_t(m_read); }
+ lldb::pipe_t GetWritePipe() const { return lldb::pipe_t(m_write); }
+
int GetReadFileDescriptor() const override;
int GetWriteFileDescriptor() const override;
int ReleaseReadFileDescriptor() override;
diff --git a/include/lldb/Host/windows/editlinewin.h b/include/lldb/Host/windows/editlinewin.h
index 4522f0dd41b0..2bd637848ff0 100644
--- a/include/lldb/Host/windows/editlinewin.h
+++ b/include/lldb/Host/windows/editlinewin.h
@@ -113,4 +113,4 @@ void el_deletestr(EditLine *, int);
History *history_init(void);
void history_end(History *);
int history(History *, HistEvent *, int, ...);
-}; \ No newline at end of file
+};
diff --git a/include/lldb/Host/windows/windows.h b/include/lldb/Host/windows/windows.h
index 3dc9f77f8e24..98a675eed4fe 100644
--- a/include/lldb/Host/windows/windows.h
+++ b/include/lldb/Host/windows/windows.h
@@ -21,6 +21,7 @@
#undef GetUserName
#undef LoadImage
#undef CreateProcess
+#undef Yield
#undef far
#undef near
#undef FAR
diff --git a/include/lldb/Initialization/SystemInitializer.h b/include/lldb/Initialization/SystemInitializer.h
index 58bbb44b1f34..b665b9997214 100644
--- a/include/lldb/Initialization/SystemInitializer.h
+++ b/include/lldb/Initialization/SystemInitializer.h
@@ -10,13 +10,24 @@
#ifndef LLDB_INITIALIZATION_SYSTEM_INITIALIZER_H
#define LLDB_INITIALIZATION_SYSTEM_INITIALIZER_H
+#include "llvm/Support/Error.h"
+
+#include <string>
+
namespace lldb_private {
+
+struct InitializerOptions {
+ bool reproducer_capture = false;
+ bool reproducer_replay = false;
+ std::string reproducer_path;
+};
+
class SystemInitializer {
public:
SystemInitializer();
virtual ~SystemInitializer();
- virtual void Initialize() = 0;
+ virtual llvm::Error Initialize(const InitializerOptions &options) = 0;
virtual void Terminate() = 0;
};
}
diff --git a/include/lldb/Initialization/SystemInitializerCommon.h b/include/lldb/Initialization/SystemInitializerCommon.h
index 2a9851c6a34c..f33acaf40466 100644
--- a/include/lldb/Initialization/SystemInitializerCommon.h
+++ b/include/lldb/Initialization/SystemInitializerCommon.h
@@ -28,7 +28,7 @@ public:
SystemInitializerCommon();
~SystemInitializerCommon() override;
- void Initialize() override;
+ llvm::Error Initialize(const InitializerOptions &options) override;
void Terminate() override;
};
diff --git a/include/lldb/Initialization/SystemLifetimeManager.h b/include/lldb/Initialization/SystemLifetimeManager.h
index 0ebd4a50a342..0839856f21e2 100644
--- a/include/lldb/Initialization/SystemLifetimeManager.h
+++ b/include/lldb/Initialization/SystemLifetimeManager.h
@@ -10,21 +10,23 @@
#ifndef LLDB_INITIALIZATION_SYSTEM_LIFETIME_MANAGER_H
#define LLDB_INITIALIZATION_SYSTEM_LIFETIME_MANAGER_H
+#include "lldb/Initialization/SystemInitializer.h"
#include "lldb/lldb-private-types.h"
+#include "llvm/Support/Error.h"
#include <memory>
#include <mutex>
namespace lldb_private {
-class SystemInitializer;
class SystemLifetimeManager {
public:
SystemLifetimeManager();
~SystemLifetimeManager();
- void Initialize(std::unique_ptr<SystemInitializer> initializer,
- LoadPluginCallbackType plugin_callback);
+ llvm::Error Initialize(std::unique_ptr<SystemInitializer> initializer,
+ const InitializerOptions &options,
+ LoadPluginCallbackType plugin_callback);
void Terminate();
private:
diff --git a/include/lldb/Interpreter/CommandAlias.h b/include/lldb/Interpreter/CommandAlias.h
index 01522bd6ecea..c865ad7ff2c9 100644
--- a/include/lldb/Interpreter/CommandAlias.h
+++ b/include/lldb/Interpreter/CommandAlias.h
@@ -10,12 +10,8 @@
#ifndef liblldb_CommandAlias_h_
#define liblldb_CommandAlias_h_
-// C Includes
-// C++ Includes
#include <memory>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/CompletionRequest.h"
diff --git a/include/lldb/Interpreter/CommandCompletions.h b/include/lldb/Interpreter/CommandCompletions.h
index d17864e05f3e..71b0af3295b6 100644
--- a/include/lldb/Interpreter/CommandCompletions.h
+++ b/include/lldb/Interpreter/CommandCompletions.h
@@ -10,12 +10,8 @@
#ifndef lldb_CommandCompletions_h_
#define lldb_CommandCompletions_h_
-// C Includes
-// C++ Includes
#include <set>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/SearchFilter.h"
#include "lldb/Utility/CompletionRequest.h"
@@ -116,7 +112,7 @@ public:
CallbackReturn SearchCallback(SearchFilter &filter, SymbolContext &context,
Address *addr, bool complete) override = 0;
- Depth GetDepth() override = 0;
+ lldb::SearchDepth GetDepth() override = 0;
virtual size_t DoCompletion(SearchFilter *filter) = 0;
@@ -136,7 +132,7 @@ public:
SourceFileCompleter(CommandInterpreter &interpreter,
bool include_support_files, CompletionRequest &request);
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
SymbolContext &context,
@@ -162,7 +158,7 @@ public:
ModuleCompleter(CommandInterpreter &interpreter,
CompletionRequest &request);
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
SymbolContext &context,
@@ -186,7 +182,7 @@ public:
SymbolCompleter(CommandInterpreter &interpreter,
CompletionRequest &request);
- Searcher::Depth GetDepth() override;
+ lldb::SearchDepth GetDepth() override;
Searcher::CallbackReturn SearchCallback(SearchFilter &filter,
SymbolContext &context,
diff --git a/include/lldb/Interpreter/CommandHistory.h b/include/lldb/Interpreter/CommandHistory.h
index faef220bbe94..f414c55e2d64 100644
--- a/include/lldb/Interpreter/CommandHistory.h
+++ b/include/lldb/Interpreter/CommandHistory.h
@@ -10,14 +10,10 @@
#ifndef liblldb_CommandHistory_h_
#define liblldb_CommandHistory_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Interpreter/CommandInterpreter.h b/include/lldb/Interpreter/CommandInterpreter.h
index 78f505c24754..558246037ad0 100644
--- a/include/lldb/Interpreter/CommandInterpreter.h
+++ b/include/lldb/Interpreter/CommandInterpreter.h
@@ -10,80 +10,81 @@
#ifndef liblldb_CommandInterpreter_h_
#define liblldb_CommandInterpreter_h_
-// C Includes
-// C++ Includes
-#include <mutex>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandAlias.h"
#include "lldb/Interpreter/CommandHistory.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/CompletionRequest.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StringList.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
+#include <mutex>
namespace lldb_private {
class CommandInterpreterRunOptions {
public:
//------------------------------------------------------------------
- /// Construct a CommandInterpreterRunOptions object.
- /// This class is used to control all the instances where we run multiple
- /// commands, e.g.
+ /// Construct a CommandInterpreterRunOptions object. This class is used to
+ /// control all the instances where we run multiple commands, e.g.
/// HandleCommands, HandleCommandsFromFile, RunCommandInterpreter.
+ ///
/// The meanings of the options in this object are:
///
/// @param[in] stop_on_continue
- /// If \b true execution will end on the first command that causes the
- /// process in the
- /// execution context to continue. If \false, we won't check the execution
- /// status.
+ /// If \b true, execution will end on the first command that causes the
+ /// process in the execution context to continue. If \b false, we won't
+ /// check the execution status.
/// @param[in] stop_on_error
- /// If \b true execution will end on the first command that causes an
+ /// If \b true, execution will end on the first command that causes an
/// error.
/// @param[in] stop_on_crash
- /// If \b true when a command causes the target to run, and the end of the
- /// run is a
- /// signal or exception, stop executing the commands.
+ /// If \b true, when a command causes the target to run, and the end of the
+ /// run is a signal or exception, stop executing the commands.
/// @param[in] echo_commands
- /// If \b true echo the command before executing it. If \false, execute
+ /// If \b true, echo the command before executing it. If \b false, execute
/// silently.
+ /// @param[in] echo_comments
+ /// If \b true, echo command even if it is a pure comment line. If
+ /// \b false, print no ouput in this case. This setting has an effect only
+ /// if \param echo_commands is \b true.
/// @param[in] print_results
- /// If \b true print the results of the command after executing it. If
- /// \false, execute silently.
+ /// If \b true print the results of the command after executing it. If
+ /// \b false, execute silently.
/// @param[in] add_to_history
- /// If \b true add the commands to the command history. If \false, don't
+ /// If \b true add the commands to the command history. If \b false, don't
/// add them.
//------------------------------------------------------------------
CommandInterpreterRunOptions(LazyBool stop_on_continue,
LazyBool stop_on_error, LazyBool stop_on_crash,
- LazyBool echo_commands, LazyBool print_results,
- LazyBool add_to_history)
+ LazyBool echo_commands, LazyBool echo_comments,
+ LazyBool print_results, LazyBool add_to_history)
: m_stop_on_continue(stop_on_continue), m_stop_on_error(stop_on_error),
m_stop_on_crash(stop_on_crash), m_echo_commands(echo_commands),
- m_print_results(print_results), m_add_to_history(add_to_history) {}
+ m_echo_comment_commands(echo_comments), m_print_results(print_results),
+ m_add_to_history(add_to_history) {}
CommandInterpreterRunOptions()
: m_stop_on_continue(eLazyBoolCalculate),
m_stop_on_error(eLazyBoolCalculate),
m_stop_on_crash(eLazyBoolCalculate),
m_echo_commands(eLazyBoolCalculate),
+ m_echo_comment_commands(eLazyBoolCalculate),
m_print_results(eLazyBoolCalculate),
m_add_to_history(eLazyBoolCalculate) {}
void SetSilent(bool silent) {
LazyBool value = silent ? eLazyBoolNo : eLazyBoolYes;
- m_echo_commands = value;
m_print_results = value;
+ m_echo_commands = value;
+ m_echo_comment_commands = value;
m_add_to_history = value;
}
// These return the default behaviors if the behavior is not
@@ -97,7 +98,7 @@ public:
m_stop_on_continue = stop_on_continue ? eLazyBoolYes : eLazyBoolNo;
}
- bool GetStopOnError() const { return DefaultToNo(m_stop_on_continue); }
+ bool GetStopOnError() const { return DefaultToNo(m_stop_on_error); }
void SetStopOnError(bool stop_on_error) {
m_stop_on_error = stop_on_error ? eLazyBoolYes : eLazyBoolNo;
@@ -115,6 +116,14 @@ public:
m_echo_commands = echo_commands ? eLazyBoolYes : eLazyBoolNo;
}
+ bool GetEchoCommentCommands() const {
+ return DefaultToYes(m_echo_comment_commands);
+ }
+
+ void SetEchoCommentCommands(bool echo_comments) {
+ m_echo_comment_commands = echo_comments ? eLazyBoolYes : eLazyBoolNo;
+ }
+
bool GetPrintResults() const { return DefaultToYes(m_print_results); }
void SetPrintResults(bool print_results) {
@@ -131,6 +140,7 @@ public:
LazyBool m_stop_on_error;
LazyBool m_stop_on_crash;
LazyBool m_echo_commands;
+ LazyBool m_echo_comment_commands;
LazyBool m_print_results;
LazyBool m_add_to_history;
@@ -206,7 +216,8 @@ public:
bool include_aliases) const;
CommandObject *GetCommandObject(llvm::StringRef cmd,
- StringList *matches = nullptr) const;
+ StringList *matches = nullptr,
+ StringList *descriptions = nullptr) const;
bool CommandExists(llvm::StringRef cmd) const;
@@ -310,7 +321,8 @@ public:
// FIXME: Only max_return_elements == -1 is supported at present.
int HandleCompletion(const char *current_line, const char *cursor,
const char *last_char, int match_start_point,
- int max_return_elements, StringList &matches);
+ int max_return_elements, StringList &matches,
+ StringList &descriptions);
// This version just returns matches, and doesn't compute the substring. It
// is here so the Help command can call it for the first argument. It uses
@@ -319,7 +331,8 @@ public:
int GetCommandNamesMatchingPartialString(const char *cmd_cstr,
bool include_aliases,
- StringList &matches);
+ StringList &matches,
+ StringList &descriptions);
void GetHelp(CommandReturnObject &result,
uint32_t types = eCommandTypesAllThem);
@@ -456,6 +469,12 @@ public:
void SetPromptOnQuit(bool b);
+ bool GetEchoCommands() const;
+ void SetEchoCommands(bool b);
+
+ bool GetEchoCommentCommands() const;
+ void SetEchoCommentCommands(bool b);
+
//------------------------------------------------------------------
/// Specify if the command interpreter should allow that the user can
/// specify a custom exit code when calling 'quit'.
@@ -520,7 +539,8 @@ protected:
lldb::CommandObjectSP GetCommandSP(llvm::StringRef cmd,
bool include_aliases = true,
bool exact = true,
- StringList *matches = nullptr) const;
+ StringList *matches = nullptr,
+ StringList *descriptions = nullptr) const;
private:
Status PreprocessCommand(std::string &command);
@@ -538,6 +558,9 @@ private:
// An interruptible wrapper around the stream output
void PrintCommandOutput(Stream &stream, llvm::StringRef str);
+ bool EchoCommandNonInteractive(llvm::StringRef line,
+ const Flags &io_handler_flags) const;
+
// A very simple state machine which models the command handling transitions
enum class CommandHandlingState {
eIdle,
diff --git a/include/lldb/Interpreter/CommandObject.h b/include/lldb/Interpreter/CommandObject.h
index 7afb18b2f598..f72628b8a643 100644
--- a/include/lldb/Interpreter/CommandObject.h
+++ b/include/lldb/Interpreter/CommandObject.h
@@ -10,14 +10,10 @@
#ifndef liblldb_CommandObject_h_
#define liblldb_CommandObject_h_
-// C Includes
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Flags.h"
#include "lldb/Interpreter/CommandCompletions.h"
@@ -37,8 +33,9 @@ namespace lldb_private {
// number added.
template <typename ValueType>
-int AddNamesMatchingPartialString(const std::map<std::string, ValueType> &in_map,
- llvm::StringRef cmd_str, StringList &matches) {
+int AddNamesMatchingPartialString(
+ const std::map<std::string, ValueType> &in_map, llvm::StringRef cmd_str,
+ StringList &matches, StringList *descriptions = nullptr) {
int number_added = 0;
const bool add_all = cmd_str.empty();
@@ -47,6 +44,8 @@ int AddNamesMatchingPartialString(const std::map<std::string, ValueType> &in_map
if (add_all || (iter->first.find(cmd_str, 0) == 0)) {
++number_added;
matches.AppendString(iter->first.c_str());
+ if (descriptions)
+ descriptions->AppendString(iter->second->GetHelp());
}
}
diff --git a/include/lldb/Interpreter/CommandObjectMultiword.h b/include/lldb/Interpreter/CommandObjectMultiword.h
index d9eff9a6e545..e1ea39f7ec34 100644
--- a/include/lldb/Interpreter/CommandObjectMultiword.h
+++ b/include/lldb/Interpreter/CommandObjectMultiword.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectMultiword_h_
#define liblldb_CommandObjectMultiword_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Utility/CompletionRequest.h"
diff --git a/include/lldb/Interpreter/CommandObjectRegexCommand.h b/include/lldb/Interpreter/CommandObjectRegexCommand.h
index 36c3f068bdf3..d50bc3ba9141 100644
--- a/include/lldb/Interpreter/CommandObjectRegexCommand.h
+++ b/include/lldb/Interpreter/CommandObjectRegexCommand.h
@@ -10,12 +10,8 @@
#ifndef liblldb_CommandObjectRegexCommand_h_
#define liblldb_CommandObjectRegexCommand_h_
-// C Includes
-// C++ Includes
#include <list>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/RegularExpression.h"
diff --git a/include/lldb/Interpreter/CommandOptionValidators.h b/include/lldb/Interpreter/CommandOptionValidators.h
index 05724cace172..e0c8ddde6ecb 100644
--- a/include/lldb/Interpreter/CommandOptionValidators.h
+++ b/include/lldb/Interpreter/CommandOptionValidators.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandOptionValidators_h_
#define liblldb_CommandOptionValidators_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private-types.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/CommandReturnObject.h b/include/lldb/Interpreter/CommandReturnObject.h
index 7b04c391bc76..53a908f97ccb 100644
--- a/include/lldb/Interpreter/CommandReturnObject.h
+++ b/include/lldb/Interpreter/CommandReturnObject.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandReturnObject_h_
#define liblldb_CommandReturnObject_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/STLUtils.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Utility/StreamString.h"
diff --git a/include/lldb/Interpreter/OptionArgParser.h b/include/lldb/Interpreter/OptionArgParser.h
index 5ace7e5d0250..b5a083929067 100644
--- a/include/lldb/Interpreter/OptionArgParser.h
+++ b/include/lldb/Interpreter/OptionArgParser.h
@@ -24,7 +24,7 @@ struct OptionArgParser {
static char ToChar(llvm::StringRef s, char fail_value, bool *success_ptr);
static int64_t ToOptionEnum(llvm::StringRef s,
- OptionEnumValueElement *enum_values,
+ const OptionEnumValues &enum_values,
int32_t fail_value, Status &error);
static lldb::ScriptLanguage ToScriptLanguage(llvm::StringRef s,
diff --git a/include/lldb/Interpreter/OptionGroupBoolean.h b/include/lldb/Interpreter/OptionGroupBoolean.h
index 2489a648dd7e..161c12a41f9f 100644
--- a/include/lldb/Interpreter/OptionGroupBoolean.h
+++ b/include/lldb/Interpreter/OptionGroupBoolean.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupBoolean_h_
#define liblldb_OptionGroupBoolean_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupFile.h b/include/lldb/Interpreter/OptionGroupFile.h
index d0c25b8bf8e6..4a56e4c742fd 100644
--- a/include/lldb/Interpreter/OptionGroupFile.h
+++ b/include/lldb/Interpreter/OptionGroupFile.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupFile_h_
#define liblldb_OptionGroupFile_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueFileSpec.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupFormat.h b/include/lldb/Interpreter/OptionGroupFormat.h
index ddf2ccece3bd..52113d8777f5 100644
--- a/include/lldb/Interpreter/OptionGroupFormat.h
+++ b/include/lldb/Interpreter/OptionGroupFormat.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupFormat_h_
#define liblldb_OptionGroupFormat_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueFormat.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
diff --git a/include/lldb/Interpreter/OptionGroupOutputFile.h b/include/lldb/Interpreter/OptionGroupOutputFile.h
index 19453c6215ef..88d45797358d 100644
--- a/include/lldb/Interpreter/OptionGroupOutputFile.h
+++ b/include/lldb/Interpreter/OptionGroupOutputFile.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupOutputFile_h_
#define liblldb_OptionGroupOutputFile_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueBoolean.h"
#include "lldb/Interpreter/OptionValueFileSpec.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupPlatform.h b/include/lldb/Interpreter/OptionGroupPlatform.h
index cda4246f1b01..9bc9588deab3 100644
--- a/include/lldb/Interpreter/OptionGroupPlatform.h
+++ b/include/lldb/Interpreter/OptionGroupPlatform.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupPlatform_h_
#define liblldb_OptionGroupPlatform_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/Options.h"
#include "lldb/Utility/ConstString.h"
#include "llvm/Support/VersionTuple.h"
diff --git a/include/lldb/Interpreter/OptionGroupString.h b/include/lldb/Interpreter/OptionGroupString.h
index 01e8aa9dc3b6..41889fe57d77 100644
--- a/include/lldb/Interpreter/OptionGroupString.h
+++ b/include/lldb/Interpreter/OptionGroupString.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupString_h_
#define liblldb_OptionGroupString_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupUInt64.h b/include/lldb/Interpreter/OptionGroupUInt64.h
index 82eb0e26af9b..d6b06066b964 100644
--- a/include/lldb/Interpreter/OptionGroupUInt64.h
+++ b/include/lldb/Interpreter/OptionGroupUInt64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupUInt64_h_
#define liblldb_OptionGroupUInt64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupUUID.h b/include/lldb/Interpreter/OptionGroupUUID.h
index def97d5f2551..390f128a8618 100644
--- a/include/lldb/Interpreter/OptionGroupUUID.h
+++ b/include/lldb/Interpreter/OptionGroupUUID.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupUUID_h_
#define liblldb_OptionGroupUUID_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueUUID.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
index 0e075773b3f7..8684453d89c6 100644
--- a/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
+++ b/include/lldb/Interpreter/OptionGroupValueObjectDisplay.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupValueObjectDisplay_h_
#define liblldb_OptionGroupValueObjectDisplay_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/Options.h"
diff --git a/include/lldb/Interpreter/OptionGroupVariable.h b/include/lldb/Interpreter/OptionGroupVariable.h
index c9e90320e141..663705acebbc 100644
--- a/include/lldb/Interpreter/OptionGroupVariable.h
+++ b/include/lldb/Interpreter/OptionGroupVariable.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupVariable_h_
#define liblldb_OptionGroupVariable_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/Options.h"
@@ -39,6 +35,8 @@ public:
bool include_frame_options : 1,
show_args : 1, // Frame option only (include_frame_options == true)
+ show_recognized_args : 1, // Frame option only (include_frame_options ==
+ // true)
show_locals : 1, // Frame option only (include_frame_options == true)
show_globals : 1, // Frame option only (include_frame_options == true)
use_regex : 1, show_scope : 1, show_decl : 1;
diff --git a/include/lldb/Interpreter/OptionGroupWatchpoint.h b/include/lldb/Interpreter/OptionGroupWatchpoint.h
index f2665638ba85..2d4456ef31a9 100644
--- a/include/lldb/Interpreter/OptionGroupWatchpoint.h
+++ b/include/lldb/Interpreter/OptionGroupWatchpoint.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionGroupWatchpoint_h_
#define liblldb_OptionGroupWatchpoint_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/Options.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValue.h b/include/lldb/Interpreter/OptionValue.h
index 4748e309c77e..e90d7ed6d8eb 100644
--- a/include/lldb/Interpreter/OptionValue.h
+++ b/include/lldb/Interpreter/OptionValue.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValue_h_
#define liblldb_OptionValue_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/FormatEntity.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/ConstString.h"
@@ -58,9 +54,11 @@ public:
eDumpOptionValue = (1u << 2),
eDumpOptionDescription = (1u << 3),
eDumpOptionRaw = (1u << 4),
+ eDumpOptionCommand = (1u << 5),
eDumpGroupValue = (eDumpOptionName | eDumpOptionType | eDumpOptionValue),
eDumpGroupHelp =
- (eDumpOptionName | eDumpOptionType | eDumpOptionDescription)
+ (eDumpOptionName | eDumpOptionType | eDumpOptionDescription),
+ eDumpGroupExport = (eDumpOptionCommand | eDumpOptionName | eDumpOptionValue)
};
OptionValue()
diff --git a/include/lldb/Interpreter/OptionValueArgs.h b/include/lldb/Interpreter/OptionValueArgs.h
index 433679da134e..41af1298c2cb 100644
--- a/include/lldb/Interpreter/OptionValueArgs.h
+++ b/include/lldb/Interpreter/OptionValueArgs.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueArgs_h_
#define liblldb_OptionValueArgs_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValueArray.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueArray.h b/include/lldb/Interpreter/OptionValueArray.h
index 44709d00763f..06c482840260 100644
--- a/include/lldb/Interpreter/OptionValueArray.h
+++ b/include/lldb/Interpreter/OptionValueArray.h
@@ -10,12 +10,8 @@
#ifndef liblldb_OptionValueArray_h_
#define liblldb_OptionValueArray_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueBoolean.h b/include/lldb/Interpreter/OptionValueBoolean.h
index 6d2a16e59597..572e6b1861fb 100644
--- a/include/lldb/Interpreter/OptionValueBoolean.h
+++ b/include/lldb/Interpreter/OptionValueBoolean.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueBoolean_h_
#define liblldb_OptionValueBoolean_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueChar.h b/include/lldb/Interpreter/OptionValueChar.h
index 0c5f602efe9b..e73976fefccc 100644
--- a/include/lldb/Interpreter/OptionValueChar.h
+++ b/include/lldb/Interpreter/OptionValueChar.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueChar_h_
#define liblldb_OptionValueChar_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueDictionary.h b/include/lldb/Interpreter/OptionValueDictionary.h
index 4e8c86008ea4..b6163e7a9a25 100644
--- a/include/lldb/Interpreter/OptionValueDictionary.h
+++ b/include/lldb/Interpreter/OptionValueDictionary.h
@@ -10,12 +10,8 @@
#ifndef liblldb_OptionValueDictionary_h_
#define liblldb_OptionValueDictionary_h_
-// C Includes
-// C++ Includes
#include <map>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueEnumeration.h b/include/lldb/Interpreter/OptionValueEnumeration.h
index 08d6ac70de52..16c09c589a27 100644
--- a/include/lldb/Interpreter/OptionValueEnumeration.h
+++ b/include/lldb/Interpreter/OptionValueEnumeration.h
@@ -30,8 +30,7 @@ public:
typedef UniqueCStringMap<EnumeratorInfo> EnumerationMap;
typedef EnumerationMap::Entry EnumerationMapEntry;
- OptionValueEnumeration(const OptionEnumValueElement *enumerators,
- enum_type value);
+ OptionValueEnumeration(const OptionEnumValues &enumerators, enum_type value);
~OptionValueEnumeration() override;
@@ -80,7 +79,7 @@ public:
void SetDefaultValue(enum_type value) { m_default_value = value; }
protected:
- void SetEnumerations(const OptionEnumValueElement *enumerators);
+ void SetEnumerations(const OptionEnumValues &enumerators);
enum_type m_current_value;
enum_type m_default_value;
diff --git a/include/lldb/Interpreter/OptionValueFileSpecList.h b/include/lldb/Interpreter/OptionValueFileSpecList.h
index 9529fbcf38bc..5c43b85bcea7 100644
--- a/include/lldb/Interpreter/OptionValueFileSpecList.h
+++ b/include/lldb/Interpreter/OptionValueFileSpecList.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueFileSpecList_h_
#define liblldb_OptionValueFileSpecList_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/FileSpecList.h"
#include "lldb/Interpreter/OptionValue.h"
diff --git a/include/lldb/Interpreter/OptionValueFormat.h b/include/lldb/Interpreter/OptionValueFormat.h
index ce7997024b09..6d46957d26f7 100644
--- a/include/lldb/Interpreter/OptionValueFormat.h
+++ b/include/lldb/Interpreter/OptionValueFormat.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueFormat_h_
#define liblldb_OptionValueFormat_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueFormatEntity.h b/include/lldb/Interpreter/OptionValueFormatEntity.h
index 880e434dc5c0..5d5a8ca02c97 100644
--- a/include/lldb/Interpreter/OptionValueFormatEntity.h
+++ b/include/lldb/Interpreter/OptionValueFormatEntity.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueFormatEntity_h_
#define liblldb_OptionValueFormatEntity_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/FormatEntity.h"
#include "lldb/Interpreter/OptionValue.h"
diff --git a/include/lldb/Interpreter/OptionValueLanguage.h b/include/lldb/Interpreter/OptionValueLanguage.h
index 8f81c5df0739..9d4956c6d789 100644
--- a/include/lldb/Interpreter/OptionValueLanguage.h
+++ b/include/lldb/Interpreter/OptionValueLanguage.h
@@ -11,10 +11,6 @@
#ifndef liblldb_OptionValueLanguage_h_
#define liblldb_OptionValueLanguage_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/lldb-enumerations.h"
diff --git a/include/lldb/Interpreter/OptionValuePathMappings.h b/include/lldb/Interpreter/OptionValuePathMappings.h
index 0e2e98d74b74..85f9926b21f8 100644
--- a/include/lldb/Interpreter/OptionValuePathMappings.h
+++ b/include/lldb/Interpreter/OptionValuePathMappings.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValuePathMappings_h_
#define liblldb_OptionValuePathMappings_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Target/PathMappingList.h"
diff --git a/include/lldb/Interpreter/OptionValueProperties.h b/include/lldb/Interpreter/OptionValueProperties.h
index 96bd93ab3d7b..941e48561f77 100644
--- a/include/lldb/Interpreter/OptionValueProperties.h
+++ b/include/lldb/Interpreter/OptionValueProperties.h
@@ -10,12 +10,8 @@
#ifndef liblldb_OptionValueProperties_h_
#define liblldb_OptionValueProperties_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Interpreter/OptionValue.h"
@@ -62,7 +58,7 @@ public:
void Apropos(llvm::StringRef keyword,
std::vector<const Property *> &matching_properties) const;
- void Initialize(const PropertyDefinition *setting_definitions);
+ void Initialize(const PropertyDefinitions &setting_definitions);
// bool
// GetQualifiedName (Stream &strm);
diff --git a/include/lldb/Interpreter/OptionValueRegex.h b/include/lldb/Interpreter/OptionValueRegex.h
index afe9318ae014..a77eb5323f23 100644
--- a/include/lldb/Interpreter/OptionValueRegex.h
+++ b/include/lldb/Interpreter/OptionValueRegex.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueRegex_h_
#define liblldb_OptionValueRegex_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Utility/RegularExpression.h"
diff --git a/include/lldb/Interpreter/OptionValueSInt64.h b/include/lldb/Interpreter/OptionValueSInt64.h
index a6893d23e692..f630cbb8e283 100644
--- a/include/lldb/Interpreter/OptionValueSInt64.h
+++ b/include/lldb/Interpreter/OptionValueSInt64.h
@@ -11,10 +11,6 @@
#ifndef liblldb_OptionValueSInt64_h_
#define liblldb_OptionValueSInt64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueString.h b/include/lldb/Interpreter/OptionValueString.h
index 4a9f2227680e..ab15595a08b4 100644
--- a/include/lldb/Interpreter/OptionValueString.h
+++ b/include/lldb/Interpreter/OptionValueString.h
@@ -10,12 +10,8 @@
#ifndef liblldb_OptionValueString_h_
#define liblldb_OptionValueString_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Flags.h"
#include "lldb/Interpreter/OptionValue.h"
diff --git a/include/lldb/Interpreter/OptionValueUInt64.h b/include/lldb/Interpreter/OptionValueUInt64.h
index 96404bed8e67..5cbcafdb6e58 100644
--- a/include/lldb/Interpreter/OptionValueUInt64.h
+++ b/include/lldb/Interpreter/OptionValueUInt64.h
@@ -11,10 +11,6 @@
#ifndef liblldb_OptionValueUInt64_h_
#define liblldb_OptionValueUInt64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValue.h"
namespace lldb_private {
diff --git a/include/lldb/Interpreter/OptionValueUUID.h b/include/lldb/Interpreter/OptionValueUUID.h
index 950efb518d5a..c2ee48962b42 100644
--- a/include/lldb/Interpreter/OptionValueUUID.h
+++ b/include/lldb/Interpreter/OptionValueUUID.h
@@ -10,10 +10,6 @@
#ifndef liblldb_OptionValueUUID_h_
#define liblldb_OptionValueUUID_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/UUID.h"
#include "lldb/Interpreter/OptionValue.h"
diff --git a/include/lldb/Interpreter/Options.h b/include/lldb/Interpreter/Options.h
index 316bf568fd92..aa9e564083a9 100644
--- a/include/lldb/Interpreter/Options.h
+++ b/include/lldb/Interpreter/Options.h
@@ -10,13 +10,9 @@
#ifndef liblldb_Options_h_
#define liblldb_Options_h_
-// C Includes
-// C++ Includes
#include <set>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Args.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/Status.h"
diff --git a/include/lldb/Interpreter/Property.h b/include/lldb/Interpreter/Property.h
index 9d0dc5fa0fd8..a7515e9903a4 100644
--- a/include/lldb/Interpreter/Property.h
+++ b/include/lldb/Interpreter/Property.h
@@ -28,10 +28,12 @@ struct PropertyDefinition {
bool global; // false == this setting is a global setting by default
uintptr_t default_uint_value;
const char *default_cstr_value;
- OptionEnumValueElement *enum_values;
+ OptionEnumValues enum_values;
const char *description;
};
+using PropertyDefinitions = llvm::ArrayRef<PropertyDefinition>;
+
class Property {
public:
Property(const PropertyDefinition &definition);
diff --git a/include/lldb/Interpreter/ScriptInterpreter.h b/include/lldb/Interpreter/ScriptInterpreter.h
index d2189edd04a6..640d9d34c617 100644
--- a/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/include/lldb/Interpreter/ScriptInterpreter.h
@@ -10,15 +10,12 @@
#ifndef liblldb_ScriptInterpreter_h_
#define liblldb_ScriptInterpreter_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/PluginInterface.h"
+#include "lldb/Core/SearchFilter.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
@@ -173,6 +170,17 @@ public:
}
virtual StructuredData::GenericSP
+ CreateFrameRecognizer(const char *class_name) {
+ return StructuredData::GenericSP();
+ }
+
+ virtual lldb::ValueObjectListSP GetRecognizedArguments(
+ const StructuredData::ObjectSP &implementor,
+ lldb::StackFrameSP frame_sp) {
+ return lldb::ValueObjectListSP();
+ }
+
+ virtual StructuredData::GenericSP
OSPlugin_CreatePluginObject(const char *class_name,
lldb::ProcessSP process_sp) {
return StructuredData::GenericSP();
@@ -234,6 +242,26 @@ public:
return lldb::eStateStepping;
}
+ virtual StructuredData::GenericSP
+ CreateScriptedBreakpointResolver(const char *class_name,
+ StructuredDataImpl *args_data,
+ lldb::BreakpointSP &bkpt_sp) {
+ return StructuredData::GenericSP();
+ }
+
+ virtual bool
+ ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
+ SymbolContext *sym_ctx)
+ {
+ return false;
+ }
+
+ virtual lldb::SearchDepth
+ ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
+ {
+ return lldb::eSearchDepthModule;
+ }
+
virtual StructuredData::ObjectSP
LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
return StructuredData::ObjectSP();
diff --git a/include/lldb/Symbol/Block.h b/include/lldb/Symbol/Block.h
index 1664362431f9..2428a1d3ffca 100644
--- a/include/lldb/Symbol/Block.h
+++ b/include/lldb/Symbol/Block.h
@@ -10,12 +10,8 @@
#ifndef liblldb_Block_h_
#define liblldb_Block_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Symbol/CompilerType.h"
@@ -327,6 +323,14 @@ public:
return m_inlineInfoSP.get();
}
+ //------------------------------------------------------------------
+ /// Get the symbol file which contains debug info for this block's
+ /// symbol context module.
+ ///
+ /// @return A pointer to the symbol file or nullptr.
+ //------------------------------------------------------------------
+ SymbolFile *GetSymbolFile();
+
CompilerDeclContext GetDeclContext();
//------------------------------------------------------------------
diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h
index 9364149d98e7..4cff9b256570 100644
--- a/include/lldb/Symbol/ClangASTContext.h
+++ b/include/lldb/Symbol/ClangASTContext.h
@@ -10,10 +10,8 @@
#ifndef liblldb_ClangASTContext_h_
#define liblldb_ClangASTContext_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <functional>
#include <initializer_list>
#include <map>
@@ -23,13 +21,12 @@
#include <utility>
#include <vector>
-// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExternalASTMerger.h"
#include "clang/AST/TemplateBase.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/SmallVector.h"
-// Project includes
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Symbol/CompilerType.h"
@@ -214,19 +211,24 @@ public:
static CompilerType GetTypeForDecl(clang::ObjCInterfaceDecl *objc_decl);
template <typename RecordDeclType>
- CompilerType GetTypeForIdentifier(const ConstString &type_name) {
+ CompilerType
+ GetTypeForIdentifier(const ConstString &type_name,
+ clang::DeclContext *decl_context = nullptr) {
CompilerType compiler_type;
if (type_name.GetLength()) {
clang::ASTContext *ast = getASTContext();
if (ast) {
+ if (!decl_context)
+ decl_context = ast->getTranslationUnitDecl();
+
clang::IdentifierInfo &myIdent =
ast->Idents.get(type_name.GetCString());
clang::DeclarationName myName =
ast->DeclarationNames.getIdentifier(&myIdent);
clang::DeclContext::lookup_result result =
- ast->getTranslationUnitDecl()->lookup(myName);
+ decl_context->lookup(myName);
if (!result.empty()) {
clang::NamedDecl *named_decl = result[0];
@@ -372,7 +374,17 @@ public:
const CompilerType &result_type,
const CompilerType *args,
unsigned num_args, bool is_variadic,
- unsigned type_quals);
+ unsigned type_quals,
+ clang::CallingConv cc);
+
+ static CompilerType CreateFunctionType(clang::ASTContext *ast,
+ const CompilerType &result_type,
+ const CompilerType *args,
+ unsigned num_args, bool is_variadic,
+ unsigned type_quals) {
+ return ClangASTContext::CreateFunctionType(
+ ast, result_type, args, num_args, is_variadic, type_quals, clang::CC_C);
+ }
CompilerType CreateFunctionType(const CompilerType &result_type,
const CompilerType *args, unsigned num_args,
@@ -381,7 +393,17 @@ public:
getASTContext(), result_type, args, num_args, is_variadic, type_quals);
}
- clang::ParmVarDecl *CreateParameterDeclaration(const char *name,
+ CompilerType CreateFunctionType(const CompilerType &result_type,
+ const CompilerType *args, unsigned num_args,
+ bool is_variadic, unsigned type_quals,
+ clang::CallingConv cc) {
+ return ClangASTContext::CreateFunctionType(getASTContext(), result_type,
+ args, num_args, is_variadic,
+ type_quals, cc);
+ }
+
+ clang::ParmVarDecl *CreateParameterDeclaration(clang::DeclContext *decl_ctx,
+ const char *name,
const CompilerType &param_type,
int storage);
@@ -720,7 +742,8 @@ public:
size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) override;
uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) override;
+ bool omit_empty_base_classes,
+ const ExecutionContext *exe_ctx) override;
CompilerType GetBuiltinTypeByName(const ConstString &name) override;
@@ -809,7 +832,7 @@ public:
// Modifying RecordType
//----------------------------------------------------------------------
static clang::FieldDecl *AddFieldToRecordType(const CompilerType &type,
- const char *name,
+ llvm::StringRef name,
const CompilerType &field_type,
lldb::AccessType access,
uint32_t bitfield_bit_size);
@@ -819,7 +842,7 @@ public:
static void SetIsPacked(const CompilerType &type);
static clang::VarDecl *AddVariableToRecordType(const CompilerType &type,
- const char *name,
+ llvm::StringRef name,
const CompilerType &var_type,
lldb::AccessType access);
@@ -831,19 +854,17 @@ public:
bool is_static, bool is_inline, bool is_explicit,
bool is_attr_used, bool is_artificial);
+ void AddMethodOverridesForCXXRecordType(lldb::opaque_compiler_type_t type);
+
// C++ Base Classes
- clang::CXXBaseSpecifier *
+ std::unique_ptr<clang::CXXBaseSpecifier>
CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
lldb::AccessType access, bool is_virtual,
bool base_of_class);
- static void DeleteBaseClassSpecifiers(clang::CXXBaseSpecifier **base_classes,
- unsigned num_base_classes);
-
- bool
- SetBaseClassesForClassType(lldb::opaque_compiler_type_t type,
- clang::CXXBaseSpecifier const *const *base_classes,
- unsigned num_base_classes);
+ bool TransferBaseClasses(
+ lldb::opaque_compiler_type_t type,
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases);
static bool SetObjCSuperClass(const CompilerType &type,
const CompilerType &superclass_compiler_type);
@@ -879,10 +900,12 @@ public:
//----------------------------------------------------------------------
// Modifying Enumeration types
//----------------------------------------------------------------------
- bool AddEnumerationValueToEnumerationType(
- lldb::opaque_compiler_type_t type,
- const CompilerType &enumerator_qual_type, const Declaration &decl,
- const char *name, int64_t enum_value, uint32_t enum_value_bit_size);
+ clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
+ const CompilerType &enum_type, const Declaration &decl, const char *name,
+ int64_t enum_value, uint32_t enum_value_bit_size);
+ clang::EnumConstantDecl *AddEnumerationValueToEnumerationType(
+ const CompilerType &enum_type, const Declaration &decl, const char *name,
+ const llvm::APSInt &value);
CompilerType GetEnumerationIntegerType(lldb::opaque_compiler_type_t type);
@@ -904,6 +927,8 @@ public:
//----------------------------------------------------------------------
// Dumping types
//----------------------------------------------------------------------
+ void Dump(Stream &s);
+
void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
Stream *s, lldb::Format format, const DataExtractor &data,
lldb::offset_t data_offset, size_t data_byte_size,
@@ -935,6 +960,8 @@ public:
static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
+ static clang::TypedefNameDecl *GetAsTypedefDecl(const CompilerType &type);
+
clang::CXXRecordDecl *GetAsCXXRecordDecl(lldb::opaque_compiler_type_t type);
static clang::ObjCInterfaceDecl *
diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h
index 52a164a1d2dd..465d7e24a1e7 100644
--- a/include/lldb/Symbol/ClangASTImporter.h
+++ b/include/lldb/Symbol/ClangASTImporter.h
@@ -10,14 +10,11 @@
#ifndef liblldb_ClangASTImporter_h_
#define liblldb_ClangASTImporter_h_
-// C Includes
-// C++ Includes
#include <map>
#include <memory>
#include <set>
#include <vector>
-// Other libraries and framework includes
#include "clang/AST/ASTImporter.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
@@ -25,7 +22,6 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/FileSystemOptions.h"
-// Project includes
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/lldb-types.h"
diff --git a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
index ef0010314e1d..c077665e51ee 100644
--- a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
+++ b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h
@@ -10,15 +10,11 @@
#ifndef liblldb_ClangExternalASTSourceCallbacks_h_
#define liblldb_ClangExternalASTSourceCallbacks_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/DenseMap.h"
-// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/CompilerType.h"
diff --git a/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/include/lldb/Symbol/ClangExternalASTSourceCommon.h
index 3e700ba2439c..894c91f157da 100644
--- a/include/lldb/Symbol/ClangExternalASTSourceCommon.h
+++ b/include/lldb/Symbol/ClangExternalASTSourceCommon.h
@@ -20,7 +20,6 @@
// file. So we have to define NDEBUG when including clang headers to avoid any
// mismatches. This is covered by rdar://problem/8691220
-// C Includes
#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF)
#define LLDB_DEFINED_NDEBUG_FOR_CLANG
#define NDEBUG
@@ -35,11 +34,8 @@
#include <assert.h>
#endif
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/ExternalASTSource.h"
-// Project includes
#include "lldb/Core/dwarf.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
diff --git a/include/lldb/Symbol/ClangUtil.h b/include/lldb/Symbol/ClangUtil.h
index cb380221152a..c8638f782548 100644
--- a/include/lldb/Symbol/ClangUtil.h
+++ b/include/lldb/Symbol/ClangUtil.h
@@ -16,6 +16,10 @@
#include "lldb/Symbol/CompilerType.h"
+namespace clang {
+class TagDecl;
+}
+
namespace lldb_private {
struct ClangUtil {
static bool IsClangType(const CompilerType &ct);
@@ -25,6 +29,8 @@ struct ClangUtil {
static clang::QualType GetCanonicalQualType(const CompilerType &ct);
static CompilerType RemoveFastQualifiers(const CompilerType &ct);
+
+ static clang::TagDecl *GetAsTagDecl(const CompilerType &type);
};
}
diff --git a/include/lldb/Symbol/CompileUnit.h b/include/lldb/Symbol/CompileUnit.h
index b816439cee13..a4d19cd3d8ae 100644
--- a/include/lldb/Symbol/CompileUnit.h
+++ b/include/lldb/Symbol/CompileUnit.h
@@ -18,6 +18,8 @@
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/DenseMap.h"
+
namespace lldb_private {
//----------------------------------------------------------------------
/// @class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h"
@@ -163,21 +165,19 @@ public:
void GetDescription(Stream *s, lldb::DescriptionLevel level) const;
//------------------------------------------------------------------
- /// Get a shared pointer to a function in this compile unit by index.
+ /// Apply a lambda to each function in this compile unit.
///
- /// Typically called when iterating though all functions in a compile unit
- /// after all functions have been parsed. This provides raw access to the
- /// function shared pointer list and will not cause the SymbolFile plug-in
- /// to parse any unparsed functions.
+ /// This provides raw access to the function shared pointer list and will not
+ /// cause the SymbolFile plug-in to parse any unparsed functions.
///
- /// @param[in] idx
- /// An index into the function list.
+ /// @note Prefer using FindFunctionByUID over this if possible.
///
- /// @return
- /// A shared pointer to a function that might contain a NULL
- /// Function class pointer.
+ /// @param[in] lambda
+ /// The lambda that should be applied to every function. The lambda can
+ /// return true if the iteration should be aborted earlier.
//------------------------------------------------------------------
- lldb::FunctionSP GetFunctionAtIndex(size_t idx);
+ void ForeachFunction(
+ llvm::function_ref<bool(const lldb::FunctionSP &)> lambda) const;
//------------------------------------------------------------------
/// Dump the compile unit contents to the stream \a s.
@@ -391,7 +391,7 @@ public:
//------------------------------------------------------------------
uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
bool check_inlines, bool exact,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list);
//------------------------------------------------------------------
@@ -409,15 +409,20 @@ public:
//------------------------------------------------------------------
bool GetIsOptimized();
+ //------------------------------------------------------------------
+ /// Returns the number of functions in this compile unit
+ //------------------------------------------------------------------
+ size_t GetNumFunctions() const { return m_functions_by_uid.size(); }
+
protected:
void *m_user_data; ///< User data for the SymbolFile parser to store
///information into.
lldb::LanguageType
m_language; ///< The programming language enumeration value.
Flags m_flags; ///< Compile unit flags that help with partial parsing.
- std::vector<lldb::FunctionSP> m_functions; ///< The sparsely populated list of
- ///shared pointers to functions
- ///< that gets populated as functions get partially parsed.
+
+ /// Maps UIDs to functions.
+ llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions_by_uid;
std::vector<ConstString> m_imported_modules; ///< All modules, including the
///current module, imported by
///this
diff --git a/include/lldb/Symbol/CompilerType.h b/include/lldb/Symbol/CompilerType.h
index 1170832a7396..353313d8e2a3 100644
--- a/include/lldb/Symbol/CompilerType.h
+++ b/include/lldb/Symbol/CompilerType.h
@@ -10,14 +10,10 @@
#ifndef liblldb_CompilerType_h_
#define liblldb_CompilerType_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/APSInt.h"
@@ -291,9 +287,10 @@ public:
struct IntegralTemplateArgument;
- uint64_t GetByteSize(ExecutionContextScope *exe_scope) const;
-
- uint64_t GetBitSize(ExecutionContextScope *exe_scope) const;
+ /// Return the size of the type in bytes.
+ llvm::Optional<uint64_t> GetByteSize(ExecutionContextScope *exe_scope) const;
+ /// Return the size of the type in bits.
+ llvm::Optional<uint64_t> GetBitSize(ExecutionContextScope *exe_scope) const;
lldb::Encoding GetEncoding(uint64_t &count) const;
@@ -301,7 +298,8 @@ public:
size_t GetTypeBitAlign() const;
- uint32_t GetNumChildren(bool omit_empty_base_classes) const;
+ uint32_t GetNumChildren(bool omit_empty_base_classes,
+ const ExecutionContext *exe_ctx) const;
lldb::BasicType GetBasicTypeEnumeration() const;
diff --git a/include/lldb/Symbol/DebugMacros.h b/include/lldb/Symbol/DebugMacros.h
index 640da027cd59..86700994fbcc 100644
--- a/include/lldb/Symbol/DebugMacros.h
+++ b/include/lldb/Symbol/DebugMacros.h
@@ -10,13 +10,9 @@
#ifndef liblldb_DebugMacros_h_
#define liblldb_DebugMacros_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Symbol/Function.h b/include/lldb/Symbol/Function.h
index 28c6b4857b10..447abd2e6f78 100644
--- a/include/lldb/Symbol/Function.h
+++ b/include/lldb/Symbol/Function.h
@@ -16,6 +16,7 @@
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Declaration.h"
#include "lldb/Utility/UserID.h"
+#include "llvm/ADT/ArrayRef.h"
namespace lldb_private {
@@ -290,6 +291,64 @@ private:
Declaration m_call_decl;
};
+class Function;
+
+//----------------------------------------------------------------------
+/// @class CallEdge Function.h "lldb/Symbol/Function.h"
+///
+/// Represent a call made within a Function. This can be used to find a path
+/// in the call graph between two functions.
+//----------------------------------------------------------------------
+class CallEdge {
+public:
+ /// Construct a call edge using a symbol name to identify the calling
+ /// function, and a return PC within the calling function to identify a
+ /// specific call site.
+ ///
+ /// TODO: A symbol name may not be globally unique. To disambiguate ODR
+ /// conflicts, it's necessary to determine the \c Target a call edge is
+ /// associated with before resolving it.
+ CallEdge(const char *symbol_name, lldb::addr_t return_pc);
+
+ CallEdge(CallEdge &&) = default;
+ CallEdge &operator=(CallEdge &&) = default;
+
+ /// Get the callee's definition.
+ ///
+ /// Note that this might lazily invoke the DWARF parser.
+ Function *GetCallee(ModuleList &images);
+
+ /// Get the load PC address of the instruction which executes after the call
+ /// returns. Returns LLDB_INVALID_ADDRESS iff this is a tail call. \p caller
+ /// is the Function containing this call, and \p target is the Target which
+ /// made the call.
+ lldb::addr_t GetReturnPCAddress(Function &caller, Target &target) const;
+
+ /// Like \ref GetReturnPCAddress, but returns an unslid function-local PC
+ /// offset.
+ lldb::addr_t GetUnresolvedReturnPCAddress() const { return return_pc; }
+
+private:
+ void ParseSymbolFileAndResolve(ModuleList &images);
+
+ /// Either the callee's mangled name or its definition, discriminated by
+ /// \ref resolved.
+ union {
+ const char *symbol_name;
+ Function *def;
+ } lazy_callee;
+
+ /// An invalid address if this is a tail call. Otherwise, the function-local
+ /// PC offset. Adding this PC offset to the function's base load address
+ /// gives the return PC for the call.
+ lldb::addr_t return_pc;
+
+ /// Whether or not an attempt was made to find the callee's definition.
+ bool resolved;
+
+ DISALLOW_COPY_AND_ASSIGN(CallEdge);
+};
+
//----------------------------------------------------------------------
/// @class Function Function.h "lldb/Symbol/Function.h"
/// A class that describes a function.
@@ -349,40 +408,6 @@ public:
Type *func_type, const AddressRange &range);
//------------------------------------------------------------------
- /// Construct with a compile unit, function UID, function type UID, optional
- /// mangled name, function type, and a section offset based address range.
- ///
- /// @param[in] comp_unit
- /// The compile unit to which this function belongs.
- ///
- /// @param[in] func_uid
- /// The UID for this function. This value is provided by the
- /// SymbolFile plug-in and can be any value that allows
- /// the plug-in to quickly find and parse more detailed
- /// information when and if more information is needed.
- ///
- /// @param[in] func_type_uid
- /// The type UID for the function Type to allow for lazy type
- /// parsing from the debug information.
- ///
- /// @param[in] mangled
- /// The optional mangled name for this function. If empty, there
- /// is no mangled information.
- ///
- /// @param[in] func_type
- /// The optional function type. If NULL, the function type will
- /// be parsed on demand when accessed using the
- /// Function::GetType() function by asking the SymbolFile
- /// plug-in to get the type for \a func_type_uid.
- ///
- /// @param[in] range
- /// The section offset based address for this function.
- //------------------------------------------------------------------
- Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
- lldb::user_id_t func_type_uid, const char *mangled, Type *func_type,
- const AddressRange &range);
-
- //------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
~Function() override;
@@ -431,6 +456,18 @@ public:
void GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no);
//------------------------------------------------------------------
+ /// Get the outgoing call edges from this function, sorted by their return
+ /// PC addresses (in increasing order).
+ //------------------------------------------------------------------
+ llvm::MutableArrayRef<CallEdge> GetCallEdges();
+
+ //------------------------------------------------------------------
+ /// Get the outgoing tail-calling edges from this function. If none exist,
+ /// return None.
+ //------------------------------------------------------------------
+ llvm::MutableArrayRef<CallEdge> GetTailCallingEdges();
+
+ //------------------------------------------------------------------
/// Get accessor for the block list.
///
/// @return
@@ -621,6 +658,10 @@ protected:
Flags m_flags;
uint32_t
m_prologue_byte_size; ///< Compute the prologue size once and cache it
+
+ bool m_call_edges_resolved = false; ///< Whether call site info has been
+ /// parsed.
+ std::vector<CallEdge> m_call_edges; ///< Outgoing call edges.
private:
DISALLOW_COPY_AND_ASSIGN(Function);
};
diff --git a/include/lldb/Symbol/GoASTContext.h b/include/lldb/Symbol/GoASTContext.h
deleted file mode 100644
index 29c8cdceacff..000000000000
--- a/include/lldb/Symbol/GoASTContext.h
+++ /dev/null
@@ -1,421 +0,0 @@
-//===-- GoASTContext.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_GoASTContext_h_
-#define liblldb_GoASTContext_h_
-
-// C Includes
-// C++ Includes
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/TypeSystem.h"
-#include "lldb/Utility/ConstString.h"
-
-namespace lldb_private {
-
-class Declaration;
-class GoType;
-
-class GoASTContext : public TypeSystem {
-public:
- GoASTContext();
- ~GoASTContext() override;
-
- //------------------------------------------------------------------
- // PluginInterface functions
- //------------------------------------------------------------------
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- static ConstString GetPluginNameStatic();
-
- static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
- Module *module, Target *target);
-
- static void EnumerateSupportedLanguages(
- std::set<lldb::LanguageType> &languages_for_types,
- std::set<lldb::LanguageType> &languages_for_expressions);
-
- static void Initialize();
-
- static void Terminate();
-
- DWARFASTParser *GetDWARFParser() override;
-
- void SetAddressByteSize(int byte_size) { m_pointer_byte_size = byte_size; }
-
- //------------------------------------------------------------------
- // llvm casting support
- //------------------------------------------------------------------
- static bool classof(const TypeSystem *ts) {
- return ts->getKind() == TypeSystem::eKindGo;
- }
-
- //----------------------------------------------------------------------
- // CompilerDecl functions
- //----------------------------------------------------------------------
- ConstString DeclGetName(void *opaque_decl) override { return ConstString(); }
-
- //----------------------------------------------------------------------
- // CompilerDeclContext functions
- //----------------------------------------------------------------------
-
- bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override {
- return false;
- }
-
- ConstString DeclContextGetName(void *opaque_decl_ctx) override {
- return ConstString();
- }
-
- ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override {
- return ConstString();
- }
-
- bool
- DeclContextIsClassMethod(void *opaque_decl_ctx,
- lldb::LanguageType *language_ptr,
- bool *is_instance_method_ptr,
- ConstString *language_object_name_ptr) override {
- return false;
- }
-
- //----------------------------------------------------------------------
- // Creating Types
- //----------------------------------------------------------------------
-
- CompilerType CreateArrayType(const ConstString &name,
- const CompilerType &element_type,
- uint64_t length);
-
- CompilerType CreateBaseType(int go_kind,
- const ConstString &type_name_const_str,
- uint64_t byte_size);
-
- // For interface, map, chan.
- CompilerType CreateTypedefType(int kind, const ConstString &name,
- CompilerType impl);
-
- CompilerType CreateVoidType(const ConstString &name);
- CompilerType CreateFunctionType(const lldb_private::ConstString &name,
- CompilerType *params, size_t params_count,
- bool is_variadic);
-
- CompilerType CreateStructType(int kind, const ConstString &name,
- uint32_t byte_size);
-
- void CompleteStructType(const CompilerType &type);
-
- void AddFieldToStruct(const CompilerType &struct_type,
- const ConstString &name, const CompilerType &field_type,
- uint32_t byte_offset);
-
- //----------------------------------------------------------------------
- // Tests
- //----------------------------------------------------------------------
-
- static bool IsGoString(const CompilerType &type);
- static bool IsGoSlice(const CompilerType &type);
- static bool IsGoInterface(const CompilerType &type);
- static bool IsDirectIface(uint8_t kind);
- static bool IsPointerKind(uint8_t kind);
-
- bool IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size,
- bool *is_incomplete) override;
-
- bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
-
- bool IsCharType(lldb::opaque_compiler_type_t type) override;
-
- bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
-
- bool IsDefined(lldb::opaque_compiler_type_t type) override;
-
- bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count,
- bool &is_complex) override;
-
- bool IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr = nullptr) override;
-
- size_t
- GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) override;
-
- bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
-
- bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) override;
-
- bool IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) override;
-
- bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
- CompilerType *target_type, // Can pass nullptr
- bool check_cplusplus, bool check_objc) override;
-
- bool IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr) override;
-
- bool IsScalarType(lldb::opaque_compiler_type_t type) override;
-
- bool IsVoidType(lldb::opaque_compiler_type_t type) override;
-
- bool SupportsLanguage(lldb::LanguageType language) override;
-
- //----------------------------------------------------------------------
- // Type Completion
- //----------------------------------------------------------------------
-
- bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
-
- //----------------------------------------------------------------------
- // AST related queries
- //----------------------------------------------------------------------
-
- uint32_t GetPointerByteSize() override;
-
- //----------------------------------------------------------------------
- // Accessors
- //----------------------------------------------------------------------
-
- ConstString GetTypeName(lldb::opaque_compiler_type_t type) override;
-
- uint32_t GetTypeInfo(
- lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_compiler_type = nullptr) override;
-
- lldb::LanguageType
- GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
-
- lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
-
- //----------------------------------------------------------------------
- // Creating related types
- //----------------------------------------------------------------------
-
- CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride = nullptr) override;
-
- CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
-
- // Returns -1 if this isn't a function of if the function doesn't have a
- // prototype Returns a value >= 0 if there is a prototype.
- int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) override;
-
- CompilerType
- GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
-
- size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
-
- TypeMemberFunctionImpl
- GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) override;
-
- CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
-
- //----------------------------------------------------------------------
- // Exploring the type
- //----------------------------------------------------------------------
-
- uint64_t GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) override;
-
- lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) override;
-
- lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
-
- uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) override;
-
- lldb::BasicType
- GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
- size_t bit_size) override;
-
- uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
- std::string &name, uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) override;
-
- uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override {
- return 0;
- }
-
- uint32_t
- GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override {
- return 0;
- }
-
- CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx,
- uint32_t *bit_offset_ptr) override {
- return CompilerType();
- }
-
- CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx,
- uint32_t *bit_offset_ptr) override {
- return CompilerType();
- }
-
- CompilerType GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
- bool transparent_pointers, bool omit_empty_base_classes,
- bool ignore_array_bounds, std::string &child_name,
- uint32_t &child_byte_size, int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class, bool &child_is_deref_of_parent,
- ValueObject *valobj, uint64_t &language_flags) override;
-
- // Lookup a child given a name. This function will match base class names and
- // member member names in "clang_type" only, not descendants.
- uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) override;
-
- // Lookup a child member given a name. This function will match member names
- // only and will descend into "clang_type" children in search for the first
- // member in this class, or any base class that matches "name".
- // TODO: Return all matches for a given name by returning a
- // vector<vector<uint32_t>>
- // so we catch all names that match a given child name, not just the first.
- size_t
- GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
- const char *name, bool omit_empty_base_classes,
- std::vector<uint32_t> &child_indexes) override;
-
- size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override {
- return 0;
- }
-
- //----------------------------------------------------------------------
- // Dumping types
- //----------------------------------------------------------------------
- void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
- Stream *s, lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- bool show_types, bool show_summary, bool verbose,
- uint32_t depth) override;
-
- bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
- lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope) override;
-
- void DumpTypeDescription(
- lldb::opaque_compiler_type_t type) override; // Dump to stdout
-
- void DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) override;
-
- //----------------------------------------------------------------------
- // TODO: These methods appear unused. Should they be removed?
- //----------------------------------------------------------------------
-
- bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
-
- void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
- Stream *s, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size) override;
-
- // Converts "s" to a floating point value and place resulting floating point
- // bytes in the "dst" buffer.
- size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
- const char *s, uint8_t *dst,
- size_t dst_size) override;
-
- //----------------------------------------------------------------------
- // TODO: Determine if these methods should move to ClangASTContext.
- //----------------------------------------------------------------------
-
- bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr) override;
-
- unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
-
- bool IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) override;
-
- size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
-
- bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
-
- bool IsConst(lldb::opaque_compiler_type_t type) override;
-
- uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) override;
-
- bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
-
- bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
-
- // If the current object represents a typedef type, get the underlying type
- CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
-
- bool IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) override;
-
- CompilerType
- GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
-
- bool IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr,
- bool *is_rvalue = nullptr) override;
-
-private:
- typedef std::map<ConstString, std::unique_ptr<GoType>> TypeMap;
- int m_pointer_byte_size;
- int m_int_byte_size;
- std::unique_ptr<TypeMap> m_types;
- std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
-
- GoASTContext(const GoASTContext &) = delete;
- const GoASTContext &operator=(const GoASTContext &) = delete;
-};
-
-class GoASTContextForExpr : public GoASTContext {
-public:
- GoASTContextForExpr(lldb::TargetSP target) : m_target_wp(target) {}
- UserExpression *
- GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
- lldb::LanguageType language,
- Expression::ResultType desired_type,
- const EvaluateExpressionOptions &options) override;
-
-private:
- lldb::TargetWP m_target_wp;
-};
-}
-#endif // liblldb_GoASTContext_h_
diff --git a/include/lldb/Symbol/JavaASTContext.h b/include/lldb/Symbol/JavaASTContext.h
deleted file mode 100644
index 41a881dcf4eb..000000000000
--- a/include/lldb/Symbol/JavaASTContext.h
+++ /dev/null
@@ -1,350 +0,0 @@
-//===-- JavaASTContext.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_JavaASTContext_h_
-#define liblldb_JavaASTContext_h_
-
-// C Includes
-// C++ Includes
-#include <map>
-#include <memory>
-#include <set>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Symbol/TypeSystem.h"
-#include "lldb/Utility/ConstString.h"
-
-namespace lldb_private {
-
-class JavaASTContext : public TypeSystem {
-public:
- class JavaType;
- typedef std::map<ConstString, std::unique_ptr<JavaType>> JavaTypeMap;
-
- JavaASTContext(const ArchSpec &arch);
- ~JavaASTContext() override;
-
- //------------------------------------------------------------------
- // PluginInterface functions
- //------------------------------------------------------------------
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- static ConstString GetPluginNameStatic();
-
- static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
- Module *module, Target *target);
-
- static void EnumerateSupportedLanguages(
- std::set<lldb::LanguageType> &languages_for_types,
- std::set<lldb::LanguageType> &languages_for_expressions);
-
- static void Initialize();
-
- static void Terminate();
-
- DWARFASTParser *GetDWARFParser() override;
-
- uint32_t GetPointerByteSize() override;
-
- //----------------------------------------------------------------------
- // CompilerDecl functions
- //----------------------------------------------------------------------
- ConstString DeclGetName(void *opaque_decl) override;
-
- //----------------------------------------------------------------------
- // CompilerDeclContext functions
- //----------------------------------------------------------------------
-
- std::vector<CompilerDecl>
- DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
- const bool ignore_imported_decls) override;
-
- bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override;
-
- ConstString DeclContextGetName(void *opaque_decl_ctx) override;
-
- bool DeclContextIsClassMethod(void *opaque_decl_ctx,
- lldb::LanguageType *language_ptr,
- bool *is_instance_method_ptr,
- ConstString *language_object_name_ptr) override;
-
- //----------------------------------------------------------------------
- // Tests
- //----------------------------------------------------------------------
-
- bool IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size,
- bool *is_incomplete) override;
-
- bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
-
- bool IsCharType(lldb::opaque_compiler_type_t type) override;
-
- bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count,
- bool &is_complex) override;
-
- bool IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr = nullptr) override;
-
- size_t
- GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) override;
-
- bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
-
- bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) override;
-
- bool IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) override;
-
- bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
- CompilerType *target_type, bool check_cplusplus,
- bool check_objc) override;
-
- bool IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr) override;
-
- bool IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr,
- bool *is_rvalue = nullptr) override;
-
- bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr) override;
-
- bool IsScalarType(lldb::opaque_compiler_type_t type) override;
-
- bool IsVoidType(lldb::opaque_compiler_type_t type) override;
-
- bool IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) override;
-
- bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
-
- bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
-
- bool IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) override;
-
- bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
-
- bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
-
- bool IsConst(lldb::opaque_compiler_type_t type) override;
-
- bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
-
- bool IsDefined(lldb::opaque_compiler_type_t type) override;
-
- uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) override;
-
- bool SupportsLanguage(lldb::LanguageType language) override;
-
- bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
-
- ConstString GetTypeName(lldb::opaque_compiler_type_t type) override;
-
- uint32_t GetTypeInfo(
- lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_compiler_type = nullptr) override;
-
- lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
-
- lldb::LanguageType
- GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride = nullptr) override;
-
- CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType
- GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
-
- CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
- size_t bit_size) override;
-
- size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) override;
-
- lldb::BasicType
- GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
-
- uint64_t GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) override;
-
- lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) override;
-
- lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
-
- unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
-
- size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override;
-
- int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) override;
-
- CompilerType
- GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
-
- size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
-
- TypeMemberFunctionImpl
- GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) override;
-
- uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
- std::string &name, uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) override;
-
- uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) override;
-
- uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override;
-
- uint32_t GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx,
- uint32_t *bit_offset_ptr) override;
-
- CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx,
- uint32_t *bit_offset_ptr) override;
-
- size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
- const char *s, uint8_t *dst,
- size_t dst_size) override;
-
- void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
- Stream *s, lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- bool show_types, bool show_summary, bool verbose,
- uint32_t depth) override;
-
- bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
- lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope) override;
-
- void DumpTypeDescription(lldb::opaque_compiler_type_t type) override;
-
- void DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) override;
-
- void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
- Stream *s, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size) override;
-
- CompilerType GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
- bool transparent_pointers, bool omit_empty_base_classes,
- bool ignore_array_bounds, std::string &child_name,
- uint32_t &child_byte_size, int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class, bool &child_is_deref_of_parent,
- ValueObject *valobj, uint64_t &language_flags) override;
-
- uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) override;
-
- size_t
- GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
- const char *name, bool omit_empty_base_classes,
- std::vector<uint32_t> &child_indexes) override;
-
- CompilerType
- GetLValueReferenceType(lldb::opaque_compiler_type_t type) override;
-
- ConstString DeclContextGetScopeQualifiedName(
- lldb::opaque_compiler_type_t opaque_decl_ctx) override;
-
- CompilerType CreateBaseType(const ConstString &name);
-
- CompilerType CreateObjectType(const ConstString &name,
- const ConstString &linkage_name,
- uint32_t byte_size);
-
- CompilerType CreateArrayType(const ConstString &linkage_name,
- const CompilerType &element_type,
- const DWARFExpression &length_expression,
- const lldb::addr_t data_offset);
-
- CompilerType CreateReferenceType(const CompilerType &pointee_type);
-
- void CompleteObjectType(const CompilerType &object_type);
-
- void AddBaseClassToObject(const CompilerType &object_type,
- const CompilerType &member_type,
- uint32_t member_offset);
-
- void AddMemberToObject(const CompilerType &object_type,
- const ConstString &name,
- const CompilerType &member_type,
- uint32_t member_offset);
-
- void SetDynamicTypeId(const CompilerType &type,
- const DWARFExpression &type_id);
-
- static uint64_t CalculateDynamicTypeId(ExecutionContext *exe_ctx,
- const CompilerType &type,
- ValueObject &in_value);
-
- static ConstString GetLinkageName(const CompilerType &type);
-
- static uint32_t CalculateArraySize(const CompilerType &type,
- ValueObject &in_value);
-
- static uint64_t CalculateArrayElementOffset(const CompilerType &type,
- size_t index);
-
- //------------------------------------------------------------------
- // llvm casting support
- //------------------------------------------------------------------
- static bool classof(const TypeSystem *ts) {
- return ts->getKind() == TypeSystem::eKindJava;
- }
-
-private:
- uint32_t m_pointer_byte_size;
- std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
- JavaTypeMap m_array_type_map;
- JavaTypeMap m_base_type_map;
- JavaTypeMap m_reference_type_map;
- JavaTypeMap m_object_type_map;
-
- JavaASTContext(const JavaASTContext &) = delete;
- const JavaASTContext &operator=(const JavaASTContext &) = delete;
-};
-}
-#endif // liblldb_JavaASTContext_h_
diff --git a/include/lldb/Symbol/LineTable.h b/include/lldb/Symbol/LineTable.h
index fe8be0c55764..684972d50789 100644
--- a/include/lldb/Symbol/LineTable.h
+++ b/include/lldb/Symbol/LineTable.h
@@ -10,12 +10,8 @@
#ifndef liblldb_LineTable_h_
#define liblldb_LineTable_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ModuleChild.h"
#include "lldb/Core/RangeMap.h"
#include "lldb/Core/Section.h"
@@ -242,21 +238,22 @@ public:
protected:
struct Entry {
Entry()
- : file_addr(LLDB_INVALID_ADDRESS), line(0), column(0), file_idx(0),
+ : file_addr(LLDB_INVALID_ADDRESS), line(0),
is_start_of_statement(false), is_start_of_basic_block(false),
is_prologue_end(false), is_epilogue_begin(false),
- is_terminal_entry(false) {}
+ is_terminal_entry(false), column(0), file_idx(0) {}
Entry(lldb::addr_t _file_addr, uint32_t _line, uint16_t _column,
uint16_t _file_idx, bool _is_start_of_statement,
bool _is_start_of_basic_block, bool _is_prologue_end,
bool _is_epilogue_begin, bool _is_terminal_entry)
- : file_addr(_file_addr), line(_line), column(_column),
- file_idx(_file_idx), is_start_of_statement(_is_start_of_statement),
+ : file_addr(_file_addr), line(_line),
+ is_start_of_statement(_is_start_of_statement),
is_start_of_basic_block(_is_start_of_basic_block),
is_prologue_end(_is_prologue_end),
is_epilogue_begin(_is_epilogue_begin),
- is_terminal_entry(_is_terminal_entry) {}
+ is_terminal_entry(_is_terminal_entry), column(_column),
+ file_idx(_file_idx) {}
int bsearch_compare(const void *key, const void *arrmem);
@@ -310,26 +307,30 @@ protected:
//------------------------------------------------------------------
// Member variables.
//------------------------------------------------------------------
- lldb::addr_t file_addr; ///< The file address for this line entry
- uint32_t line; ///< The source line number, or zero if there is no line
- ///number information.
- uint16_t column; ///< The column number of the source line, or zero if there
- ///is no column information.
- uint16_t file_idx : 11, ///< The file index into CompileUnit's file table,
- ///or zero if there is no file information.
- is_start_of_statement : 1, ///< Indicates this entry is the beginning of
- ///a statement.
- is_start_of_basic_block : 1, ///< Indicates this entry is the beginning
- ///of a basic block.
- is_prologue_end : 1, ///< Indicates this entry is one (of possibly many)
- ///where execution should be suspended for an entry
- ///breakpoint of a function.
- is_epilogue_begin : 1, ///< Indicates this entry is one (of possibly
- ///many) where execution should be suspended for
- ///an exit breakpoint of a function.
- is_terminal_entry : 1; ///< Indicates this entry is that of the first
- ///byte after the end of a sequence of target
- ///machine instructions.
+ /// The file address for this line entry.
+ lldb::addr_t file_addr;
+ /// The source line number, or zero if there is no line number
+ /// information.
+ uint32_t line : 27;
+ /// Indicates this entry is the beginning of a statement.
+ uint32_t is_start_of_statement : 1;
+ /// Indicates this entry is the beginning of a basic block.
+ uint32_t is_start_of_basic_block : 1;
+ /// Indicates this entry is one (of possibly many) where execution
+ /// should be suspended for an entry breakpoint of a function.
+ uint32_t is_prologue_end : 1;
+ /// Indicates this entry is one (of possibly many) where execution
+ /// should be suspended for an exit breakpoint of a function.
+ uint32_t is_epilogue_begin : 1;
+ /// Indicates this entry is that of the first byte after the end
+ /// of a sequence of target machine instructions.
+ uint32_t is_terminal_entry : 1;
+ /// The column number of the source line, or zero if there is no
+ /// column information.
+ uint16_t column;
+ /// The file index into CompileUnit's file table, or zero if there
+ /// is no file information.
+ uint16_t file_idx;
};
struct EntrySearchInfo {
diff --git a/include/lldb/Symbol/OCamlASTContext.h b/include/lldb/Symbol/OCamlASTContext.h
deleted file mode 100644
index 7144886e1c75..000000000000
--- a/include/lldb/Symbol/OCamlASTContext.h
+++ /dev/null
@@ -1,318 +0,0 @@
-//===-- OCamlASTContext.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_OCamlASTContext_h_
-#define liblldb_OCamlASTContext_h_
-
-// C Includes
-// C++ Includes
-#include <map>
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/TypeSystem.h"
-#include "lldb/Utility/ConstString.h"
-
-namespace lldb_private {
-
-class OCamlASTContext : public TypeSystem {
-public:
- class OCamlType;
- typedef std::map<ConstString, std::unique_ptr<OCamlType>> OCamlTypeMap;
-
- OCamlASTContext();
- ~OCamlASTContext() override;
-
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- static ConstString GetPluginNameStatic();
-
- static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
- Module *module, Target *target);
-
- static void EnumerateSupportedLanguages(
- std::set<lldb::LanguageType> &languages_for_types,
- std::set<lldb::LanguageType> &languages_for_expressions);
-
- static void Initialize();
-
- static void Terminate();
-
- DWARFASTParser *GetDWARFParser() override;
-
- void SetAddressByteSize(int byte_size) { m_pointer_byte_size = byte_size; }
-
- static bool classof(const TypeSystem *ts) {
- return ts->getKind() == TypeSystem::eKindOCaml;
- }
-
- ConstString DeclGetName(void *opaque_decl) override { return ConstString(); }
-
- bool DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) override {
- return false;
- }
-
- ConstString DeclContextGetName(void *opaque_decl_ctx) override {
- return ConstString();
- }
-
- ConstString DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) override {
- return ConstString();
- }
-
- bool
- DeclContextIsClassMethod(void *opaque_decl_ctx,
- lldb::LanguageType *language_ptr,
- bool *is_instance_method_ptr,
- ConstString *language_object_name_ptr) override {
- return false;
- }
-
- bool SupportsLanguage(lldb::LanguageType language) override;
- uint32_t GetPointerByteSize() override;
-
- bool IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size,
- bool *is_incomplete) override;
-
- bool IsAggregateType(lldb::opaque_compiler_type_t type) override;
-
- bool IsCharType(lldb::opaque_compiler_type_t type) override;
-
- bool IsCompleteType(lldb::opaque_compiler_type_t type) override;
-
- bool IsDefined(lldb::opaque_compiler_type_t type) override;
-
- bool IsFloatingPointType(lldb::opaque_compiler_type_t type, uint32_t &count,
- bool &is_complex) override;
-
- bool IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr = nullptr) override;
-
- size_t
- GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) override;
-
- bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) override;
-
- bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) override;
-
- bool IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) override;
-
- bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
- CompilerType *target_type, bool check_cplusplus,
- bool check_objc) override;
-
- bool IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr) override;
-
- bool IsScalarType(lldb::opaque_compiler_type_t type) override;
-
- bool IsVoidType(lldb::opaque_compiler_type_t type) override;
-
- bool GetCompleteType(lldb::opaque_compiler_type_t type) override;
-
- ConstString GetTypeName(lldb::opaque_compiler_type_t type) override;
-
- uint32_t GetTypeInfo(
- lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_compiler_type = nullptr) override;
-
- lldb::LanguageType
- GetMinimumLanguage(lldb::opaque_compiler_type_t type) override;
-
- lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride = nullptr) override;
-
- CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) override;
-
- int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) override;
-
- CompilerType
- GetFunctionReturnType(lldb::opaque_compiler_type_t type) override;
-
- size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) override;
-
- TypeMemberFunctionImpl
- GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) override;
-
- CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetPointerType(lldb::opaque_compiler_type_t type) override;
-
- uint64_t GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) override;
-
- lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) override;
-
- lldb::Format GetFormat(lldb::opaque_compiler_type_t type) override;
-
- uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) override;
-
- lldb::BasicType
- GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
- size_t bit_size) override;
-
- uint32_t GetNumFields(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
- std::string &name, uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) override;
-
- uint32_t GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) override {
- return 0;
- }
-
- uint32_t
- GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) override {
- return 0;
- }
-
- CompilerType GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx,
- uint32_t *bit_offset_ptr) override {
- return CompilerType();
- }
-
- CompilerType GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx,
- uint32_t *bit_offset_ptr) override {
- return CompilerType();
- }
-
- CompilerType GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
- bool transparent_pointers, bool omit_empty_base_classes,
- bool ignore_array_bounds, std::string &child_name,
- uint32_t &child_byte_size, int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class, bool &child_is_deref_of_parent,
- ValueObject *valobj, uint64_t &language_flags) override;
-
- uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) override;
-
- size_t
- GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
- const char *name, bool omit_empty_base_classes,
- std::vector<uint32_t> &child_indexes) override;
-
- size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) override {
- return 0;
- }
-
- void DumpValue(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
- Stream *s, lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- bool show_types, bool show_summary, bool verbose,
- uint32_t depth) override;
-
- bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
- lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope) override;
-
- void DumpTypeDescription(lldb::opaque_compiler_type_t type) override;
-
- void DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) override;
-
- bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) override;
-
- void DumpSummary(lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx,
- Stream *s, const DataExtractor &data,
- lldb::offset_t data_offset, size_t data_byte_size) override;
-
- size_t ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
- const char *s, uint8_t *dst,
- size_t dst_size) override;
-
- bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr) override;
-
- unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) override;
-
- bool IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) override;
-
- size_t GetTypeBitAlign(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) override;
-
- bool IsBeingDefined(lldb::opaque_compiler_type_t type) override;
-
- bool IsConst(lldb::opaque_compiler_type_t type) override;
-
- uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) override;
-
- bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) override;
-
- bool IsTypedefType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) override;
-
- bool IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) override;
-
- CompilerType
- GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) override;
-
- CompilerType GetNonReferenceType(lldb::opaque_compiler_type_t type) override;
-
- bool IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type = nullptr,
- bool *is_rvalue = nullptr) override;
-
- CompilerType CreateBaseType(const ConstString &name, uint64_t);
-
-private:
- int m_pointer_byte_size;
- std::unique_ptr<DWARFASTParser> m_dwarf_ast_parser_ap;
- OCamlTypeMap m_base_type_map;
-
- OCamlASTContext(const OCamlASTContext &) = delete;
- const OCamlASTContext &operator=(const OCamlASTContext &) = delete;
-};
-
-class OCamlASTContextForExpr : public OCamlASTContext {
-public:
- OCamlASTContextForExpr(lldb::TargetSP target) : m_target_wp(target) {}
-
-private:
- lldb::TargetWP m_target_wp;
-};
-}
-#endif // liblldb_OCamlASTContext_h_
diff --git a/include/lldb/Symbol/ObjectContainer.h b/include/lldb/Symbol/ObjectContainer.h
index 2138d22808c3..1e14856ea6ea 100644
--- a/include/lldb/Symbol/ObjectContainer.h
+++ b/include/lldb/Symbol/ObjectContainer.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ObjectContainer_h_
#define liblldb_ObjectContainer_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ModuleChild.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Utility/DataExtractor.h"
diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h
index 1e9ae8b45417..c6bafcecb6f6 100644
--- a/include/lldb/Symbol/ObjectFile.h
+++ b/include/lldb/Symbol/ObjectFile.h
@@ -40,7 +40,7 @@ public:
virtual void PopulateSectionList(lldb_private::ObjectFile *obj_file,
lldb_private::SectionList &section_list) = 0;
- virtual bool GetArchitecture(lldb_private::ArchSpec &arch) = 0;
+ virtual ArchSpec GetArchitecture() = 0;
};
//----------------------------------------------------------------------
@@ -305,19 +305,13 @@ public:
virtual const FileSpec &GetFileSpec() const { return m_file; }
//------------------------------------------------------------------
- /// Get the name of the cpu, vendor and OS for this object file.
- ///
- /// This value is a string that represents the target triple where the cpu
- /// type, the vendor and the OS are encoded into a string.
- ///
- /// @param[out] target_triple
- /// The string value of the target triple.
+ /// Get the ArchSpec for this object file.
///
/// @return
- /// \b True if the target triple was able to be computed, \b
- /// false otherwise.
+ /// The ArchSpec of this object file. In case of error, an invalid
+ /// ArchSpec object is returned.
//------------------------------------------------------------------
- virtual bool GetArchitecture(ArchSpec &arch) = 0;
+ virtual ArchSpec GetArchitecture() = 0;
//------------------------------------------------------------------
/// Gets the section list for the currently selected architecture (and
@@ -551,18 +545,16 @@ public:
virtual lldb_private::Address GetEntryPointAddress() { return Address(); }
//------------------------------------------------------------------
- /// Returns the address that represents the header of this object file.
+ /// Returns base address of this object file.
///
- /// The header address is defined as where the header for the object file is
- /// that describes the content of the file. If the header doesn't appear in
- /// a section that is defined in the object file, an address with no section
- /// is returned that has the file offset set in the m_file_offset member of
- /// the lldb_private::Address object.
- ///
- /// @return
- /// Returns the entry address for this module.
+ /// This also sometimes referred to as the "preferred load address" or the
+ /// "image base address". Addresses within object files are often expressed
+ /// relative to this base. If this address corresponds to a specific section
+ /// (usually the first byte of the first section) then the returned address
+ /// will have this section set. Otherwise, the address will just have the
+ /// offset member filled in, indicating that this represents a file address.
//------------------------------------------------------------------
- virtual lldb_private::Address GetHeaderAddress() {
+ virtual lldb_private::Address GetBaseAddress() {
return Address(m_memory_addr);
}
@@ -817,4 +809,16 @@ private:
} // namespace lldb_private
+namespace llvm {
+template <> struct format_provider<lldb_private::ObjectFile::Type> {
+ static void format(const lldb_private::ObjectFile::Type &type,
+ raw_ostream &OS, StringRef Style);
+};
+
+template <> struct format_provider<lldb_private::ObjectFile::Strata> {
+ static void format(const lldb_private::ObjectFile::Strata &strata,
+ raw_ostream &OS, StringRef Style);
+};
+} // namespace llvm
+
#endif // liblldb_ObjectFile_h_
diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h
index 0ec0006f193a..a7afffb705d2 100644
--- a/include/lldb/Symbol/SymbolContext.h
+++ b/include/lldb/Symbol/SymbolContext.h
@@ -10,14 +10,10 @@
#ifndef liblldb_SymbolContext_h_
#define liblldb_SymbolContext_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Symbol/LineEntry.h"
@@ -232,7 +228,7 @@ public:
bool GetAddressRangeFromHereToEndLine(uint32_t end_line, AddressRange &range,
Status &error);
-
+
//------------------------------------------------------------------
/// Find the best global data symbol visible from this context.
///
@@ -469,10 +465,6 @@ public:
bool AppendIfUnique(const SymbolContext &sc, bool merge_symbol_into_function);
- bool MergeSymbolContextIntoFunctionContext(const SymbolContext &symbol_sc,
- uint32_t start_idx = 0,
- uint32_t stop_idx = UINT32_MAX);
-
uint32_t AppendIfUnique(const SymbolContextList &sc_list,
bool merge_symbol_into_function);
@@ -531,18 +523,6 @@ public:
return m_symbol_contexts[idx];
}
- //------------------------------------------------------------------
- /// Get accessor for the last symbol context in the list.
- ///
- /// @param[out] sc
- /// A reference to the symbol context to fill in.
- ///
- /// @return
- /// Returns \b true if \a sc was filled in, \b false if the
- /// list is empty.
- //------------------------------------------------------------------
- bool GetLastContext(SymbolContext &sc) const;
-
bool RemoveContextAtIndex(size_t idx);
//------------------------------------------------------------------
diff --git a/include/lldb/Symbol/SymbolContextScope.h b/include/lldb/Symbol/SymbolContextScope.h
index c2fbb5272fc0..85718b9bba4f 100644
--- a/include/lldb/Symbol/SymbolContextScope.h
+++ b/include/lldb/Symbol/SymbolContextScope.h
@@ -10,10 +10,6 @@
#ifndef liblldb_SymbolContextScope_h_
#define liblldb_SymbolContextScope_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h
index 7b77c60a3c3d..433c20da99e2 100644
--- a/include/lldb/Symbol/SymbolFile.h
+++ b/include/lldb/Symbol/SymbolFile.h
@@ -14,11 +14,20 @@
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Type.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/DenseSet.h"
+#include <mutex>
+
+#if defined(LLDB_CONFIGURATION_DEBUG)
+#define ASSERT_MODULE_LOCK(expr) (expr->AssertModuleLock())
+#else
+#define ASSERT_MODULE_LOCK(expr) ((void)0)
+#endif
+
namespace lldb_private {
class SymbolFile : public PluginInterface {
@@ -93,6 +102,12 @@ public:
virtual uint32_t CalculateAbilities() = 0;
//------------------------------------------------------------------
+ /// Symbols file subclasses should override this to return the Module that
+ /// owns the TypeSystem that this symbol file modifies type information in.
+ //------------------------------------------------------------------
+ virtual std::recursive_mutex &GetModuleMutex() const;
+
+ //------------------------------------------------------------------
/// Initialize the SymbolFile object.
///
/// The SymbolFile object with the best set of abilities (detected
@@ -110,24 +125,38 @@ public:
virtual uint32_t GetNumCompileUnits() = 0;
virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) = 0;
- virtual lldb::LanguageType
- ParseCompileUnitLanguage(const SymbolContext &sc) = 0;
- virtual size_t ParseCompileUnitFunctions(const SymbolContext &sc) = 0;
- virtual bool ParseCompileUnitLineTable(const SymbolContext &sc) = 0;
- virtual bool ParseCompileUnitDebugMacros(const SymbolContext &sc) = 0;
- virtual bool ParseCompileUnitSupportFiles(const SymbolContext &sc,
- FileSpecList &support_files) = 0;
- virtual bool
- ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) {
- return false;
- }
+ virtual lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) = 0;
+ virtual size_t ParseFunctions(CompileUnit &comp_unit) = 0;
+ virtual bool ParseLineTable(CompileUnit &comp_unit) = 0;
+ virtual bool ParseDebugMacros(CompileUnit &comp_unit) = 0;
+ virtual bool ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) = 0;
+ virtual size_t ParseTypes(CompileUnit &comp_unit) = 0;
+ virtual bool ParseIsOptimized(CompileUnit &comp_unit) { return false; }
+
virtual bool
ParseImportedModules(const SymbolContext &sc,
std::vector<ConstString> &imported_modules) = 0;
- virtual size_t ParseFunctionBlocks(const SymbolContext &sc) = 0;
- virtual size_t ParseTypes(const SymbolContext &sc) = 0;
+ virtual size_t ParseBlocksRecursive(Function &func) = 0;
virtual size_t ParseVariablesForContext(const SymbolContext &sc) = 0;
virtual Type *ResolveTypeUID(lldb::user_id_t type_uid) = 0;
+
+
+ /// The characteristics of an array type.
+ struct ArrayInfo {
+ int64_t first_index;
+ llvm::SmallVector<uint64_t, 1> element_orders;
+ uint32_t byte_stride;
+ uint32_t bit_stride;
+ };
+ /// If \c type_uid points to an array type, return its characteristics.
+ /// To support variable-length array types, this function takes an
+ /// optional \p ExtecutionContext. If \c exe_ctx is non-null, the
+ /// dynamic characteristics for that context are returned.
+ virtual llvm::Optional<ArrayInfo>
+ GetDynamicArrayInfoForUID(lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) = 0;
+
virtual bool CompleteType(CompilerType &compiler_type) = 0;
virtual void ParseDeclsForContext(CompilerDeclContext decl_ctx) {}
virtual CompilerDecl GetDeclForUID(lldb::user_id_t uid) {
@@ -140,12 +169,14 @@ public:
return CompilerDeclContext();
}
virtual uint32_t ResolveSymbolContext(const Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContext &sc) = 0;
virtual uint32_t ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line, bool check_inlines,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list);
+
+ virtual void DumpClangAST(Stream &s) {}
virtual uint32_t
FindGlobalVariables(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
@@ -155,15 +186,15 @@ public:
VariableList &variables);
virtual uint32_t FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines,
- bool append, SymbolContextList &sc_list);
+ lldb::FunctionNameType name_type_mask,
+ bool include_inlines, bool append,
+ SymbolContextList &sc_list);
virtual uint32_t FindFunctions(const RegularExpression &regex,
bool include_inlines, bool append,
SymbolContextList &sc_list);
virtual uint32_t
- FindTypes(const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
- uint32_t max_matches,
+ FindTypes(const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types);
virtual size_t FindTypes(const std::vector<CompilerContext> &context,
@@ -177,7 +208,7 @@ public:
// types) = 0;
virtual TypeList *GetTypeList();
virtual size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) = 0;
virtual void PreloadSymbols();
@@ -186,7 +217,7 @@ public:
GetTypeSystemForLanguage(lldb::LanguageType language);
virtual CompilerDeclContext
- FindNamespace(const SymbolContext &sc, const ConstString &name,
+ FindNamespace(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx) {
return CompilerDeclContext();
}
@@ -194,6 +225,12 @@ public:
ObjectFile *GetObjectFile() { return m_obj_file; }
const ObjectFile *GetObjectFile() const { return m_obj_file; }
+ virtual std::vector<CallEdge> ParseCallEdgesInFunction(UserID func_id) {
+ return {};
+ }
+
+ virtual void AddSymbols(Symtab &symtab) {}
+
//------------------------------------------------------------------
/// Notify the SymbolFile that the file addresses in the Sections
/// for this module have been changed.
@@ -203,6 +240,8 @@ public:
virtual void Dump(Stream &s) {}
protected:
+ void AssertModuleLock();
+
ObjectFile *m_obj_file; // The object file that symbols can be extracted from.
uint32_t m_abilities;
bool m_calculated_abilities;
diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h
index 312b146f2970..d48f646d52cd 100644
--- a/include/lldb/Symbol/SymbolVendor.h
+++ b/include/lldb/Symbol/SymbolVendor.h
@@ -46,37 +46,37 @@ public:
virtual void Dump(Stream *s);
- virtual lldb::LanguageType ParseCompileUnitLanguage(const SymbolContext &sc);
+ virtual lldb::LanguageType ParseLanguage(CompileUnit &comp_unit);
- virtual size_t ParseCompileUnitFunctions(const SymbolContext &sc);
+ virtual size_t ParseFunctions(CompileUnit &comp_unit);
- virtual bool ParseCompileUnitLineTable(const SymbolContext &sc);
+ virtual bool ParseLineTable(CompileUnit &comp_unit);
- virtual bool ParseCompileUnitDebugMacros(const SymbolContext &sc);
+ virtual bool ParseDebugMacros(CompileUnit &comp_unit);
- virtual bool ParseCompileUnitSupportFiles(const SymbolContext &sc,
- FileSpecList &support_files);
+ virtual bool ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files);
- virtual bool ParseCompileUnitIsOptimized(const SymbolContext &sc);
+ virtual bool ParseIsOptimized(CompileUnit &comp_unit);
+
+ virtual size_t ParseTypes(CompileUnit &comp_unit);
virtual bool ParseImportedModules(const SymbolContext &sc,
std::vector<ConstString> &imported_modules);
- virtual size_t ParseFunctionBlocks(const SymbolContext &sc);
-
- virtual size_t ParseTypes(const SymbolContext &sc);
+ virtual size_t ParseBlocksRecursive(Function &func);
virtual size_t ParseVariablesForContext(const SymbolContext &sc);
virtual Type *ResolveTypeUID(lldb::user_id_t type_uid);
virtual uint32_t ResolveSymbolContext(const Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContext &sc);
virtual uint32_t ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line, bool check_inlines,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list);
virtual size_t FindGlobalVariables(const ConstString &name,
@@ -90,17 +90,17 @@ public:
virtual size_t FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines,
- bool append, SymbolContextList &sc_list);
+ lldb::FunctionNameType name_type_mask,
+ bool include_inlines, bool append,
+ SymbolContextList &sc_list);
virtual size_t FindFunctions(const RegularExpression &regex,
bool include_inlines, bool append,
SymbolContextList &sc_list);
virtual size_t
- FindTypes(const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
- size_t max_matches,
+ FindTypes(const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types);
@@ -108,7 +108,7 @@ public:
bool append, TypeMap &types);
virtual CompilerDeclContext
- FindNamespace(const SymbolContext &sc, const ConstString &name,
+ FindNamespace(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx);
virtual size_t GetNumCompileUnits();
@@ -122,8 +122,8 @@ public:
const TypeList &GetTypeList() const { return m_type_list; }
- virtual size_t GetTypes(SymbolContextScope *sc_scope, uint32_t type_mask,
- TypeList &type_list);
+ virtual size_t GetTypes(SymbolContextScope *sc_scope,
+ lldb::TypeClass type_mask, TypeList &type_list);
SymbolFile *GetSymbolFile() { return m_sym_file_ap.get(); }
@@ -164,6 +164,8 @@ protected:
// file)
std::unique_ptr<SymbolFile> m_sym_file_ap; // A single symbol file. Subclasses
// can add more of these if needed.
+ Symtab *m_symtab; // Save a symtab once to not pass it through `AddSymbols` of
+ // the symbol file each time when it is needed
private:
//------------------------------------------------------------------
diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h
index 3d24862af365..286e4f48c2e8 100644
--- a/include/lldb/Symbol/Symtab.h
+++ b/include/lldb/Symbol/Symtab.h
@@ -168,12 +168,12 @@ private:
Visibility symbol_visibility) const {
switch (symbol_debug_type) {
case eDebugNo:
- if (m_symbols[idx].IsDebug() == true)
+ if (m_symbols[idx].IsDebug())
return false;
break;
case eDebugYes:
- if (m_symbols[idx].IsDebug() == false)
+ if (!m_symbols[idx].IsDebug())
return false;
break;
@@ -197,6 +197,15 @@ private:
void SymbolIndicesToSymbolContextList(std::vector<uint32_t> &symbol_indexes,
SymbolContextList &sc_list);
+ void RegisterMangledNameEntry(
+ NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts,
+ std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
+ RichManglingContext &rmc);
+
+ void RegisterBacklogEntry(const NameToIndexMap::Entry &entry,
+ const char *decl_context,
+ const std::set<const char *> &class_contexts);
+
DISALLOW_COPY_AND_ASSIGN(Symtab);
};
diff --git a/include/lldb/Symbol/TypeSystem.h b/include/lldb/Symbol/TypeSystem.h
index 94d1b9cdf3fd..6afbd188a234 100644
--- a/include/lldb/Symbol/TypeSystem.h
+++ b/include/lldb/Symbol/TypeSystem.h
@@ -10,18 +10,14 @@
#ifndef liblldb_TypeSystem_h_
#define liblldb_TypeSystem_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <map>
#include <mutex>
#include <string>
-// Other libraries and framework includes
#include "llvm/ADT/APSInt.h"
#include "llvm/Support/Casting.h"
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/Expression/Expression.h"
#include "lldb/Symbol/CompilerDecl.h"
@@ -72,8 +68,6 @@ public:
enum LLVMCastKind {
eKindClang,
eKindSwift,
- eKindGo,
- eKindJava,
eKindOCaml,
kNumKinds
};
@@ -286,7 +280,8 @@ public:
virtual lldb::Format GetFormat(lldb::opaque_compiler_type_t type) = 0;
virtual uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) = 0;
+ bool omit_empty_base_classes,
+ const ExecutionContext *exe_ctx) = 0;
virtual CompilerType GetBuiltinTypeByName(const ConstString &name);
@@ -347,7 +342,7 @@ public:
const char *name, bool omit_empty_base_classes,
std::vector<uint32_t> &child_indexes) = 0;
- virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type) = 0;
+ virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type);
virtual lldb::TemplateArgumentKind
GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx);
diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h
index a76ea23b46bc..7a5cf7f02a67 100644
--- a/include/lldb/Symbol/UnwindPlan.h
+++ b/include/lldb/Symbol/UnwindPlan.h
@@ -10,14 +10,10 @@
#ifndef liblldb_UnwindPlan_h
#define liblldb_UnwindPlan_h
-// C Includes
-// C++ Includes
#include <map>
#include <memory>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/AddressRange.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Stream.h"
@@ -28,14 +24,22 @@ namespace lldb_private {
// The UnwindPlan object specifies how to unwind out of a function - where this
// function saves the caller's register values before modifying them (for non-
// volatile aka saved registers) and how to find this frame's Canonical Frame
-// Address (CFA).
+// Address (CFA) or Aligned Frame Address (AFA).
+// CFA is a DWARF's Canonical Frame Address.
// Most commonly, registers are saved on the stack, offset some bytes from the
// Canonical Frame Address, or CFA, which is the starting address of this
// function's stack frame (the CFA is same as the eh_frame's CFA, whatever that
// may be on a given architecture). The CFA address for the stack frame does
// not change during the lifetime of the function.
+// AFA is an artificially introduced Aligned Frame Address.
+// It is used only for stack frames with realignment (e.g. when some of the
+// locals has an alignment requirement higher than the stack alignment right
+// after the function call). It is used to access register values saved on the
+// stack after the realignment (and so they are inaccessible through the CFA).
+// AFA usually equals the stack pointer value right after the realignment.
+
// Internally, the UnwindPlan is structured as a vector of register locations
// organized by code address in the function, showing which registers have been
// saved at that point and where they are saved. It can be thought of as the
@@ -61,6 +65,8 @@ public:
same, // reg is unchanged
atCFAPlusOffset, // reg = deref(CFA + offset)
isCFAPlusOffset, // reg = CFA + offset
+ atAFAPlusOffset, // reg = deref(AFA + offset)
+ isAFAPlusOffset, // reg = AFA + offset
inOtherRegister, // reg = other reg
atDWARFExpression, // reg = deref(eval(dwarf_expr))
isDWARFExpression // reg = eval(dwarf_expr)
@@ -90,6 +96,10 @@ public:
bool IsAtCFAPlusOffset() const { return m_type == atCFAPlusOffset; }
+ bool IsAFAPlusOffset() const { return m_type == isAFAPlusOffset; }
+
+ bool IsAtAFAPlusOffset() const { return m_type == atAFAPlusOffset; }
+
bool IsInOtherRegister() const { return m_type == inOtherRegister; }
bool IsAtDWARFExpression() const { return m_type == atDWARFExpression; }
@@ -106,6 +116,16 @@ public:
m_location.offset = offset;
}
+ void SetAtAFAPlusOffset(int32_t offset) {
+ m_type = atAFAPlusOffset;
+ m_location.offset = offset;
+ }
+
+ void SetIsAFAPlusOffset(int32_t offset) {
+ m_type = isAFAPlusOffset;
+ m_location.offset = offset;
+ }
+
void SetInRegister(uint32_t reg_num) {
m_type = inOtherRegister;
m_location.reg_num = reg_num;
@@ -120,9 +140,16 @@ public:
RestoreType GetLocationType() const { return m_type; }
int32_t GetOffset() const {
- if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
+ switch(m_type)
+ {
+ case atCFAPlusOffset:
+ case isCFAPlusOffset:
+ case atAFAPlusOffset:
+ case isAFAPlusOffset:
return m_location.offset;
- return 0;
+ default:
+ return 0;
+ }
}
void GetDWARFExpr(const uint8_t **opcodes, uint16_t &len) const {
@@ -169,20 +196,20 @@ public:
} m_location;
};
- class CFAValue {
+ class FAValue {
public:
enum ValueType {
unspecified, // not specified
- isRegisterPlusOffset, // CFA = register + offset
- isRegisterDereferenced, // CFA = [reg]
- isDWARFExpression // CFA = eval(dwarf_expr)
+ isRegisterPlusOffset, // FA = register + offset
+ isRegisterDereferenced, // FA = [reg]
+ isDWARFExpression // FA = eval(dwarf_expr)
};
- CFAValue() : m_type(unspecified), m_value() {}
+ FAValue() : m_type(unspecified), m_value() {}
- bool operator==(const CFAValue &rhs) const;
+ bool operator==(const FAValue &rhs) const;
- bool operator!=(const CFAValue &rhs) const { return !(*this == rhs); }
+ bool operator!=(const FAValue &rhs) const { return !(*this == rhs); }
void SetUnspecified() { m_type = unspecified; }
@@ -279,7 +306,7 @@ public:
uint16_t length;
} expr;
} m_value;
- }; // class CFAValue
+ }; // class FAValue
public:
Row();
@@ -302,7 +329,9 @@ public:
void SlideOffset(lldb::addr_t offset) { m_offset += offset; }
- CFAValue &GetCFAValue() { return m_cfa_value; }
+ FAValue &GetCFAValue() { return m_cfa_value; }
+
+ FAValue &GetAFAValue() { return m_afa_value; }
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset,
bool can_replace);
@@ -329,7 +358,8 @@ public:
typedef std::map<uint32_t, RegisterLocation> collection;
lldb::addr_t m_offset; // Offset into the function for this row
- CFAValue m_cfa_value;
+ FAValue m_cfa_value;
+ FAValue m_afa_value;
collection m_register_locations;
}; // class Row
diff --git a/include/lldb/Symbol/UnwindTable.h b/include/lldb/Symbol/UnwindTable.h
index 5c83e3003192..061e7ddc0f99 100644
--- a/include/lldb/Symbol/UnwindTable.h
+++ b/include/lldb/Symbol/UnwindTable.h
@@ -50,7 +50,7 @@ public:
GetUncachedFuncUnwindersContainingAddress(const Address &addr,
SymbolContext &sc);
- bool GetArchitecture(lldb_private::ArchSpec &arch);
+ ArchSpec GetArchitecture();
private:
void Dump(Stream &s);
diff --git a/include/lldb/Target/ABI.h b/include/lldb/Target/ABI.h
index 343b3a749597..24fff1caf6c4 100644
--- a/include/lldb/Target/ABI.h
+++ b/include/lldb/Target/ABI.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABI_h_
#define liblldb_ABI_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Utility/Status.h"
diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h
index aae85f420ef7..e96ee168389b 100644
--- a/include/lldb/Target/CPPLanguageRuntime.h
+++ b/include/lldb/Target/CPPLanguageRuntime.h
@@ -11,11 +11,7 @@
#ifndef liblldb_CPPLanguageRuntime_h_
#define liblldb_CPPLanguageRuntime_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/lldb-private.h"
@@ -24,6 +20,25 @@ namespace lldb_private {
class CPPLanguageRuntime : public LanguageRuntime {
public:
+ enum class LibCppStdFunctionCallableCase {
+ Lambda = 0,
+ CallableObject,
+ FreeOrMemberFunction,
+ Invalid
+ };
+
+ struct LibCppStdFunctionCallableInfo {
+ Symbol callable_symbol;
+ Address callable_address;
+ LineEntry callable_line_entry;
+ lldb::addr_t member__f_pointer_value = 0u;
+ LibCppStdFunctionCallableCase callable_case =
+ LibCppStdFunctionCallableCase::Invalid;
+ };
+
+ LibCppStdFunctionCallableInfo
+ FindLibCppStdFunctionCallableInfo(lldb::ValueObjectSP &valobj_sp);
+
~CPPLanguageRuntime() override;
lldb::LanguageType GetLanguageType() const override {
@@ -37,6 +52,19 @@ public:
bool GetObjectDescription(Stream &str, Value &value,
ExecutionContextScope *exe_scope) override;
+ /// Obtain a ThreadPlan to get us into C++ constructs such as std::function.
+ ///
+ /// @param[in] thread
+ /// Curent thrad of execution.
+ ///
+ /// @param[in] stop_others
+ /// True if other threads should pause during execution.
+ ///
+ /// @return
+ /// A ThreadPlan Shared pointer
+ lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
+ bool stop_others);
+
protected:
//------------------------------------------------------------------
// Classes that inherit from CPPLanguageRuntime can see and modify these
diff --git a/include/lldb/Target/DynamicLoader.h b/include/lldb/Target/DynamicLoader.h
index de9c4e233b0c..fe04f94aa31b 100644
--- a/include/lldb/Target/DynamicLoader.h
+++ b/include/lldb/Target/DynamicLoader.h
@@ -10,18 +10,17 @@
#ifndef liblldb_DynamicLoader_h_
#define liblldb_DynamicLoader_h_
-// Project includes
#include "lldb/Core/PluginInterface.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/UUID.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-forward.h" // for ModuleSP, ThreadPlanSP
-#include "lldb/lldb-private-enumerations.h" // for LazyBool, LazyBool::eLaz...
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for int64_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class ModuleList;
}
diff --git a/include/lldb/Target/ExecutionContext.h b/include/lldb/Target/ExecutionContext.h
index 70eba3654dec..167189c3a837 100644
--- a/include/lldb/Target/ExecutionContext.h
+++ b/include/lldb/Target/ExecutionContext.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ExecutionContext_h_
#define liblldb_ExecutionContext_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackID.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/ExecutionContextScope.h b/include/lldb/Target/ExecutionContextScope.h
index b73ca576bd8a..3e787584be0b 100644
--- a/include/lldb/Target/ExecutionContextScope.h
+++ b/include/lldb/Target/ExecutionContextScope.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ExecutionContextScope_h_
#define liblldb_ExecutionContextScope_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
diff --git a/include/lldb/Target/InstrumentationRuntime.h b/include/lldb/Target/InstrumentationRuntime.h
index 21d66d5766a9..ba905cb8535d 100644
--- a/include/lldb/Target/InstrumentationRuntime.h
+++ b/include/lldb/Target/InstrumentationRuntime.h
@@ -10,13 +10,9 @@
#ifndef liblldb_InstrumentationRuntime_h_
#define liblldb_InstrumentationRuntime_h_
-// C Includes
-// C++ Includes
#include <map>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-forward.h"
diff --git a/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/include/lldb/Target/InstrumentationRuntimeStopInfo.h
index b11231960ac1..7c72c9524eca 100644
--- a/include/lldb/Target/InstrumentationRuntimeStopInfo.h
+++ b/include/lldb/Target/InstrumentationRuntimeStopInfo.h
@@ -10,12 +10,8 @@
#ifndef liblldb_InstrumentationRuntimeStopInfo_h_
#define liblldb_InstrumentationRuntimeStopInfo_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StopInfo.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/include/lldb/Target/Language.h b/include/lldb/Target/Language.h
index dd7db26f3ba6..27f40fd1ba83 100644
--- a/include/lldb/Target/Language.h
+++ b/include/lldb/Target/Language.h
@@ -11,15 +11,12 @@
#ifndef liblldb_Language_h_
#define liblldb_Language_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <memory>
#include <set>
#include <vector>
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Core/Highlighter.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/DataFormatters/FormatClasses.h"
@@ -152,6 +149,13 @@ public:
static Language *FindPlugin(lldb::LanguageType language);
+ /// Returns the Language associated with the given file path or a nullptr
+ /// if there is no known language.
+ static Language *FindPlugin(llvm::StringRef file_path);
+
+ static Language *FindPlugin(lldb::LanguageType language,
+ llvm::StringRef file_path);
+
// return false from callback to stop iterating
static void ForEach(std::function<bool(Language *)> callback);
@@ -159,6 +163,10 @@ public:
virtual bool IsTopLevelFunction(Function &function);
+ virtual bool IsSourceFile(llvm::StringRef file_path) const = 0;
+
+ virtual const Highlighter *GetHighlighter() const { return nullptr; }
+
virtual lldb::TypeCategoryImplSP GetFormatters();
virtual HardcodedFormatters::HardcodedFormatFinder GetHardcodedFormats();
diff --git a/include/lldb/Target/LanguageRuntime.h b/include/lldb/Target/LanguageRuntime.h
index 6537a8f6dd55..2a2f47b85359 100644
--- a/include/lldb/Target/LanguageRuntime.h
+++ b/include/lldb/Target/LanguageRuntime.h
@@ -11,10 +11,6 @@
#ifndef liblldb_LanguageRuntime_h_
#define liblldb_LanguageRuntime_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
#include "lldb/Core/PluginInterface.h"
@@ -123,6 +119,17 @@ public:
static Breakpoint::BreakpointPreconditionSP
CreateExceptionPrecondition(lldb::LanguageType language, bool catch_bp,
bool throw_bp);
+
+ virtual lldb::ValueObjectSP GetExceptionObjectForThread(
+ lldb::ThreadSP thread_sp) {
+ return lldb::ValueObjectSP();
+ }
+
+ virtual lldb::ThreadSP GetBacktraceThreadFromException(
+ lldb::ValueObjectSP thread_sp) {
+ return lldb::ThreadSP();
+ }
+
Process *GetProcess() { return m_process; }
Target &GetTargetRef() { return m_process->GetTarget(); }
diff --git a/include/lldb/Target/Memory.h b/include/lldb/Target/Memory.h
index 16d7b256a78e..d5e6c105f76d 100644
--- a/include/lldb/Target/Memory.h
+++ b/include/lldb/Target/Memory.h
@@ -10,15 +10,11 @@
#ifndef liblldb_Memory_h_
#define liblldb_Memory_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/RangeMap.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/MemoryHistory.h b/include/lldb/Target/MemoryHistory.h
index acc36ffe2eb4..cb3e90053357 100644
--- a/include/lldb/Target/MemoryHistory.h
+++ b/include/lldb/Target/MemoryHistory.h
@@ -11,12 +11,8 @@
#ifndef liblldb_MemoryHistory_h_
#define liblldb_MemoryHistory_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/lldb-private.h"
#include "lldb/lldb-types.h"
diff --git a/include/lldb/Target/MemoryRegionInfo.h b/include/lldb/Target/MemoryRegionInfo.h
index 505ecfcfc5ae..a57c4678bb37 100644
--- a/include/lldb/Target/MemoryRegionInfo.h
+++ b/include/lldb/Target/MemoryRegionInfo.h
@@ -14,7 +14,6 @@
#include "lldb/Core/RangeMap.h"
#include "llvm/Support/FormatProviders.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/Range.h"
namespace lldb_private {
class MemoryRegionInfo {
@@ -109,6 +108,26 @@ protected:
OptionalBool m_flash;
lldb::offset_t m_blocksize;
};
+
+inline bool operator<(const MemoryRegionInfo &lhs,
+ const MemoryRegionInfo &rhs) {
+ return lhs.GetRange() < rhs.GetRange();
+}
+
+inline bool operator<(const MemoryRegionInfo &lhs, lldb::addr_t rhs) {
+ return lhs.GetRange().GetRangeBase() < rhs;
+}
+
+inline bool operator<(lldb::addr_t lhs, const MemoryRegionInfo &rhs) {
+ return lhs < rhs.GetRange().GetRangeBase();
+}
+
+// Forward-declarable wrapper.
+class MemoryRegionInfos : public std::vector<lldb_private::MemoryRegionInfo> {
+public:
+ using std::vector<lldb_private::MemoryRegionInfo>::vector;
+};
+
}
namespace llvm {
diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h
index 6f8354ea3a27..9eebf9463043 100644
--- a/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/include/lldb/Target/ObjCLanguageRuntime.h
@@ -10,17 +10,13 @@
#ifndef liblldb_ObjCLanguageRuntime_h_
#define liblldb_ObjCLanguageRuntime_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <map>
#include <memory>
#include <unordered_set>
-// Other libraries and framework includes
#include "llvm/Support/Casting.h"
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/ThreadSafeDenseMap.h"
#include "lldb/Symbol/CompilerType.h"
diff --git a/include/lldb/Target/OperatingSystem.h b/include/lldb/Target/OperatingSystem.h
index fe4fdee182f4..4d73bb3906ee 100644
--- a/include/lldb/Target/OperatingSystem.h
+++ b/include/lldb/Target/OperatingSystem.h
@@ -11,9 +11,6 @@
#ifndef liblldb_OperatingSystem_h_
#define liblldb_OperatingSystem_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/PathMappingList.h b/include/lldb/Target/PathMappingList.h
index a5ee3265a223..29e6ef191e27 100644
--- a/include/lldb/Target/PathMappingList.h
+++ b/include/lldb/Target/PathMappingList.h
@@ -10,14 +10,10 @@
#ifndef liblldb_PathMappingList_h_
#define liblldb_PathMappingList_h_
-// C Includes
-// C++ Includes
#include <map>
#include <vector>
-// Other libraries and framework includes
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
-// Project includes
namespace lldb_private {
diff --git a/include/lldb/Target/Platform.h b/include/lldb/Target/Platform.h
index 217b945d29cd..3dbeef73f0ab 100644
--- a/include/lldb/Target/Platform.h
+++ b/include/lldb/Target/Platform.h
@@ -10,8 +10,6 @@
#ifndef liblldb_Platform_h_
#define liblldb_Platform_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <map>
#include <memory>
@@ -19,8 +17,6 @@
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Interpreter/Options.h"
@@ -1131,10 +1127,6 @@ public:
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- // 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;
@@ -1160,10 +1152,6 @@ public:
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- // 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;
@@ -1187,10 +1175,6 @@ public:
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- // 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;
diff --git a/include/lldb/Target/Process.h b/include/lldb/Target/Process.h
index 66ac5a692522..be72b9a9c747 100644
--- a/include/lldb/Target/Process.h
+++ b/include/lldb/Target/Process.h
@@ -12,10 +12,8 @@
#include "lldb/Host/Config.h"
-// C Includes
#include <limits.h>
-// C++ Includes
#include <chrono>
#include <list>
#include <memory>
@@ -24,13 +22,8 @@
#include <unordered_set>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointSiteList.h"
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Communication.h"
-#include "lldb/Core/Event.h"
-#include "lldb/Core/Listener.h"
#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/ThreadSafeValue.h"
@@ -47,6 +40,9 @@
#include "lldb/Target/QueueList.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/Listener.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
@@ -319,7 +315,7 @@ public:
NameMatch process_name_match_type)
: m_match_info(), m_name_match_type(process_name_match_type),
m_match_all_users(false) {
- m_match_info.GetExecutableFile().SetFile(process_name, false,
+ m_match_info.GetExecutableFile().SetFile(process_name,
FileSpec::Style::native);
}
@@ -402,7 +398,8 @@ class ProcessModID {
public:
ProcessModID()
: m_stop_id(0), m_last_natural_stop_id(0), m_resume_id(0), m_memory_id(0),
- m_last_user_expression_resume(0), m_running_user_expression(false) {}
+ m_last_user_expression_resume(0), m_running_user_expression(false),
+ m_running_utility_function(0) {}
ProcessModID(const ProcessModID &rhs)
: m_stop_id(rhs.m_stop_id), m_memory_id(rhs.m_memory_id) {}
@@ -431,6 +428,10 @@ public:
m_last_user_expression_resume = m_resume_id;
}
+ bool IsRunningUtilityFunction() const {
+ return m_running_utility_function > 0;
+ }
+
uint32_t GetStopID() const { return m_stop_id; }
uint32_t GetLastNaturalStopID() const { return m_last_natural_stop_id; }
uint32_t GetMemoryID() const { return m_memory_id; }
@@ -467,6 +468,17 @@ public:
m_running_user_expression--;
}
+ void SetRunningUtilityFunction(bool on) {
+ if (on)
+ m_running_utility_function++;
+ else {
+ assert(m_running_utility_function > 0 &&
+ "Called SetRunningUtilityFunction(false) without calling "
+ "SetRunningUtilityFunction(true) before?");
+ m_running_utility_function--;
+ }
+ }
+
void SetStopEventForLastNaturalStopID(lldb::EventSP event_sp) {
m_last_natural_stop_event = event_sp;
}
@@ -484,6 +496,7 @@ private:
uint32_t m_memory_id;
uint32_t m_last_user_expression_resume;
uint32_t m_running_user_expression;
+ uint32_t m_running_utility_function;
lldb::EventSP m_last_natural_stop_event;
};
@@ -2068,7 +2081,7 @@ public:
/// An error value.
//------------------------------------------------------------------
virtual Status
- GetMemoryRegions(std::vector<lldb::MemoryRegionInfoSP> &region_list);
+ GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list);
virtual Status GetWatchpointSupportInfo(uint32_t &num) {
Status error;
@@ -2554,6 +2567,7 @@ public:
virtual bool StopNoticingNewThreads() { return true; }
void SetRunningUserExpression(bool on);
+ void SetRunningUtilityFunction(bool on);
//------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
@@ -3225,6 +3239,24 @@ private:
DISALLOW_COPY_AND_ASSIGN(Process);
};
+//------------------------------------------------------------------
+/// RAII guard that should be aquired when an utility function is called within
+/// a given process.
+//------------------------------------------------------------------
+class UtilityFunctionScope {
+ Process *m_process;
+
+public:
+ UtilityFunctionScope(Process *p) : m_process(p) {
+ if (m_process)
+ m_process->SetRunningUtilityFunction(true);
+ }
+ ~UtilityFunctionScope() {
+ if (m_process)
+ m_process->SetRunningUtilityFunction(false);
+ }
+};
+
} // namespace lldb_private
#endif // liblldb_Process_h_
diff --git a/include/lldb/Target/ProcessLaunchInfo.h b/include/lldb/Target/ProcessLaunchInfo.h
index 92c517a3e460..ef1d63035b18 100644
--- a/include/lldb/Target/ProcessLaunchInfo.h
+++ b/include/lldb/Target/ProcessLaunchInfo.h
@@ -52,7 +52,10 @@ public:
bool AppendSuppressFileAction(int fd, bool read, bool write);
- void FinalizeFileActions(Target *target, bool default_to_use_pty);
+ // Redirect stdin/stdout/stderr to a pty, if no action for the respective file
+ // descriptor is specified. (So if stdin and stdout already have file actions,
+ // but stderr doesn't, then only stderr will be redirected to a pty.)
+ llvm::Error SetUpPtyRedirection();
size_t GetNumFileActions() const { return m_file_actions.size(); }
@@ -131,8 +134,6 @@ public:
m_listener_sp = listener_sp;
}
- lldb::ListenerSP GetListenerForProcess(Debugger &debugger);
-
lldb::ListenerSP GetHijackListener() const { return m_hijack_listener_sp; }
void SetHijackListener(const lldb::ListenerSP &listener_sp) {
diff --git a/include/lldb/Target/ProcessStructReader.h b/include/lldb/Target/ProcessStructReader.h
index 8f1445ae8c1b..79f0b4cccd45 100644
--- a/include/lldb/Target/ProcessStructReader.h
+++ b/include/lldb/Target/ProcessStructReader.h
@@ -60,18 +60,20 @@ public:
return;
auto size = field_type.GetByteSize(nullptr);
// no support for things larger than a uint64_t (yet)
- if (size > 8)
+ if (!size || *size > 8)
return;
ConstString const_name = ConstString(name.c_str());
size_t byte_index = static_cast<size_t>(bit_offset / 8);
m_fields[const_name] =
- FieldImpl{field_type, byte_index, static_cast<size_t>(size)};
+ FieldImpl{field_type, byte_index, static_cast<size_t>(*size)};
}
- size_t total_size = struct_type.GetByteSize(nullptr);
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(total_size, 0));
+ auto total_size = struct_type.GetByteSize(nullptr);
+ if (!total_size)
+ return;
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(*total_size, 0));
Status error;
process->ReadMemoryFromInferior(base_addr, buffer_sp->GetBytes(),
- total_size, error);
+ *total_size, error);
if (error.Fail())
return;
m_data = DataExtractor(buffer_sp, m_byte_order, m_addr_byte_size);
diff --git a/include/lldb/Target/QueueItem.h b/include/lldb/Target/QueueItem.h
index 76bcea36a2fa..3fd331ca525a 100644
--- a/include/lldb/Target/QueueItem.h
+++ b/include/lldb/Target/QueueItem.h
@@ -10,14 +10,10 @@
#ifndef liblldb_QueueItem_h_
#define liblldb_QueueItem_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/RegisterContext.h b/include/lldb/Target/RegisterContext.h
index 73a2930fd2b5..a24c270a1e5e 100644
--- a/include/lldb/Target/RegisterContext.h
+++ b/include/lldb/Target/RegisterContext.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContext_h_
#define liblldb_RegisterContext_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/SectionLoadHistory.h b/include/lldb/Target/SectionLoadHistory.h
index 0ed335a9d040..0a14fc05c458 100644
--- a/include/lldb/Target/SectionLoadHistory.h
+++ b/include/lldb/Target/SectionLoadHistory.h
@@ -10,12 +10,9 @@
#ifndef liblldb_SectionLoadHistory_h_
#define liblldb_SectionLoadHistory_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
-// Project includes
#include "lldb/lldb-public.h"
namespace lldb_private {
diff --git a/include/lldb/Target/SectionLoadList.h b/include/lldb/Target/SectionLoadList.h
index 1156c686df17..2a321e7a2545 100644
--- a/include/lldb/Target/SectionLoadList.h
+++ b/include/lldb/Target/SectionLoadList.h
@@ -11,14 +11,10 @@
#ifndef liblldb_SectionLoadList_h_
#define liblldb_SectionLoadList_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
-// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
-// Project includes
#include "lldb/Core/Section.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/Target/StackFrame.h b/include/lldb/Target/StackFrame.h
index ce9b16227672..a4e31a567440 100644
--- a/include/lldb/Target/StackFrame.h
+++ b/include/lldb/Target/StackFrame.h
@@ -10,20 +10,16 @@
#ifndef liblldb_StackFrame_h_
#define liblldb_StackFrame_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Flags.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/StackID.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/UserID.h"
@@ -35,9 +31,9 @@ namespace lldb_private {
/// 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.
+/// A frame may have a plain pc value or it may 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.
@@ -54,14 +50,27 @@ public:
eExpressionPathOptionsInspectAnonymousUnions = (1u << 5)
};
+ enum class Kind {
+ /// A regular stack frame with access to registers and local variables.
+ Regular,
+
+ /// A historical stack frame -- possibly without CFA or registers or
+ /// local variables.
+ History,
+
+ /// An artificial stack frame (e.g. a synthesized result of inferring
+ /// missing tail call frames from a backtrace) with limited support for
+ /// local variables.
+ Artificial
+ };
+
//------------------------------------------------------------------
/// 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,
+ /// point in the past. We may only have pc values. We may have a CFA,
/// or more likely, we won't.
///
/// @param [in] thread_sp
@@ -92,23 +101,7 @@ public:
/// @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] frame_kind
///
/// @param [in] sc_ptr
/// Optionally seed the StackFrame with the SymbolContext information that
@@ -117,8 +110,7 @@ public:
//------------------------------------------------------------------
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,
+ bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind,
const SymbolContext *sc_ptr);
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
@@ -177,7 +169,7 @@ public:
/// A SymbolContext reference which includes the types of information
/// requested by resolve_scope, if they are available.
//------------------------------------------------------------------
- const SymbolContext &GetSymbolContext(uint32_t resolve_scope);
+ const SymbolContext &GetSymbolContext(lldb::SymbolContextItem resolve_scope);
//------------------------------------------------------------------
/// Return the Canonical Frame Address (DWARF term) for this frame.
@@ -403,6 +395,18 @@ public:
bool IsInlined();
//------------------------------------------------------------------
+ /// Query whether this frame is part of a historical backtrace.
+ //------------------------------------------------------------------
+ bool IsHistorical() const;
+
+ //------------------------------------------------------------------
+ /// Query whether this frame is artificial (e.g a synthesized result of
+ /// inferring missing tail call frames from a backtrace). Artificial frames
+ /// may have limited support for inspecting variables.
+ //------------------------------------------------------------------
+ bool IsArtificial() const;
+
+ //------------------------------------------------------------------
/// Query this frame to find what frame it is in this Thread's
/// StackFrameList.
///
@@ -413,6 +417,11 @@ public:
uint32_t GetFrameIndex() const;
//------------------------------------------------------------------
+ /// Set this frame's synthetic frame index.
+ //------------------------------------------------------------------
+ void SetFrameIndex(uint32_t index) { m_frame_index = index; }
+
+ //------------------------------------------------------------------
/// Query this frame to find what frame it is in this Thread's
/// StackFrameList, not counting inlined frames.
///
@@ -504,6 +513,21 @@ public:
int64_t offset);
//------------------------------------------------------------------
+ /// Attempt to reconstruct the ValueObject for a variable with a given \a name
+ /// from within the current StackFrame, within the current block. The search
+ /// for the variable starts in the deepest block corresponding to the current
+ /// PC in the stack frame and traverse through all parent blocks stopping at
+ /// inlined function boundaries.
+ ///
+ /// @params [in] name
+ /// The name of the variable.
+ ///
+ /// @return
+ /// The ValueObject if found.
+ //------------------------------------------------------------------
+ lldb::ValueObjectSP FindVariable(ConstString name);
+
+ //------------------------------------------------------------------
// lldb::ExecutionContextScope pure virtual functions
//------------------------------------------------------------------
lldb::TargetSP CalculateTarget() override;
@@ -516,6 +540,8 @@ public:
void CalculateExecutionContext(ExecutionContext &exe_ctx) override;
+ lldb::RecognizedStackFrameSP GetRecognizedFrame();
+
protected:
friend class StackFrameList;
@@ -545,14 +571,12 @@ private:
Status 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;
+ Kind m_stack_frame_kind;
lldb::VariableListSP m_variable_list_sp;
ValueObjectList m_variable_list_value_objects; // Value objects for each
// variable in
// m_variable_list_sp
+ lldb::RecognizedStackFrameSP m_recognized_frame_sp;
StreamString m_disassembly;
std::recursive_mutex m_mutex;
diff --git a/include/lldb/Target/StackFrameList.h b/include/lldb/Target/StackFrameList.h
index cb9fb136fb4e..0de90b3ba4ac 100644
--- a/include/lldb/Target/StackFrameList.h
+++ b/include/lldb/Target/StackFrameList.h
@@ -10,14 +10,10 @@
#ifndef liblldb_StackFrameList_h_
#define liblldb_StackFrameList_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackFrame.h"
namespace lldb_private {
@@ -32,22 +28,33 @@ public:
~StackFrameList();
+ /// Get the number of visible frames. Frames may be created if \p can_create
+ /// is true. Synthetic (inline) frames expanded from the concrete frame #0
+ /// (aka invisible frames) are not included in this count.
uint32_t GetNumFrames(bool can_create = true);
+ /// Get the frame at index \p idx. Invisible frames cannot be indexed.
lldb::StackFrameSP GetFrameAtIndex(uint32_t idx);
+ /// Get the first concrete frame with index greater than or equal to \p idx.
+ /// Unlike \ref GetFrameAtIndex, this cannot return a synthetic frame.
lldb::StackFrameSP GetFrameWithConcreteFrameIndex(uint32_t unwind_idx);
+ /// Retrieve the stack frame with the given ID \p stack_id.
lldb::StackFrameSP GetFrameWithStackID(const StackID &stack_id);
- // Mark a stack frame as the current frame
+ /// Mark a stack frame as the currently selected frame and return its index.
uint32_t SetSelectedFrame(lldb_private::StackFrame *frame);
+ /// Get the currently selected frame index.
uint32_t GetSelectedFrameIndex() const;
- // Mark a stack frame as the current frame using the frame index
+ /// Mark a stack frame as the currently selected frame using the frame index
+ /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected.
bool SetSelectedFrameByIndex(uint32_t idx);
+ /// If the current inline depth (i.e the number of invisible frames) is valid,
+ /// subtract it from \p idx. Otherwise simply return \p idx.
uint32_t GetVisibleStackFrameIndex(uint32_t idx) {
if (m_current_inlined_depth < UINT32_MAX)
return idx - m_current_inlined_depth;
@@ -55,16 +62,23 @@ public:
return idx;
}
+ /// Calculate and set the current inline depth. This may be used to update
+ /// the StackFrameList's set of inline frames when execution stops, e.g when
+ /// a breakpoint is hit.
void CalculateCurrentInlinedDepth();
+ /// If the currently selected frame comes from the currently selected thread,
+ /// point the default file and line of the thread's target to the location
+ /// specified by the frame.
void SetDefaultFileAndLineToSelectedFrame();
+ /// Clear the cache of frames.
void Clear();
- void InvalidateFrames(uint32_t start_idx);
-
void Dump(Stream *s);
+ /// If \p stack_frame_ptr is contained in this StackFrameList, return its
+ /// wrapping shared pointer.
lldb::StackFrameSP
GetStackFrameSPForStackFramePtr(StackFrame *stack_frame_ptr);
@@ -83,6 +97,10 @@ protected:
void GetFramesUpTo(uint32_t end_idx);
+ void GetOnlyConcreteFramesUpTo(uint32_t end_idx, Unwind *unwinder);
+
+ void SynthesizeTailCallFrames(StackFrame &next_frame);
+
bool GetAllFramesFetched() { return m_concrete_frames_fetched == UINT32_MAX; }
void SetAllFramesFetched() { m_concrete_frames_fetched = UINT32_MAX; }
@@ -99,15 +117,45 @@ protected:
typedef collection::iterator iterator;
typedef collection::const_iterator const_iterator;
+ /// The thread this frame list describes.
Thread &m_thread;
+
+ /// The old stack frame list.
+ // TODO: The old stack frame list is used to fill in missing frame info
+ // heuristically when it's otherwise unavailable (say, because the unwinder
+ // fails). We should have stronger checks to make sure that this is a valid
+ // source of information.
lldb::StackFrameListSP m_prev_frames_sp;
+
+ /// A mutex for this frame list.
+ // TODO: This mutex may not always be held when required. In particular, uses
+ // of the StackFrameList APIs in lldb_private::Thread look suspect. Consider
+ // passing around a lock_guard reference to enforce proper locking.
mutable std::recursive_mutex m_mutex;
+
+ /// A cache of frames. This may need to be updated when the program counter
+ /// changes.
collection m_frames;
+
+ /// The currently selected frame.
uint32_t m_selected_frame_idx;
+
+ /// The number of concrete frames fetched while filling the frame list. This
+ /// is only used when synthetic frames are enabled.
uint32_t m_concrete_frames_fetched;
+
+ /// The number of synthetic function activations (invisible frames) expanded
+ /// from the concrete frame #0 activation.
+ // TODO: Use an optional instead of UINT32_MAX to denote invalid values.
uint32_t m_current_inlined_depth;
+
+ /// The program counter value at the currently selected synthetic activation.
+ /// This is only valid if m_current_inlined_depth is valid.
+ // TODO: Use an optional instead of UINT32_MAX to denote invalid values.
lldb::addr_t m_current_inlined_pc;
- bool m_show_inlined_frames;
+
+ /// Whether or not to show synthetic (inline) frames. Immutable.
+ const bool m_show_inlined_frames;
private:
DISALLOW_COPY_AND_ASSIGN(StackFrameList);
diff --git a/include/lldb/Target/StackFrameRecognizer.h b/include/lldb/Target/StackFrameRecognizer.h
new file mode 100644
index 000000000000..35ec23b754f3
--- /dev/null
+++ b/include/lldb/Target/StackFrameRecognizer.h
@@ -0,0 +1,129 @@
+//===-- StackFrameRecognizer.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_StackFrameRecognizer_h_
+#define liblldb_StackFrameRecognizer_h_
+
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Utility/StructuredData.h"
+#include "lldb/lldb-private-forward.h"
+#include "lldb/lldb-public.h"
+
+namespace lldb_private {
+
+/// @class RecognizedStackFrame
+///
+/// This class provides extra information about a stack frame that was
+/// provided by a specific stack frame recognizer. Right now, this class only
+/// holds recognized arguments (via GetRecognizedArguments).
+
+class RecognizedStackFrame
+ : public std::enable_shared_from_this<RecognizedStackFrame> {
+public:
+ virtual lldb::ValueObjectListSP GetRecognizedArguments() {
+ return m_arguments;
+ }
+ virtual lldb::ValueObjectSP GetExceptionObject() {
+ return lldb::ValueObjectSP();
+ }
+ virtual ~RecognizedStackFrame(){};
+
+protected:
+ lldb::ValueObjectListSP m_arguments;
+};
+
+/// @class StackFrameRecognizer
+///
+/// A base class for frame recognizers. Subclasses (actual frame recognizers)
+/// should implement RecognizeFrame to provide a RecognizedStackFrame for a
+/// given stack frame.
+
+class StackFrameRecognizer
+ : public std::enable_shared_from_this<StackFrameRecognizer> {
+public:
+ virtual lldb::RecognizedStackFrameSP RecognizeFrame(
+ lldb::StackFrameSP frame) {
+ return lldb::RecognizedStackFrameSP();
+ };
+ virtual std::string GetName() {
+ return "";
+ }
+
+ virtual ~StackFrameRecognizer(){};
+};
+
+#ifndef LLDB_DISABLE_PYTHON
+
+/// @class ScriptedStackFrameRecognizer
+///
+/// Python implementation for frame recognizers. An instance of this class
+/// tracks a particular Python classobject, which will be asked to recognize
+/// stack frames.
+
+class ScriptedStackFrameRecognizer : public StackFrameRecognizer {
+ lldb_private::ScriptInterpreter *m_interpreter;
+ lldb_private::StructuredData::ObjectSP m_python_object_sp;
+ std::string m_python_class;
+
+public:
+ ScriptedStackFrameRecognizer(lldb_private::ScriptInterpreter *interpreter,
+ const char *pclass);
+ ~ScriptedStackFrameRecognizer() {}
+
+ std::string GetName() override {
+ return GetPythonClassName();
+ }
+
+ const char *GetPythonClassName() { return m_python_class.c_str(); }
+
+ lldb::RecognizedStackFrameSP RecognizeFrame(
+ lldb::StackFrameSP frame) override;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(ScriptedStackFrameRecognizer);
+};
+
+#endif
+
+/// @class StackFrameRecognizerManager
+///
+/// Static class that provides a registry of known stack frame recognizers.
+/// Has static methods to add, enumerate, remove, query and invoke recognizers.
+
+class StackFrameRecognizerManager {
+public:
+ static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
+ const ConstString &module,
+ const ConstString &symbol,
+ bool first_instruction_only = true);
+
+ static void AddRecognizer(lldb::StackFrameRecognizerSP recognizer,
+ lldb::RegularExpressionSP module,
+ lldb::RegularExpressionSP symbol,
+ bool first_instruction_only = true);
+
+ static void ForEach(
+ std::function<void(uint32_t recognizer_id, std::string recognizer_name,
+ std::string module, std::string symbol,
+ bool regexp)> const &callback);
+
+ static bool RemoveRecognizerWithID(uint32_t recognizer_id);
+
+ static void RemoveAllRecognizers();
+
+ static lldb::StackFrameRecognizerSP GetRecognizerForFrame(
+ lldb::StackFrameSP frame);
+
+ static lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_StackFrameRecognizer_h_
diff --git a/include/lldb/Target/StackID.h b/include/lldb/Target/StackID.h
index 51e51a6c0741..871f39c463a9 100644
--- a/include/lldb/Target/StackID.h
+++ b/include/lldb/Target/StackID.h
@@ -10,10 +10,6 @@
#ifndef liblldb_StackID_h_
#define liblldb_StackID_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/AddressRange.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/StopInfo.h b/include/lldb/Target/StopInfo.h
index b25bf7dd3d5d..1a9f5b8480db 100644
--- a/include/lldb/Target/StopInfo.h
+++ b/include/lldb/Target/StopInfo.h
@@ -10,12 +10,8 @@
#ifndef liblldb_StopInfo_h_
#define liblldb_StopInfo_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-public.h"
diff --git a/include/lldb/Target/SystemRuntime.h b/include/lldb/Target/SystemRuntime.h
index 06cc3ec2d012..328dbe231078 100644
--- a/include/lldb/Target/SystemRuntime.h
+++ b/include/lldb/Target/SystemRuntime.h
@@ -10,10 +10,6 @@
#ifndef liblldb_SystemRuntime_h_
#define liblldb_SystemRuntime_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include <vector>
#include "lldb/Core/ModuleList.h"
diff --git a/include/lldb/Target/Target.h b/include/lldb/Target/Target.h
index 75af8e80d2e5..90df1f4929b7 100644
--- a/include/lldb/Target/Target.h
+++ b/include/lldb/Target/Target.h
@@ -10,21 +10,16 @@
#ifndef liblldb_Target_h_
#define liblldb_Target_h_
-// C Includes
-// C++ Includes
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointList.h"
#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Core/Architecture.h"
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/UserSettingsController.h"
@@ -35,13 +30,14 @@
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/SectionLoadHistory.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-public.h"
namespace lldb_private {
-extern OptionEnumValueElement g_dynamic_value_types[];
+OptionEnumValues GetDynamicValueTypes();
typedef enum InlineStrategy {
eInlineBreakpointsNever = 0,
@@ -61,6 +57,12 @@ typedef enum LoadCWDlldbinitFile {
eLoadCWDlldbinitWarn
} LoadCWDlldbinitFile;
+typedef enum LoadDependentFiles {
+ eLoadDependentsDefault,
+ eLoadDependentsYes,
+ eLoadDependentsNo,
+} LoadDependentFiles;
+
//----------------------------------------------------------------------
// TargetProperties
//----------------------------------------------------------------------
@@ -186,6 +188,10 @@ public:
void SetDisplayRuntimeSupportValues(bool b);
+ bool GetDisplayRecognizedArguments() const;
+
+ void SetDisplayRecognizedArguments(bool b);
+
const ProcessLaunchInfo &GetProcessLaunchInfo();
void SetProcessLaunchInfo(const ProcessLaunchInfo &launch_info);
@@ -196,6 +202,10 @@ public:
bool GetUseModernTypeLookup() const;
+ void SetRequireHardwareBreakpoints(bool b);
+
+ bool GetRequireHardwareBreakpoints() const;
+
private:
//------------------------------------------------------------------
// Callbacks for m_launch_info.
@@ -375,6 +385,10 @@ public:
bool GetAutoApplyFixIts() const { return m_auto_apply_fixits; }
+ bool IsForUtilityExpr() const { return m_running_utility_expression; }
+
+ void SetIsForUtilityExpr(bool b) { m_running_utility_expression = b; }
+
private:
ExecutionPolicy m_execution_policy = default_execution_policy;
lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
@@ -392,6 +406,10 @@ private:
bool m_ansi_color_errors = false;
bool m_result_is_internal = false;
bool m_auto_apply_fixits = true;
+ /// True if the executed code should be treated as utility code that is only
+ /// used by LLDB internally.
+ bool m_running_utility_expression = false;
+
lldb::DynamicValueType m_use_dynamic = lldb::eNoDynamicValues;
Timeout<std::micro> m_timeout = default_timeout;
Timeout<std::micro> m_one_thread_timeout = llvm::None;
@@ -515,7 +533,9 @@ public:
//------------------------------------------------------------------
void Dump(Stream *s, lldb::DescriptionLevel description_level);
- const lldb::ProcessSP &CreateProcess(lldb::ListenerSP listener,
+ // If listener_sp is null, the listener of the owning Debugger object will be
+ // used.
+ const lldb::ProcessSP &CreateProcess(lldb::ListenerSP listener_sp,
llvm::StringRef plugin_name,
const FileSpec *crash_file);
@@ -549,7 +569,7 @@ public:
// module it is nullptr
lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules,
const FileSpec &file, uint32_t line_no,
- lldb::addr_t offset,
+ uint32_t column, lldb::addr_t offset,
LazyBool check_inlines,
LazyBool skip_prologue, bool internal,
bool request_hardware,
@@ -594,14 +614,12 @@ public:
// eLazyBoolCalculate, we use the current target setting, else we use the
// values passed in. func_name_type_mask is or'ed values from the
// FunctionNameType enum.
- lldb::BreakpointSP CreateBreakpoint(const FileSpecList *containingModules,
- const FileSpecList *containingSourceFiles,
- const char *func_name,
- uint32_t func_name_type_mask,
- lldb::LanguageType language,
- lldb::addr_t offset,
- LazyBool skip_prologue, bool internal,
- bool request_hardware);
+ lldb::BreakpointSP CreateBreakpoint(
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles, const char *func_name,
+ lldb::FunctionNameType func_name_type_mask, lldb::LanguageType language,
+ lldb::addr_t offset, LazyBool skip_prologue, bool internal,
+ bool request_hardware);
lldb::BreakpointSP
CreateExceptionBreakpoint(enum lldb::LanguageType language, bool catch_bp,
@@ -609,25 +627,34 @@ public:
Args *additional_args = nullptr,
Status *additional_args_error = nullptr);
+ lldb::BreakpointSP
+ CreateScriptedBreakpoint(const llvm::StringRef class_name,
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ bool internal,
+ bool request_hardware,
+ StructuredData::ObjectSP extra_args_sp,
+ Status *creation_error = nullptr);
+
// 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 you
// already know. func_name_type_mask is or'ed values from the
// FunctionNameType enum.
- lldb::BreakpointSP
- CreateBreakpoint(const FileSpecList *containingModules,
- const FileSpecList *containingSourceFiles,
- const char *func_names[], size_t num_names,
- uint32_t func_name_type_mask, lldb::LanguageType language,
- lldb::addr_t offset, LazyBool skip_prologue, bool internal,
- bool request_hardware);
+ lldb::BreakpointSP CreateBreakpoint(
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles, const char *func_names[],
+ size_t num_names, lldb::FunctionNameType func_name_type_mask,
+ lldb::LanguageType language, lldb::addr_t offset, 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, lldb::LanguageType language,
- lldb::addr_t m_offset, LazyBool skip_prologue, bool internal,
+ lldb::FunctionNameType func_name_type_mask,
+ lldb::LanguageType language, lldb::addr_t m_offset,
+ LazyBool skip_prologue, bool internal,
bool request_hardware);
// Use this to create a general breakpoint:
@@ -665,7 +692,6 @@ public:
const BreakpointOptions &options,
const BreakpointName::Permissions &permissions);
void ApplyNameToBreakpoints(BreakpointName &bp_name);
-
// This takes ownership of the name obj passed in.
void AddBreakpointName(BreakpointName *bp_name);
@@ -753,9 +779,9 @@ public:
/// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
/// returned.
//------------------------------------------------------------------
- lldb::addr_t GetOpcodeLoadAddress(
- lldb::addr_t load_addr,
- AddressClass addr_class = AddressClass::eInvalid) const;
+ lldb::addr_t
+ GetOpcodeLoadAddress(lldb::addr_t load_addr,
+ AddressClass addr_class = AddressClass::eInvalid) const;
// Get load_addr as breakable load address for this target. Take a addr and
// check if for any reason there is a better address than this to put a
@@ -826,14 +852,16 @@ public:
/// A shared pointer reference to the module that will become
/// the main executable for this process.
///
- /// @param[in] get_dependent_files
+ /// @param[in] load_dependent_files
/// If \b true then ask the object files to track down any
/// known dependent files.
///
/// @see ObjectFile::GetDependentModules (FileSpecList&)
/// @see Process::GetImages()
//------------------------------------------------------------------
- void SetExecutableModule(lldb::ModuleSP &module_sp, bool get_dependent_files);
+ void SetExecutableModule(
+ lldb::ModuleSP &module_sp,
+ LoadDependentFiles load_dependent_files = eLoadDependentsDefault);
bool LoadScriptingResources(std::list<Status> &errors,
Stream *feedback_stream = nullptr,
@@ -913,28 +941,30 @@ public:
/// Set the architecture for this target.
///
/// If the current target has no Images read in, then this just sets the
- /// architecture, which will
- /// be used to select the architecture of the ExecutableModule when that is
- /// set.
- /// If the current target has an ExecutableModule, then calling
- /// SetArchitecture with a different
+ /// architecture, which will be used to select the architecture of the
+ /// ExecutableModule when that is set. If the current target has an
+ /// ExecutableModule, then calling SetArchitecture with a different
/// architecture from the currently selected one will reset the
- /// ExecutableModule to that slice
- /// of the file backing the ExecutableModule. If the file backing the
- /// ExecutableModule does not
- /// contain a fork of this architecture, then this code will return false, and
- /// the architecture
- /// won't be changed.
- /// If the input arch_spec is the same as the already set architecture, this
- /// is a no-op.
+ /// ExecutableModule to that slice of the file backing the ExecutableModule.
+ /// If the file backing the ExecutableModule does not contain a fork of this
+ /// architecture, then this code will return false, and the architecture
+ /// won't be changed. If the input arch_spec is the same as the already set
+ /// architecture, this is a no-op.
///
/// @param[in] arch_spec
/// The new architecture.
///
+ /// @param[in] set_platform
+ /// If \b true, then the platform will be adjusted if the currently
+ /// selected platform is not compatible with the archicture being set.
+ /// If \b false, then just the architecture will be set even if the
+ /// currently selected platform isn't compatible (in case it might be
+ /// manually set following this function call).
+ ///
/// @return
/// \b true if the architecture was successfully set, \bfalse otherwise.
//------------------------------------------------------------------
- bool SetArchitecture(const ArchSpec &arch_spec);
+ bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false);
bool MergeArchitecture(const ArchSpec &arch_spec);
@@ -1324,6 +1354,8 @@ private:
void AddBreakpoint(lldb::BreakpointSP breakpoint_sp, bool internal);
+ void FinalizeFileActions(ProcessLaunchInfo &info);
+
DISALLOW_COPY_AND_ASSIGN(Target);
};
diff --git a/include/lldb/Target/TargetList.h b/include/lldb/Target/TargetList.h
index 43f4520369b6..90c480745a0c 100644
--- a/include/lldb/Target/TargetList.h
+++ b/include/lldb/Target/TargetList.h
@@ -10,15 +10,11 @@
#ifndef liblldb_TargetList_h_
#define liblldb_TargetList_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Broadcaster.h"
namespace lldb_private {
@@ -92,7 +88,8 @@ public:
/// An error object that indicates success or failure
//------------------------------------------------------------------
Status CreateTarget(Debugger &debugger, llvm::StringRef user_exe_path,
- llvm::StringRef triple_str, bool get_dependent_modules,
+ llvm::StringRef triple_str,
+ LoadDependentFiles get_dependent_modules,
const OptionGroupPlatform *platform_options,
lldb::TargetSP &target_sp);
@@ -103,7 +100,8 @@ public:
/// platform you will be using
//------------------------------------------------------------------
Status CreateTarget(Debugger &debugger, llvm::StringRef user_exe_path,
- const ArchSpec &arch, bool get_dependent_modules,
+ const ArchSpec &arch,
+ LoadDependentFiles get_dependent_modules,
lldb::PlatformSP &platform_sp, lldb::TargetSP &target_sp);
//------------------------------------------------------------------
@@ -217,12 +215,13 @@ private:
Status CreateTargetInternal(Debugger &debugger, llvm::StringRef user_exe_path,
llvm::StringRef triple_str,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options,
lldb::TargetSP &target_sp, bool is_dummy_target);
Status CreateTargetInternal(Debugger &debugger, llvm::StringRef user_exe_path,
- const ArchSpec &arch, bool get_dependent_modules,
+ const ArchSpec &arch,
+ LoadDependentFiles get_dependent_modules,
lldb::PlatformSP &platform_sp,
lldb::TargetSP &target_sp, bool is_dummy_target);
diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h
index 9ce73e0cbeff..0d14b10c651f 100644
--- a/include/lldb/Target/Thread.h
+++ b/include/lldb/Target/Thread.h
@@ -10,21 +10,17 @@
#ifndef liblldb_Thread_h_
#define liblldb_Thread_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <mutex>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/RegisterCheckpoint.h"
#include "lldb/Target/StackFrameList.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
@@ -57,6 +53,8 @@ public:
bool GetStepInAvoidsNoDebug() const;
bool GetStepOutAvoidsNoDebug() const;
+
+ uint64_t GetMaxBacktraceDepth() const;
};
typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP;
@@ -282,7 +280,7 @@ public:
/// message).
//------------------------------------------------------------------
StructuredData::ObjectSP GetExtendedInfo() {
- if (m_extended_info_fetched == false) {
+ if (!m_extended_info_fetched) {
m_extended_info = FetchThreadExtendedInfo();
m_extended_info_fetched = true;
}
@@ -496,9 +494,9 @@ public:
// If stop_format is true, this will be the form used when we print stop
// info. If false, it will be the form we use for thread list and co.
- void DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
+ void DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx,
bool stop_format);
-
+
bool GetDescription(Stream &s, lldb::DescriptionLevel level,
bool print_json_thread, bool print_json_stopinfo);
@@ -655,12 +653,16 @@ public:
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @return
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads);
+ bool step_over, bool abort_other_plans, bool stop_other_threads,
+ Status &status);
//------------------------------------------------------------------
/// Queues the plan used to step through an address range, stepping over
@@ -690,6 +692,9 @@ public:
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @param[in] step_out_avoids_code_without_debug_info
/// If eLazyBoolYes, if the step over steps out it will continue to step
/// out till it comes to a frame with debug info.
@@ -702,6 +707,7 @@ public:
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
+ Status &status,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
// Helper function that takes a LineEntry to step, insted of an AddressRange.
@@ -710,6 +716,7 @@ public:
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
+ Status &status,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
//------------------------------------------------------------------
@@ -744,6 +751,9 @@ public:
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @param[in] step_in_avoids_code_without_debug_info
/// If eLazyBoolYes we will step out if we step into code with no debug
/// info.
@@ -761,7 +771,7 @@ public:
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_other_threads,
+ lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
@@ -771,7 +781,7 @@ public:
virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_other_threads,
+ lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
@@ -803,6 +813,9 @@ public:
/// @param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @param[in] step_out_avoids_code_without_debug_info
/// If eLazyBoolYes, if the step over steps out it will continue to step
/// out till it comes to a frame with debug info.
@@ -814,10 +827,8 @@ public:
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOut(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads,
- Vote stop_vote, // = eVoteYes,
- Vote run_vote, // = eVoteNoOpinion);
- uint32_t frame_idx,
+ bool stop_other_threads, Vote stop_vote, Vote run_vote,
+ uint32_t frame_idx, Status &status,
LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate);
//------------------------------------------------------------------
@@ -848,9 +859,15 @@ public:
/// \b true if we will stop other threads while we single step this one.
///
/// @param[in] stop_vote
+ ///
/// @param[in] run_vote
/// See standard meanings for the stop & run votes in ThreadPlan.h.
///
+ /// @param[in] frame_idx
+ ///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @param[in] continue_to_next_branch
/// Normally this will enqueue a plan that will put a breakpoint on the
/// return address and continue
@@ -874,16 +891,13 @@ public:
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP QueueThreadPlanForStepOutNoShouldStop(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
- bool stop_other_threads,
- Vote stop_vote, // = eVoteYes,
- Vote run_vote, // = eVoteNoOpinion);
- uint32_t frame_idx, bool continue_to_next_branch = false);
+ bool stop_other_threads, Vote stop_vote, Vote run_vote,
+ uint32_t frame_idx, Status &status, bool continue_to_next_branch = false);
//------------------------------------------------------------------
/// Gets the plan used to step through the code that steps from a function
/// call site at the current PC into the actual function call.
///
- ///
/// @param[in] return_stack_id
/// The stack id that we will return to (by setting backstop breakpoints on
/// the return
@@ -897,14 +911,17 @@ public:
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @return
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepThrough(StackID &return_stack_id,
- bool abort_other_plans,
- bool stop_other_threads);
+ bool abort_other_plans, bool stop_other_threads,
+ Status &status);
//------------------------------------------------------------------
/// Gets the plan used to continue from the current PC.
@@ -922,22 +939,24 @@ public:
/// @param[in] stop_other_threads
/// \b true if we will stop other threads while we single step this one.
///
+ /// @param[out] status
+ /// A status with an error if queuing failed.
+ ///
/// @return
/// A shared pointer to the newly queued thread plan, or nullptr if the
/// plan could not be queued.
//------------------------------------------------------------------
virtual lldb::ThreadPlanSP
QueueThreadPlanForRunToAddress(bool abort_other_plans, Address &target_addr,
- bool stop_other_threads);
+ bool stop_other_threads, Status &status);
- virtual lldb::ThreadPlanSP
- QueueThreadPlanForStepUntil(bool abort_other_plans,
- lldb::addr_t *address_list, size_t num_addresses,
- bool stop_others, uint32_t frame_idx);
+ virtual lldb::ThreadPlanSP QueueThreadPlanForStepUntil(
+ bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
+ bool stop_others, uint32_t frame_idx, Status &status);
virtual lldb::ThreadPlanSP
QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name,
- bool stop_other_threads);
+ bool stop_other_threads, Status &status);
//------------------------------------------------------------------
// Thread Plan accessors:
@@ -1023,7 +1042,7 @@ public:
/// false otherwise.
//------------------------------------------------------------------
bool CompletedPlanOverridesBreakpoint();
-
+
//------------------------------------------------------------------
/// Queues a generic thread plan.
///
@@ -1038,7 +1057,7 @@ public:
/// @return
/// A pointer to the last completed plan.
//------------------------------------------------------------------
- void QueueThreadPlan(lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
+ Status QueueThreadPlan(lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
//------------------------------------------------------------------
/// Discards the plans queued on the plan stack of the current thread. This
@@ -1234,6 +1253,10 @@ public:
//----------------------------------------------------------------------
virtual uint64_t GetExtendedBacktraceToken() { return LLDB_INVALID_ADDRESS; }
+ lldb::ValueObjectSP GetCurrentException();
+
+ lldb::ThreadSP GetCurrentExceptionBacktrace();
+
protected:
friend class ThreadPlan;
friend class ThreadList;
diff --git a/include/lldb/Target/ThreadPlan.h b/include/lldb/Target/ThreadPlan.h
index 7591fa9c9d07..15bc4c7656c3 100644
--- a/include/lldb/Target/ThreadPlan.h
+++ b/include/lldb/Target/ThreadPlan.h
@@ -10,13 +10,9 @@
#ifndef liblldb_ThreadPlan_h_
#define liblldb_ThreadPlan_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
@@ -600,10 +596,12 @@ protected:
bool IsUsuallyUnexplainedStopReason(lldb::StopReason);
+ Status m_status;
Thread &m_thread;
Vote m_stop_vote;
Vote m_run_vote;
- bool m_takes_iteration_count = false;
+ bool m_takes_iteration_count;
+ bool m_could_not_resolve_hw_bp;
int32_t m_iteration_count = 1;
private:
@@ -655,6 +653,8 @@ public:
bool OkayToDiscard() override { return false; }
+ const Status &GetStatus() { return m_status; }
+
protected:
bool DoPlanExplainsStop(Event *event_ptr) override;
diff --git a/include/lldb/Target/ThreadPlanBase.h b/include/lldb/Target/ThreadPlanBase.h
index 7a8b7eb20bb2..bcf20c5544bc 100644
--- a/include/lldb/Target/ThreadPlanBase.h
+++ b/include/lldb/Target/ThreadPlanBase.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanFundamental_h_
#define liblldb_ThreadPlanFundamental_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
diff --git a/include/lldb/Target/ThreadPlanCallFunction.h b/include/lldb/Target/ThreadPlanCallFunction.h
index 56bfc819320c..3bec86e370d1 100644
--- a/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/include/lldb/Target/ThreadPlanCallFunction.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanCallFunction_h_
#define liblldb_ThreadPlanCallFunction_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h b/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
index d58f7f050dbe..9b75da5fd2f8 100644
--- a/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
+++ b/include/lldb/Target/ThreadPlanCallFunctionUsingABI.h
@@ -11,10 +11,6 @@
#ifndef liblldb_ThreadPlanCallFunctionUsingABI_h_
#define liblldb_ThreadPlanCallFunctionUsingABI_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
diff --git a/include/lldb/Target/ThreadPlanCallUserExpression.h b/include/lldb/Target/ThreadPlanCallUserExpression.h
index 5fe80927ca21..ba1001ce5e91 100644
--- a/include/lldb/Target/ThreadPlanCallUserExpression.h
+++ b/include/lldb/Target/ThreadPlanCallUserExpression.h
@@ -11,10 +11,6 @@
#ifndef liblldb_ThreadPlanCallUserExpression_h_
#define liblldb_ThreadPlanCallUserExpression_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
diff --git a/include/lldb/Target/ThreadPlanPython.h b/include/lldb/Target/ThreadPlanPython.h
index 973c935b7c79..fc4cfb3bf0b4 100644
--- a/include/lldb/Target/ThreadPlanPython.h
+++ b/include/lldb/Target/ThreadPlanPython.h
@@ -11,12 +11,8 @@
#ifndef liblldb_ThreadPlan_Python_h_
#define liblldb_ThreadPlan_Python_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
@@ -63,6 +59,7 @@ protected:
private:
std::string m_class_name;
StructuredData::ObjectSP m_implementation_sp;
+ bool m_did_push;
DISALLOW_COPY_AND_ASSIGN(ThreadPlanPython);
};
diff --git a/include/lldb/Target/ThreadPlanRunToAddress.h b/include/lldb/Target/ThreadPlanRunToAddress.h
index 8e91fb9472a7..58608864d463 100644
--- a/include/lldb/Target/ThreadPlanRunToAddress.h
+++ b/include/lldb/Target/ThreadPlanRunToAddress.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ThreadPlanRunToAddress_h_
#define liblldb_ThreadPlanRunToAddress_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlan.h"
#include "lldb/lldb-private.h"
diff --git a/include/lldb/Target/ThreadPlanShouldStopHere.h b/include/lldb/Target/ThreadPlanShouldStopHere.h
index 030d5e434bd9..d3aca3e6f5c0 100644
--- a/include/lldb/Target/ThreadPlanShouldStopHere.h
+++ b/include/lldb/Target/ThreadPlanShouldStopHere.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanShouldStopHere_h_
#define liblldb_ThreadPlanShouldStopHere_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlan.h"
namespace lldb_private {
@@ -101,10 +97,12 @@ public:
void ClearShouldStopHereCallbacks() { m_callbacks.Clear(); }
- bool InvokeShouldStopHereCallback(lldb::FrameComparison operation);
+ bool InvokeShouldStopHereCallback(lldb::FrameComparison operation,
+ Status &status);
lldb::ThreadPlanSP
- CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation);
+ CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation,
+ Status &status);
lldb_private::Flags &GetFlags() { return m_flags; }
@@ -114,14 +112,16 @@ protected:
static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan,
Flags &flags,
lldb::FrameComparison operation,
- void *baton);
+ Status &status, void *baton);
static lldb::ThreadPlanSP
DefaultStepFromHereCallback(ThreadPlan *current_plan, Flags &flags,
- lldb::FrameComparison operation, void *baton);
+ lldb::FrameComparison operation, Status &status,
+ void *baton);
virtual lldb::ThreadPlanSP
- QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation);
+ QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation,
+ Status &status);
// Implement this, and call it in the plan's constructor to set the default
// flags.
diff --git a/include/lldb/Target/ThreadPlanStepInRange.h b/include/lldb/Target/ThreadPlanStepInRange.h
index c3116eac81b5..c13b3533af1c 100644
--- a/include/lldb/Target/ThreadPlanStepInRange.h
+++ b/include/lldb/Target/ThreadPlanStepInRange.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepInRange_h_
#define liblldb_ThreadPlanStepInRange_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/AddressRange.h"
#include "lldb/Target/StackID.h"
#include "lldb/Target/Thread.h"
@@ -58,7 +54,7 @@ protected:
static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan,
Flags &flags,
lldb::FrameComparison operation,
- void *baton);
+ Status &status, void *baton);
bool DoWillResume(lldb::StateType resume_state, bool current_plan) override;
@@ -80,11 +76,11 @@ private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_others,
- LazyBool avoid_code_without_debug_info);
+ Status &status, LazyBool avoid_code_without_debug_info);
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_others,
+ lldb::RunMode stop_others, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info);
diff --git a/include/lldb/Target/ThreadPlanStepInstruction.h b/include/lldb/Target/ThreadPlanStepInstruction.h
index 8b56e41ad64f..ea5d93fa4944 100644
--- a/include/lldb/Target/ThreadPlanStepInstruction.h
+++ b/include/lldb/Target/ThreadPlanStepInstruction.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepInstruction_h_
#define liblldb_ThreadPlanStepInstruction_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/lldb-private.h"
@@ -43,7 +39,8 @@ protected:
private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads);
+ bool step_over, bool abort_other_plans, bool stop_other_threads,
+ Status &status);
lldb::addr_t m_instruction_addr;
bool m_stop_other_threads;
diff --git a/include/lldb/Target/ThreadPlanStepOut.h b/include/lldb/Target/ThreadPlanStepOut.h
index 285f4cab13a2..8ef9f95d4f96 100644
--- a/include/lldb/Target/ThreadPlanStepOut.h
+++ b/include/lldb/Target/ThreadPlanStepOut.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepOut_h_
#define liblldb_ThreadPlanStepOut_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanShouldStopHere.h"
@@ -74,13 +70,14 @@ private:
// if ShouldStopHere told us
// to.
Function *m_immediate_step_from_function;
+ std::vector<lldb::StackFrameSP> m_stepped_past_frames;
lldb::ValueObjectSP m_return_valobj_sp;
bool m_calculate_return_value;
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepOut(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
bool stop_others, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info);
+ Status &status, LazyBool step_out_avoids_code_without_debug_info);
void SetupAvoidNoDebug(LazyBool step_out_avoids_code_without_debug_info);
// Need an appropriate marker for the current stack so we can tell step out
diff --git a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
index e799ec5a44ff..7aaf56ed7c0b 100644
--- a/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
+++ b/include/lldb/Target/ThreadPlanStepOverBreakpoint.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepOverBreakpoint_h_
#define liblldb_ThreadPlanStepOverBreakpoint_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
diff --git a/include/lldb/Target/ThreadPlanStepOverRange.h b/include/lldb/Target/ThreadPlanStepOverRange.h
index 84fdb0ddcf99..2eeb2bb96022 100644
--- a/include/lldb/Target/ThreadPlanStepOverRange.h
+++ b/include/lldb/Target/ThreadPlanStepOverRange.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepOverRange_h_
#define liblldb_ThreadPlanStepOverRange_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/AddressRange.h"
#include "lldb/Target/StackID.h"
#include "lldb/Target/Thread.h"
diff --git a/include/lldb/Target/ThreadPlanStepRange.h b/include/lldb/Target/ThreadPlanStepRange.h
index 65bc1671cb1e..b3e267a0827b 100644
--- a/include/lldb/Target/ThreadPlanStepRange.h
+++ b/include/lldb/Target/ThreadPlanStepRange.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepRange_h_
#define liblldb_ThreadPlanStepRange_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/AddressRange.h"
#include "lldb/Target/StackID.h"
#include "lldb/Target/Thread.h"
diff --git a/include/lldb/Target/ThreadPlanStepThrough.h b/include/lldb/Target/ThreadPlanStepThrough.h
index 41aa7b21abe0..1bff541e7df6 100644
--- a/include/lldb/Target/ThreadPlanStepThrough.h
+++ b/include/lldb/Target/ThreadPlanStepThrough.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepThrough_h_
#define liblldb_ThreadPlanStepThrough_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -45,10 +41,9 @@ protected:
private:
friend lldb::ThreadPlanSP
-
Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
bool abort_other_plans,
- bool stop_others);
+ bool stop_others, Status &status);
void ClearBackstopBreakpoint();
diff --git a/include/lldb/Target/ThreadPlanStepUntil.h b/include/lldb/Target/ThreadPlanStepUntil.h
index bdc630bcf8de..33ccc0fa0d54 100644
--- a/include/lldb/Target/ThreadPlanStepUntil.h
+++ b/include/lldb/Target/ThreadPlanStepUntil.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadPlanStepUntil_h_
#define liblldb_ThreadPlanStepUntil_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -59,7 +55,7 @@ private:
friend lldb::ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
- bool stop_others, uint32_t frame_idx);
+ bool stop_others, uint32_t frame_idx, Status &status);
// Need an appropriate marker for the current stack so we can tell step out
// from step in.
diff --git a/include/lldb/Target/ThreadPlanTracer.h b/include/lldb/Target/ThreadPlanTracer.h
index 65115383efaa..21f9023f8d57 100644
--- a/include/lldb/Target/ThreadPlanTracer.h
+++ b/include/lldb/Target/ThreadPlanTracer.h
@@ -11,13 +11,9 @@
#ifndef liblldb_ThreadPlanTracer_h_
#define liblldb_ThreadPlanTracer_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Symbol/TaggedASTType.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
diff --git a/include/lldb/Target/UnixSignals.h b/include/lldb/Target/UnixSignals.h
index 7ec683585f8e..8774139371f0 100644
--- a/include/lldb/Target/UnixSignals.h
+++ b/include/lldb/Target/UnixSignals.h
@@ -10,14 +10,10 @@
#ifndef lldb_UnixSignals_h_
#define lldb_UnixSignals_h_
-// C Includes
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/Optional.h"
diff --git a/include/lldb/Target/Unwind.h b/include/lldb/Target/Unwind.h
index a50e8d4a7bdd..9e0da9ed553b 100644
--- a/include/lldb/Target/Unwind.h
+++ b/include/lldb/Target/Unwind.h
@@ -10,12 +10,8 @@
#ifndef liblldb_Unwind_h_
#define liblldb_Unwind_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
namespace lldb_private {
diff --git a/include/lldb/Utility/ArchSpec.h b/include/lldb/Utility/ArchSpec.h
index 680e9b1b9ea6..e84cbbbe5efa 100644
--- a/include/lldb/Utility/ArchSpec.h
+++ b/include/lldb/Utility/ArchSpec.h
@@ -15,11 +15,11 @@
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private-enumerations.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include <cstddef> // for size_t
-#include <cstdint> // for uint32_t
-#include <string> // for string
+#include <cstddef>
+#include <cstdint>
+#include <string>
namespace lldb_private {
@@ -371,6 +371,7 @@ public:
bool IsValid() const {
return m_core >= eCore_arm_generic && m_core < kNumCores;
}
+ explicit operator bool() const { return IsValid(); }
bool TripleVendorWasSpecified() const {
return !m_triple.getVendorName().empty();
diff --git a/include/lldb/Utility/Baton.h b/include/lldb/Utility/Baton.h
index 59999e4697fa..7477846be48b 100644
--- a/include/lldb/Utility/Baton.h
+++ b/include/lldb/Utility/Baton.h
@@ -10,10 +10,10 @@
#ifndef lldb_Baton_h_
#define lldb_Baton_h_
-#include "lldb/lldb-enumerations.h" // for DescriptionLevel
+#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
-#include <memory> // for unique_ptr
+#include <memory>
namespace lldb_private {
class Stream;
diff --git a/include/lldb/Core/Broadcaster.h b/include/lldb/Utility/Broadcaster.h
index 4851007c9a2a..8763a63b0d5e 100644
--- a/include/lldb/Core/Broadcaster.h
+++ b/include/lldb/Utility/Broadcaster.h
@@ -7,22 +7,22 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Broadcaster_h_
-#define liblldb_Broadcaster_h_
+#ifndef LLDB_UTILITY_BROADCASTER_H
+#define LLDB_UTILITY_BROADCASTER_H
#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-forward.h" // for ListenerSP, EventSP, Broadcast...
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
#include "llvm/ADT/SmallVector.h"
-#include <cstdint> // for uint32_t, UINT32_MAX
+#include <cstdint>
#include <map>
-#include <memory> // for shared_ptr, operator==, enable...
+#include <memory>
#include <mutex>
-#include <set> // for set
+#include <set>
#include <string>
-#include <utility> // for pair
+#include <utility>
#include <vector>
namespace lldb_private {
@@ -223,7 +223,7 @@ private:
};
//----------------------------------------------------------------------
-/// @class Broadcaster Broadcaster.h "lldb/Core/Broadcaster.h" An event
+/// @class Broadcaster Broadcaster.h "lldb/Utility/Broadcaster.h" An event
/// broadcasting class.
///
/// The Broadcaster class is designed to be subclassed by objects that wish to
@@ -595,4 +595,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Broadcaster_h_
+#endif // LLDB_UTILITY_BROADCASTER_H
diff --git a/include/lldb/Utility/CompletionRequest.h b/include/lldb/Utility/CompletionRequest.h
index ef75474813e0..38d8d5c587e2 100644
--- a/include/lldb/Utility/CompletionRequest.h
+++ b/include/lldb/Utility/CompletionRequest.h
@@ -11,11 +11,50 @@
#define LLDB_UTILITY_COMPLETIONREQUEST_H
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/StringList.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
namespace lldb_private {
+class CompletionResult {
+ //----------------------------------------------------------
+ /// A single completion and all associated data.
+ //----------------------------------------------------------
+ struct Completion {
+ Completion(llvm::StringRef completion, llvm::StringRef description)
+ : m_completion(completion.str()), m_descripton(description.str()) {}
+
+ std::string m_completion;
+ std::string m_descripton;
+
+ /// Generates a string that uniquely identifies this completion result.
+ std::string GetUniqueKey() const;
+ };
+ std::vector<Completion> m_results;
+
+ /// List of added completions so far. Used to filter out duplicates.
+ llvm::StringSet<> m_added_values;
+
+public:
+ void AddResult(llvm::StringRef completion, llvm::StringRef description);
+
+ //----------------------------------------------------------
+ /// Adds all collected completion matches to the given list.
+ /// The list will be cleared before the results are added. The number of
+ /// results here is guaranteed to be equal to GetNumberOfResults().
+ //----------------------------------------------------------
+ void GetMatches(StringList &matches) const;
+
+ //----------------------------------------------------------
+ /// Adds all collected completion descriptions to the given list.
+ /// The list will be cleared before the results are added. The number of
+ /// results here is guaranteed to be equal to GetNumberOfResults().
+ //----------------------------------------------------------
+ void GetDescriptions(StringList &descriptions) const;
+
+ std::size_t GetNumberOfResults() const { return m_results.size(); }
+};
//----------------------------------------------------------------------
/// @class CompletionRequest CompletionRequest.h
@@ -46,13 +85,13 @@ public:
/// completion from match_start_point, and return match_return_elements
/// elements.
///
- /// @param [out] matches
- /// A list of matches that will be filled by the different completion
- /// handlers.
+ /// @param [out] result
+ /// The CompletionResult that will be filled with the results after this
+ /// request has been handled.
//----------------------------------------------------------
CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos,
int match_start_point, int max_return_elements,
- StringList &matches);
+ CompletionResult &result);
llvm::StringRef GetRawLine() const { return m_command; }
@@ -84,10 +123,11 @@ public:
/// afterwards.
///
/// @param match The suggested completion.
- void AddCompletion(llvm::StringRef completion) {
- // Add the completion if we haven't seen the same value before.
- if (m_match_set.insert(completion).second)
- m_matches->AppendString(completion);
+ /// @param match An optional description of the completion string. The
+ /// description will be displayed to the user alongside the completion.
+ void AddCompletion(llvm::StringRef completion,
+ llvm::StringRef description = "") {
+ m_result.AddResult(completion, description);
}
/// Adds multiple possible completion strings.
@@ -100,7 +140,25 @@ public:
AddCompletion(completions.GetStringAtIndex(i));
}
- std::size_t GetNumberOfMatches() const { return m_matches->GetSize(); }
+ /// Adds multiple possible completion strings alongside their descriptions.
+ ///
+ /// The number of completions and descriptions must be identical.
+ ///
+ /// \param completions The list of completions.
+ /// \param completions The list of descriptions.
+ ///
+ /// @see AddCompletion
+ void AddCompletions(const StringList &completions,
+ const StringList &descriptions) {
+ lldbassert(completions.GetSize() == descriptions.GetSize());
+ for (std::size_t i = 0; i < completions.GetSize(); ++i)
+ AddCompletion(completions.GetStringAtIndex(i),
+ descriptions.GetStringAtIndex(i));
+ }
+
+ std::size_t GetNumberOfMatches() const {
+ return m_result.GetNumberOfResults();
+ }
llvm::StringRef GetCursorArgument() const {
return GetParsedLine().GetArgumentAtIndex(GetCursorIndex());
@@ -134,14 +192,11 @@ private:
/// after the completion.) \bfalse otherwise.
bool m_word_complete = false;
- // Note: This list is kept private. This is by design to prevent that any
- // completion depends on any already computed completion from another backend.
- // Note: We don't own the list. It's owned by the creator of the
- // CompletionRequest object.
- StringList *m_matches;
-
- /// List of added completions so far. Used to filter out duplicates.
- llvm::StringSet<> m_match_set;
+ /// The result this request is supposed to fill out.
+ /// We keep this object private to ensure that no backend can in any way
+ /// depend on already calculated completions (which would make debugging and
+ /// testing them much more complicated).
+ CompletionResult &m_result;
};
} // namespace lldb_private
diff --git a/include/lldb/Utility/Connection.h b/include/lldb/Utility/Connection.h
index 1b0801378f84..074b44b36865 100644
--- a/include/lldb/Utility/Connection.h
+++ b/include/lldb/Utility/Connection.h
@@ -10,16 +10,16 @@
#ifndef liblldb_Connection_h_
#define liblldb_Connection_h_
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ConnectionStatus
-#include "lldb/lldb-forward.h" // for IOObjectSP
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
-#include <ratio> // for micro
+#include <ratio>
#include <string>
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class Status;
diff --git a/include/lldb/Utility/ConstString.h b/include/lldb/Utility/ConstString.h
index 98b3447abe3e..41f6717edee9 100644
--- a/include/lldb/Utility/ConstString.h
+++ b/include/lldb/Utility/ConstString.h
@@ -11,9 +11,9 @@
#define liblldb_ConstString_h_
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FormatVariadic.h" // for format_provider
+#include "llvm/Support/FormatVariadic.h"
-#include <stddef.h> // for size_t
+#include <stddef.h>
namespace lldb_private {
class Stream;
@@ -253,7 +253,7 @@ public:
//------------------------------------------------------------------
/// Clear this object's state.
///
- /// Clear any contained string and reset the value to the an empty string
+ /// Clear any contained string and reset the value to the empty string
/// value.
//------------------------------------------------------------------
void Clear() { m_string = nullptr; }
@@ -346,6 +346,15 @@ public:
bool IsEmpty() const { return m_string == nullptr || m_string[0] == '\0'; }
//------------------------------------------------------------------
+ /// Test for null string.
+ ///
+ /// @return
+ /// @li \b true if there is no string associated with this instance.
+ /// @li \b false if there is a string associated with this instance.
+ //------------------------------------------------------------------
+ bool IsNull() const { return m_string == nullptr; }
+
+ //------------------------------------------------------------------
/// Set the C string value.
///
/// Set the string value in the object by uniquing the \a cstr string value
@@ -373,15 +382,14 @@ public:
/// them.
///
/// @param[in] demangled
- /// The demangled C string to correlate with the \a mangled
- /// name.
+ /// The demangled string to correlate with the \a mangled name.
///
/// @param[in] mangled
/// The already uniqued mangled ConstString to correlate the
/// soon to be uniqued version of \a demangled.
//------------------------------------------------------------------
- void SetCStringWithMangledCounterpart(const char *demangled,
- const ConstString &mangled);
+ void SetStringWithMangledCounterpart(llvm::StringRef demangled,
+ const ConstString &mangled);
//------------------------------------------------------------------
/// Retrieve the mangled or demangled counterpart for a mangled or demangled
diff --git a/include/lldb/Utility/DataBufferHeap.h b/include/lldb/Utility/DataBufferHeap.h
index d64e5b7563a9..5a1e98803f0a 100644
--- a/include/lldb/Utility/DataBufferHeap.h
+++ b/include/lldb/Utility/DataBufferHeap.h
@@ -11,10 +11,10 @@
#define liblldb_DataBufferHeap_h_
#include "lldb/Utility/DataBuffer.h"
-#include "lldb/lldb-types.h" // for offset_t
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringRef.h"
-#include <cstdint> // for uint8_t, uint64_t
+#include <cstdint>
#include <vector>
namespace lldb_private {
@@ -90,7 +90,8 @@ public:
/// Set the number of bytes in the data buffer.
///
/// Sets the number of bytes that this object should be able to contain.
- /// This can be used prior to copying data into the buffer.
+ /// This can be used prior to copying data into the buffer. Note that this
+ /// zero-initializes up to \p byte_size bytes.
///
/// @param[in] byte_size
/// The new size in bytes that this data buffer should attempt
diff --git a/include/lldb/Utility/DataBufferLLVM.h b/include/lldb/Utility/DataBufferLLVM.h
index d76582cbf47c..947ddb54da4a 100644
--- a/include/lldb/Utility/DataBufferLLVM.h
+++ b/include/lldb/Utility/DataBufferLLVM.h
@@ -11,10 +11,10 @@
#define LLDB_CORE_DATABUFFERLLVM_H
#include "lldb/Utility/DataBuffer.h"
-#include "lldb/lldb-types.h" // for offset_t
+#include "lldb/lldb-types.h"
#include <memory>
-#include <stdint.h> // for uint8_t, uint64_t
+#include <stdint.h>
namespace llvm {
class WritableMemoryBuffer;
@@ -23,16 +23,11 @@ class Twine;
namespace lldb_private {
+class FileSystem;
class DataBufferLLVM : public DataBuffer {
public:
~DataBufferLLVM();
- static std::shared_ptr<DataBufferLLVM>
- CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size, uint64_t Offset);
-
- static std::shared_ptr<DataBufferLLVM>
- CreateFromPath(const llvm::Twine &Path);
-
uint8_t *GetBytes() override;
const uint8_t *GetBytes() const override;
lldb::offset_t GetByteSize() const override;
@@ -40,6 +35,7 @@ public:
char *GetChars() { return reinterpret_cast<char *>(GetBytes()); }
private:
+ friend FileSystem;
/// Construct a DataBufferLLVM from \p Buffer. \p Buffer must be a valid
/// pointer.
explicit DataBufferLLVM(std::unique_ptr<llvm::WritableMemoryBuffer> Buffer);
diff --git a/include/lldb/Utility/DataEncoder.h b/include/lldb/Utility/DataEncoder.h
index c1214705c726..b1ee5a599983 100644
--- a/include/lldb/Utility/DataEncoder.h
+++ b/include/lldb/Utility/DataEncoder.h
@@ -12,12 +12,12 @@
#if defined(__cplusplus)
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-enumerations.h" // for ByteOrder
-#include "lldb/lldb-forward.h" // for DataBufferSP
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
-#include <stddef.h> // for size_t
+#include <stddef.h>
#include <stdint.h>
namespace lldb_private {
diff --git a/include/lldb/Utility/DataExtractor.h b/include/lldb/Utility/DataExtractor.h
index 50c88db8e358..f1e15e6d00e3 100644
--- a/include/lldb/Utility/DataExtractor.h
+++ b/include/lldb/Utility/DataExtractor.h
@@ -11,9 +11,10 @@
#define LLDB_UTILITY_DATAEXTRACTOR_H
#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h" // for ByteOrder
-#include "lldb/lldb-forward.h" // for DataBufferSP
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
#include "lldb/lldb-types.h"
+#include "llvm/ADT/ArrayRef.h"
#include <cassert>
#include <stdint.h>
@@ -29,7 +30,6 @@ namespace llvm {
template <typename T> class SmallVectorImpl;
}
-// C++ Includes
namespace lldb_private {
@@ -1095,6 +1095,10 @@ public:
void Checksum(llvm::SmallVectorImpl<uint8_t> &dest, uint64_t max_data = 0);
+ llvm::ArrayRef<uint8_t> GetData() const {
+ return {GetDataStart(), size_t(GetByteSize())};
+ }
+
protected:
//------------------------------------------------------------------
// Member variables
diff --git a/include/lldb/Utility/Either.h b/include/lldb/Utility/Either.h
deleted file mode 100644
index 0dc340b64e86..000000000000
--- a/include/lldb/Utility/Either.h
+++ /dev/null
@@ -1,126 +0,0 @@
-//===-- Either.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_Either_h_
-#define liblldb_Either_h_
-
-#include "llvm/ADT/Optional.h"
-
-#include <functional>
-
-namespace lldb_utility {
-template <typename T1, typename T2> class Either {
-private:
- enum class Selected { One, Two };
-
- Selected m_selected;
- union {
- T1 m_t1;
- T2 m_t2;
- };
-
-public:
- Either(const T1 &t1) {
- m_t1 = t1;
- m_selected = Selected::One;
- }
-
- Either(const T2 &t2) {
- m_t2 = t2;
- m_selected = Selected::Two;
- }
-
- Either(const Either<T1, T2> &rhs) {
- switch (rhs.m_selected) {
- case Selected::One:
- m_t1 = rhs.GetAs<T1>().getValue();
- m_selected = Selected::One;
- break;
- case Selected::Two:
- m_t2 = rhs.GetAs<T2>().getValue();
- m_selected = Selected::Two;
- break;
- }
- }
-
- template <class X, typename std::enable_if<std::is_same<T1, X>::value>::type
- * = nullptr>
- llvm::Optional<T1> GetAs() const {
- switch (m_selected) {
- case Selected::One:
- return m_t1;
- default:
- return llvm::Optional<T1>();
- }
- }
-
- template <class X, typename std::enable_if<std::is_same<T2, X>::value>::type
- * = nullptr>
- llvm::Optional<T2> GetAs() const {
- switch (m_selected) {
- case Selected::Two:
- return m_t2;
- default:
- return llvm::Optional<T2>();
- }
- }
-
- template <class ResultType>
- ResultType Apply(std::function<ResultType(T1)> if_T1,
- std::function<ResultType(T2)> if_T2) const {
- switch (m_selected) {
- case Selected::One:
- return if_T1(m_t1);
- case Selected::Two:
- return if_T2(m_t2);
- }
- }
-
- bool operator==(const Either<T1, T2> &rhs) {
- return (GetAs<T1>() == rhs.GetAs<T1>()) && (GetAs<T2>() == rhs.GetAs<T2>());
- }
-
- explicit operator bool() {
- switch (m_selected) {
- case Selected::One:
- return (bool)m_t1;
- case Selected::Two:
- return (bool)m_t2;
- }
- }
-
- Either<T1, T2> &operator=(const Either<T1, T2> &rhs) {
- switch (rhs.m_selected) {
- case Selected::One:
- m_t1 = rhs.GetAs<T1>().getValue();
- m_selected = Selected::One;
- break;
- case Selected::Two:
- m_t2 = rhs.GetAs<T2>().getValue();
- m_selected = Selected::Two;
- break;
- }
- return *this;
- }
-
- ~Either() {
- switch (m_selected) {
- case Selected::One:
- m_t1.T1::~T1();
- break;
- case Selected::Two:
- m_t2.T2::~T2();
- break;
- }
- }
-};
-
-} // namespace lldb_utility
-
-#endif // #ifndef liblldb_Either_h_
diff --git a/include/lldb/Core/Event.h b/include/lldb/Utility/Event.h
index fa3017057675..d65043f564fb 100644
--- a/include/lldb/Core/Event.h
+++ b/include/lldb/Utility/Event.h
@@ -7,24 +7,24 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Event_h_
-#define liblldb_Event_h_
+#ifndef LLDB_UTILITY_EVENT_H
+#define LLDB_UTILITY_EVENT_H
-#include "lldb/Core/Broadcaster.h"
-#include "lldb/Host/Predicate.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/StructuredData.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-forward.h" // for EventDataSP, ProcessSP, Struct...
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include <chrono>
#include <memory>
#include <string>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class Event;
@@ -271,4 +271,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Event_h_
+#endif // LLDB_UTILITY_EVENT_H
diff --git a/include/lldb/Utility/FastDemangle.h b/include/lldb/Utility/FastDemangle.h
deleted file mode 100644
index f779aaa04606..000000000000
--- a/include/lldb/Utility/FastDemangle.h
+++ /dev/null
@@ -1,26 +0,0 @@
-//===-- FastDemangle.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_FastDemangle_h_
-#define liblldb_FastDemangle_h_
-
-#include <cstddef>
-
-#include <functional>
-
-namespace lldb_private {
-
-char *FastDemangle(const char *mangled_name);
-
-char *
-FastDemangle(const char *mangled_name, size_t mangled_name_length,
- std::function<void(const char *s)> primitive_type_hook = nullptr);
-}
-
-#endif
diff --git a/include/lldb/Utility/FileSpec.h b/include/lldb/Utility/FileSpec.h
index d062ba598ccc..0699ab7b5c90 100644
--- a/include/lldb/Utility/FileSpec.h
+++ b/include/lldb/Utility/FileSpec.h
@@ -10,13 +10,9 @@
#ifndef liblldb_FileSpec_h_
#define liblldb_FileSpec_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "llvm/ADT/StringRef.h"
@@ -24,8 +20,8 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class Stream;
@@ -70,23 +66,19 @@ public:
///
/// Takes a path to a file which can be just a filename, or a full path. If
/// \a path is not nullptr or empty, this function will call
- /// FileSpec::SetFile (const char *path, bool resolve).
+ /// FileSpec::SetFile (const char *path).
///
/// @param[in] path
/// The full or partial path to a file.
///
- /// @param[in] resolve_path
- /// If \b true, then we resolve the path, removing stray ../.. and so
- /// forth,
- /// if \b false we trust the path is in canonical form already.
+ /// @param[in] style
+ /// The style of the path
///
- /// @see FileSpec::SetFile (const char *path, bool resolve)
+ /// @see FileSpec::SetFile (const char *path)
//------------------------------------------------------------------
- explicit FileSpec(llvm::StringRef path, bool resolve_path,
- Style style = Style::native);
+ explicit FileSpec(llvm::StringRef path, Style style = Style::native);
- explicit FileSpec(llvm::StringRef path, bool resolve_path,
- const llvm::Triple &Triple);
+ explicit FileSpec(llvm::StringRef path, const llvm::Triple &Triple);
//------------------------------------------------------------------
/// Copy constructor
@@ -272,47 +264,6 @@ public:
//------------------------------------------------------------------
void Dump(Stream *s) const;
- //------------------------------------------------------------------
- /// Existence test.
- ///
- /// @return
- /// \b true if the file exists on disk, \b false otherwise.
- //------------------------------------------------------------------
- bool Exists() const;
-
- //------------------------------------------------------------------
- /// Check if a file is readable by the current user
- ///
- /// @return
- /// \b true if the file exists on disk and is readable, \b false
- /// otherwise.
- //------------------------------------------------------------------
- bool Readable() const;
-
- //------------------------------------------------------------------
- /// Expanded existence test.
- ///
- /// Call into the Host to see if it can help find the file (e.g. by
- /// searching paths set in the environment, etc.).
- ///
- /// If found, sets the value of m_directory to the directory where the file
- /// was found.
- ///
- /// @return
- /// \b true if was able to find the file using expanded search
- /// methods, \b false otherwise.
- //------------------------------------------------------------------
- bool ResolveExecutableLocation();
-
- //------------------------------------------------------------------
- /// Canonicalize this file path (basically running the static
- /// FileSpec::Resolve method on it). Useful if you asked us not to resolve
- /// the file path when you set the file.
- //------------------------------------------------------------------
- bool ResolvePath();
-
- uint64_t GetByteSize() const;
-
Style GetPathStyle() const;
//------------------------------------------------------------------
@@ -375,6 +326,9 @@ public:
//------------------------------------------------------------------
bool IsAbsolute() const;
+ /// Temporary helper for FileSystem change.
+ void SetPath(llvm::StringRef p) { SetFile(p); }
+
//------------------------------------------------------------------
/// Extract the full path to the file.
///
@@ -450,19 +404,6 @@ public:
ConstString GetFileNameStrippingExtension() const;
//------------------------------------------------------------------
- /// Return the current permissions of the path.
- ///
- /// Returns a bitmask for the current permissions of the file ( zero or more
- /// of the permission bits defined in File::Permissions).
- ///
- /// @return
- /// Zero if the file doesn't exist or we are unable to get
- /// information for the file, otherwise one or more permission
- /// bits from the File::Permissions enumeration.
- //------------------------------------------------------------------
- uint32_t GetPermissions() const;
-
- //------------------------------------------------------------------
/// Get the memory cost of this object.
///
/// Return the size in bytes that this object takes in memory. This returns
@@ -490,10 +431,9 @@ public:
/// If \b true, then we will try to resolve links the path using
/// the static FileSpec::Resolve.
//------------------------------------------------------------------
- void SetFile(llvm::StringRef path, bool resolve_path, Style style);
+ void SetFile(llvm::StringRef path, Style style);
- void SetFile(llvm::StringRef path, bool resolve_path,
- const llvm::Triple &Triple);
+ void SetFile(llvm::StringRef path, const llvm::Triple &Triple);
bool IsResolved() const { return m_is_resolved; }
@@ -512,16 +452,6 @@ public:
//------------------------------------------------------------------
void SetIsResolved(bool is_resolved) { m_is_resolved = is_resolved; }
- //------------------------------------------------------------------
- /// Resolves user name and links in \a path, and overwrites the input
- /// argument with the resolved path.
- ///
- /// @param[in] path
- /// Input path to be resolved, in the form of a llvm::SmallString or
- /// similar.
- //------------------------------------------------------------------
- static void Resolve(llvm::SmallVectorImpl<char> &path);
-
FileSpec CopyByAppendingPathComponent(llvm::StringRef component) const;
FileSpec CopyByRemovingLastPathComponent() const;
@@ -542,32 +472,11 @@ public:
ConstString GetLastPathComponent() const;
- enum EnumerateDirectoryResult {
- eEnumerateDirectoryResultNext, // Enumerate next entry in the current
- // directory
- eEnumerateDirectoryResultEnter, // Recurse into the current entry if it is a
- // directory or symlink, or next if not
- eEnumerateDirectoryResultQuit // Stop directory enumerations at any level
- };
-
- typedef EnumerateDirectoryResult (*EnumerateDirectoryCallbackType)(
- void *baton, llvm::sys::fs::file_type file_type, const FileSpec &spec);
-
- static void EnumerateDirectory(llvm::StringRef dir_path,
- bool find_directories, bool find_files,
- bool find_other,
- EnumerateDirectoryCallbackType callback,
- void *callback_baton);
-
- typedef std::function<EnumerateDirectoryResult(
- llvm::sys::fs::file_type file_type, const FileSpec &spec)>
- DirectoryCallback;
-
protected:
//------------------------------------------------------------------
// Convenience method for setting the file without changing the style.
//------------------------------------------------------------------
- void SetFile(llvm::StringRef path, bool resolve_path);
+ void SetFile(llvm::StringRef path);
//------------------------------------------------------------------
// Member variables
diff --git a/include/lldb/Utility/Iterable.h b/include/lldb/Utility/Iterable.h
index dcb340a05ef1..1b7ec89d6cf5 100644
--- a/include/lldb/Utility/Iterable.h
+++ b/include/lldb/Utility/Iterable.h
@@ -10,12 +10,8 @@
#ifndef liblldb_Iterable_h_
#define liblldb_Iterable_h_
-// C Includes
-// C++ Includes
#include <utility>
-// Other libraries and framework includes
-// Project includes
namespace lldb_private {
diff --git a/include/lldb/Utility/LLDBAssert.h b/include/lldb/Utility/LLDBAssert.h
index 9d9f3ceefab0..e7448cdac545 100644
--- a/include/lldb/Utility/LLDBAssert.h
+++ b/include/lldb/Utility/LLDBAssert.h
@@ -14,7 +14,8 @@
#define lldbassert(x) assert(x)
#else
#define lldbassert(x) \
- lldb_private::lldb_assert(x, #x, __FUNCTION__, __FILE__, __LINE__)
+ lldb_private::lldb_assert(static_cast<bool>(x), #x, __FUNCTION__, __FILE__, \
+ __LINE__)
#endif
namespace lldb_private {
diff --git a/include/lldb/Core/Listener.h b/include/lldb/Utility/Listener.h
index 3d12f8fb3391..11f89d7aeec2 100644
--- a/include/lldb/Core/Listener.h
+++ b/include/lldb/Utility/Listener.h
@@ -7,25 +7,25 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Select_h_
-#define liblldb_Select_h_
+#ifndef LLDB_UTILITY_LISTENER_H
+#define LLDB_UTILITY_LISTENER_H
-#include "lldb/Core/Broadcaster.h" // for Broadcaster::BroadcasterImplWP
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Timeout.h"
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
-#include "lldb/lldb-forward.h" // for BroadcasterManagerWP, EventSP
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
#include <condition_variable>
#include <list>
#include <map>
-#include <memory> // for owner_less, enable_shared_from_this
+#include <memory>
#include <mutex>
-#include <ratio> // for micro
+#include <ratio>
#include <string>
#include <vector>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
class ConstString;
@@ -158,4 +158,4 @@ private:
} // namespace lldb_private
-#endif // liblldb_Select_h_
+#endif // LLDB_UTILITY_LISTENER_H
diff --git a/include/lldb/Utility/Log.h b/include/lldb/Utility/Log.h
index 62776bdb281b..30b97f0137ef 100644
--- a/include/lldb/Utility/Log.h
+++ b/include/lldb/Utility/Log.h
@@ -15,8 +15,8 @@
#include "lldb/lldb-defines.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringMap.h" // for StringMap
-#include "llvm/ADT/StringRef.h" // for StringRef, StringLiteral
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/ManagedStatic.h"
@@ -25,9 +25,9 @@
#include <atomic>
#include <cstdarg>
#include <cstdint>
-#include <memory> // for shared_ptr
-#include <string> // for string
-#include <type_traits> // for forward
+#include <memory>
+#include <string>
+#include <type_traits>
namespace llvm {
class raw_ostream;
diff --git a/include/lldb/Host/Predicate.h b/include/lldb/Utility/Predicate.h
index d8128e71c53e..d05f17131c68 100644
--- a/include/lldb/Host/Predicate.h
+++ b/include/lldb/Utility/Predicate.h
@@ -10,16 +10,12 @@
#ifndef liblldb_Predicate_h_
#define liblldb_Predicate_h_
-// C Includes
#include <stdint.h>
#include <time.h>
-// C++ Includes
#include <condition_variable>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Timeout.h"
#include "lldb/lldb-defines.h"
@@ -34,11 +30,11 @@ typedef enum {
eBroadcastNever, ///< No broadcast will be sent when the value is modified.
eBroadcastAlways, ///< Always send a broadcast when the value is modified.
eBroadcastOnChange ///< Only broadcast if the value changes when the value is
- ///modified.
+ /// modified.
} PredicateBroadcastType;
//----------------------------------------------------------------------
-/// @class Predicate Predicate.h "lldb/Host/Predicate.h"
+/// @class Predicate Predicate.h "lldb/Utility/Predicate.h"
/// A C++ wrapper class for providing threaded access to a value of
/// type T.
///
@@ -220,8 +216,8 @@ protected:
T m_value; ///< The templatized value T that we are protecting access to
mutable std::mutex m_mutex; ///< The mutex to use when accessing the data
std::condition_variable m_condition; ///< The pthread condition variable to
- ///use for signaling that data available
- ///or changed.
+ /// use for signaling that data available
+ /// or changed.
private:
//------------------------------------------------------------------
diff --git a/include/lldb/Utility/Range.h b/include/lldb/Utility/Range.h
deleted file mode 100644
index 60880dbdbc87..000000000000
--- a/include/lldb/Utility/Range.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//===--------------------- Range.h ------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef utility_Range_h_
-#define utility_Range_h_
-
-#include <stdint.h>
-
-namespace lldb_utility {
-
-class Range {
-public:
- typedef uint64_t ValueType;
-
- static const ValueType OPEN_END = UINT64_MAX;
-
- Range(const Range &rng);
-
- Range(ValueType low = 0, ValueType high = OPEN_END);
-
- Range &operator=(const Range &rhs);
-
- ValueType GetLow() { return m_low; }
-
- ValueType GetHigh() { return m_high; }
-
- void SetLow(ValueType low) { m_low = low; }
-
- void SetHigh(ValueType high) { m_high = high; }
-
- void Flip();
-
- void Intersection(const Range &other);
-
- void Union(const Range &other);
-
- typedef bool (*RangeCallback)(ValueType index);
-
- void Iterate(RangeCallback callback);
-
- ValueType GetSize();
-
- bool IsEmpty();
-
-private:
- void InitRange();
-
- ValueType m_low;
- ValueType m_high;
-};
-
-} // namespace lldb_private
-
-#endif // #ifndef utility_Range_h_
diff --git a/include/lldb/Core/RegisterValue.h b/include/lldb/Utility/RegisterValue.h
index b369c3dff9a9..c025a26fb25a 100644
--- a/include/lldb/Core/RegisterValue.h
+++ b/include/lldb/Utility/RegisterValue.h
@@ -7,31 +7,23 @@
//
//===----------------------------------------------------------------------===//
-#ifndef lldb_RegisterValue_h
-#define lldb_RegisterValue_h
+#ifndef LLDB_UTILITY_REGISTERVALUE_H
+#define LLDB_UTILITY_REGISTERVALUE_H
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/Endian.h"
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-enumerations.h" // for ByteOrder, Format
-#include "lldb/lldb-types.h" // for offset_t
-
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
-
-#include <stdint.h> // for uint32_t, uint8_t, uint64_t, uin...
-#include <string.h>
+#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+#include <cstring>
namespace lldb_private {
class DataExtractor;
-}
-namespace lldb_private {
class Stream;
-}
-namespace lldb_private {
struct RegisterInfo;
-}
-namespace lldb_private {
class RegisterValue {
public:
@@ -276,4 +268,4 @@ protected:
} // namespace lldb_private
-#endif // lldb_RegisterValue_h
+#endif // LLDB_UTILITY_REGISTERVALUE_H
diff --git a/include/lldb/Utility/RegularExpression.h b/include/lldb/Utility/RegularExpression.h
index 6048fcc610a3..b379c6e8bea1 100644
--- a/include/lldb/Utility/RegularExpression.h
+++ b/include/lldb/Utility/RegularExpression.h
@@ -40,7 +40,7 @@ inline void regfree(llvm_regex_t *a) { llvm_regfree(a); }
#include <string>
#include <vector>
-#include <stddef.h> // for size_t
+#include <stddef.h>
#include <stdint.h>
namespace llvm {
diff --git a/include/lldb/Utility/Reproducer.h b/include/lldb/Utility/Reproducer.h
new file mode 100644
index 000000000000..ea315ad771a6
--- /dev/null
+++ b/include/lldb/Utility/Reproducer.h
@@ -0,0 +1,215 @@
+//===-- Reproducer.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_UTILITY_REPRODUCER_H
+#define LLDB_UTILITY_REPRODUCER_H
+
+#include "lldb/Utility/FileSpec.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/YAMLTraits.h"
+
+#include <mutex>
+#include <string>
+#include <vector>
+
+namespace lldb_private {
+namespace repro {
+
+class Reproducer;
+
+enum class ReproducerMode {
+ Capture,
+ Replay,
+ Off,
+};
+
+/// Abstraction for information associated with a provider. This information
+/// is serialized into an index which is used by the loader.
+struct ProviderInfo {
+ std::string name;
+ std::vector<std::string> files;
+};
+
+/// The provider defines an interface for generating files needed for
+/// reproducing. The provider must populate its ProviderInfo to communicate
+/// its name and files to the index, before registering with the generator,
+/// i.e. in the constructor.
+///
+/// Different components will implement different providers.
+class ProviderBase {
+public:
+ virtual ~ProviderBase() = default;
+
+ const ProviderInfo &GetInfo() const { return m_info; }
+ const FileSpec &GetRoot() const { return m_root; }
+
+ /// The Keep method is called when it is decided that we need to keep the
+ /// data in order to provide a reproducer.
+ virtual void Keep(){};
+
+ /// The Discard method is called when it is decided that we do not need to
+ /// keep any information and will not generate a reproducer.
+ virtual void Discard(){};
+
+ // Returns the class ID for this type.
+ static const void *ClassID() { return &ID; }
+
+ // Returns the class ID for the dynamic type of this Provider instance.
+ virtual const void *DynamicClassID() const = 0;
+
+protected:
+ ProviderBase(const FileSpec &root) : m_root(root) {}
+
+ /// Every provider keeps track of its own files.
+ ProviderInfo m_info;
+private:
+ /// Every provider knows where to dump its potential files.
+ FileSpec m_root;
+
+ virtual void anchor();
+ static char ID;
+};
+
+template <typename ThisProviderT> class Provider : public ProviderBase {
+public:
+ static const void *ClassID() { return &ThisProviderT::ID; }
+
+ const void *DynamicClassID() const override { return &ThisProviderT::ID; }
+
+protected:
+ using ProviderBase::ProviderBase; // Inherit constructor.
+};
+
+/// The generator is responsible for the logic needed to generate a
+/// reproducer. For doing so it relies on providers, who serialize data that
+/// is necessary for reproducing a failure.
+class Generator final {
+public:
+ Generator(const FileSpec &root);
+ ~Generator();
+
+ /// Method to indicate we want to keep the reproducer. If reproducer
+ /// generation is disabled, this does nothing.
+ void Keep();
+
+ /// Method to indicate we do not want to keep the reproducer. This is
+ /// unaffected by whether or not generation reproduction is enabled, as we
+ /// might need to clean up files already written to disk.
+ void Discard();
+
+ /// Create and register a new provider.
+ template <typename T> T *Create() {
+ std::unique_ptr<ProviderBase> provider = llvm::make_unique<T>(m_root);
+ return static_cast<T *>(Register(std::move(provider)));
+ }
+
+ /// Get an existing provider.
+ template <typename T> T *Get() {
+ auto it = m_providers.find(T::ClassID());
+ if (it == m_providers.end())
+ return nullptr;
+ return static_cast<T *>(it->second.get());
+ }
+
+ /// Get a provider if it exists, otherwise create it.
+ template <typename T> T &GetOrCreate() {
+ auto *provider = Get<T>();
+ if (provider)
+ return *provider;
+ return *Create<T>();
+ }
+
+ const FileSpec &GetRoot() const;
+
+private:
+ friend Reproducer;
+
+ ProviderBase *Register(std::unique_ptr<ProviderBase> provider);
+
+ /// Builds and index with provider info.
+ void AddProvidersToIndex();
+
+ /// Map of provider IDs to provider instances.
+ llvm::DenseMap<const void *, std::unique_ptr<ProviderBase>> m_providers;
+ std::mutex m_providers_mutex;
+
+ /// The reproducer root directory.
+ FileSpec m_root;
+
+ /// Flag to ensure that we never call both keep and discard.
+ bool m_done;
+};
+
+class Loader final {
+public:
+ Loader(const FileSpec &root);
+
+ llvm::Optional<ProviderInfo> GetProviderInfo(llvm::StringRef name);
+ llvm::Error LoadIndex();
+
+ const FileSpec &GetRoot() const { return m_root; }
+
+private:
+ llvm::StringMap<ProviderInfo> m_provider_info;
+ FileSpec m_root;
+ bool m_loaded;
+};
+
+/// The reproducer enables clients to obtain access to the Generator and
+/// Loader.
+class Reproducer {
+public:
+ static Reproducer &Instance();
+ static llvm::Error Initialize(ReproducerMode mode,
+ llvm::Optional<FileSpec> root);
+ static void Terminate();
+
+ Reproducer() = default;
+
+ Generator *GetGenerator();
+ Loader *GetLoader();
+
+ const Generator *GetGenerator() const;
+ const Loader *GetLoader() const;
+
+ FileSpec GetReproducerPath() const;
+
+protected:
+ llvm::Error SetCapture(llvm::Optional<FileSpec> root);
+ llvm::Error SetReplay(llvm::Optional<FileSpec> root);
+
+private:
+ static llvm::Optional<Reproducer> &InstanceImpl();
+
+ llvm::Optional<Generator> m_generator;
+ llvm::Optional<Loader> m_loader;
+
+ mutable std::mutex m_mutex;
+};
+
+} // namespace repro
+} // namespace lldb_private
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(lldb_private::repro::ProviderInfo)
+
+namespace llvm {
+namespace yaml {
+
+template <> struct MappingTraits<lldb_private::repro::ProviderInfo> {
+ static void mapping(IO &io, lldb_private::repro::ProviderInfo &info) {
+ io.mapRequired("name", info.name);
+ io.mapOptional("files", info.files);
+ }
+};
+} // namespace yaml
+} // namespace llvm
+
+#endif // LLDB_UTILITY_REPRODUCER_H
diff --git a/include/lldb/Core/Scalar.h b/include/lldb/Utility/Scalar.h
index 40671a242ec3..c23b2f8be25e 100644
--- a/include/lldb/Core/Scalar.h
+++ b/include/lldb/Utility/Scalar.h
@@ -7,25 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_Scalar_h_
-#define liblldb_Scalar_h_
-
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-enumerations.h" // for Encoding, ByteOrder
-#include "lldb/lldb-private-types.h" // for type128
+#ifndef LLDB_UTILITY_SCALAR_H
+#define LLDB_UTILITY_SCALAR_H
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private-types.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
-
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t, int64_t
+#include <cstddef>
+#include <cstdint>
namespace lldb_private {
class DataExtractor;
-}
-namespace lldb_private {
class Stream;
-}
+} // namespace lldb_private
#define NUM_OF_WORDS_INT128 2
#define BITWIDTH_INT128 128
@@ -375,4 +371,4 @@ bool operator>=(const Scalar &lhs, const Scalar &rhs);
} // namespace lldb_private
-#endif // liblldb_Scalar_h_
+#endif // LLDB_UTILITY_SCALAR_H
diff --git a/include/lldb/Utility/SelectHelper.h b/include/lldb/Utility/SelectHelper.h
index 004952f1c598..f2dac7cf53da 100644
--- a/include/lldb/Utility/SelectHelper.h
+++ b/include/lldb/Utility/SelectHelper.h
@@ -10,8 +10,8 @@
#ifndef liblldb_SelectHelper_h_
#define liblldb_SelectHelper_h_
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-types.h" // for socket_t
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-types.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
diff --git a/include/lldb/Utility/SharingPtr.h b/include/lldb/Utility/SharingPtr.h
index 691c92afaaae..7eaa049f4d18 100644
--- a/include/lldb/Utility/SharingPtr.h
+++ b/include/lldb/Utility/SharingPtr.h
@@ -10,8 +10,6 @@
#ifndef utility_SharingPtr_h_
#define utility_SharingPtr_h_
-// C Includes
-// C++ Includes
#include <memory>
// Microsoft Visual C++ currently does not enable std::atomic to work in CLR
@@ -25,8 +23,6 @@
#include <stddef.h>
-// Other libraries and framework includes
-// Project includes
//#define ENABLE_SP_LOGGING 1 // DON'T CHECK THIS LINE IN UNLESS COMMENTED OUT
#if defined(ENABLE_SP_LOGGING)
diff --git a/include/lldb/Core/State.h b/include/lldb/Utility/State.h
index 68f0fee254b3..7b3c0f1c17ab 100644
--- a/include/lldb/Core/State.h
+++ b/include/lldb/Utility/State.h
@@ -7,16 +7,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_State_h_
-#define liblldb_State_h_
+#ifndef LLDB_UTILITY_STATE_H
+#define LLDB_UTILITY_STATE_H
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FormatProviders.h"
-
-#include "lldb/lldb-enumerations.h" // for StateType
-#include "llvm/ADT/StringRef.h" // for StringRef
-#include "llvm/Support/raw_ostream.h" // for raw_ostream
-
-#include <stdint.h> // for uint32_t
+#include "llvm/Support/raw_ostream.h"
+#include <cstdint>
namespace lldb_private {
@@ -80,6 +78,6 @@ template <> struct format_provider<lldb::StateType> {
Stream << lldb_private::StateAsCString(state);
}
};
-}
+} // namespace llvm
-#endif // liblldb_State_h_
+#endif // LLDB_UTILITY_STATE_H
diff --git a/include/lldb/Utility/Status.h b/include/lldb/Utility/Status.h
index 3bd2cd5b3b41..9395ea86090b 100644
--- a/include/lldb/Utility/Status.h
+++ b/include/lldb/Utility/Status.h
@@ -11,15 +11,15 @@
#define LLDB_UTILITY_STATUS_H
#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType...
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
#include <cstdarg>
-#include <stdint.h> // for uint32_t
+#include <stdint.h>
#include <string>
-#include <system_error> // for error_code
-#include <type_traits> // for forward
+#include <system_error>
+#include <type_traits>
namespace llvm {
class raw_ostream;
diff --git a/include/lldb/Utility/Stream.h b/include/lldb/Utility/Stream.h
index 4930521d9497..bd4283edf8a9 100644
--- a/include/lldb/Utility/Stream.h
+++ b/include/lldb/Utility/Stream.h
@@ -12,14 +12,15 @@
#include "lldb/Utility/Flags.h"
#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h" // for ByteOrder::eByteOrderInvalid
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
#include <stdarg.h>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t, uint64_t, uint8_t
-#include <type_traits> // for forward
+#include <stddef.h>
+#include <stdint.h>
+#include <type_traits>
namespace lldb_private {
@@ -37,6 +38,25 @@ public:
/// string mode.
};
+ /// Utility class for counting the bytes that were written to a stream in a
+ /// certain time span.
+ /// @example
+ /// ByteDelta delta(*this);
+ /// WriteDataToStream("foo");
+ /// return *delta;
+ /// @endcode
+ class ByteDelta {
+ Stream *m_stream;
+ /// Bytes we have written so far when ByteDelta was created.
+ size_t m_start;
+
+ public:
+ ByteDelta(Stream &s) : m_stream(&s), m_start(s.GetWrittenBytes()) {}
+ /// Returns the number of bytes written to the given Stream since this
+ /// ByteDelta object was created.
+ size_t operator*() const { return m_stream->GetWrittenBytes() - m_start; }
+ };
+
//------------------------------------------------------------------
/// Construct with flags and address size and byte order.
///
@@ -52,6 +72,17 @@ public:
//------------------------------------------------------------------
Stream();
+ // FIXME: Streams should not be copyable.
+ Stream(const Stream &other) : m_forwarder(*this) { (*this) = other; }
+
+ Stream &operator=(const Stream &rhs) {
+ m_flags = rhs.m_flags;
+ m_addr_size = rhs.m_addr_size;
+ m_byte_order = rhs.m_byte_order;
+ m_indent_level = rhs.m_indent_level;
+ return *this;
+ }
+
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
@@ -83,7 +114,13 @@ public:
/// @return
/// The number of bytes that were appended to the stream.
//------------------------------------------------------------------
- virtual size_t Write(const void *src, size_t src_len) = 0;
+ size_t Write(const void *src, size_t src_len) {
+ size_t appended_byte_count = WriteImpl(src, src_len);
+ m_bytes_written += appended_byte_count;
+ return appended_byte_count;
+ }
+
+ size_t GetWrittenBytes() const { return m_bytes_written; }
//------------------------------------------------------------------
// Member functions
@@ -121,14 +158,10 @@ public:
__attribute__((__format__(__printf__, 2, 3)));
//------------------------------------------------------------------
- /// Format a C string from a printf style format and variable arguments and
- /// encode and append the resulting C string as hex bytes.
+ /// Append an uint8_t value in the hexadecimal format to the stream.
///
- /// @param[in] format
- /// A printf style format string.
- ///
- /// @param[in] ...
- /// Any additional arguments needed for the printf format string.
+ /// @param[in] uvalue
+ /// The value to append.
///
/// @return
/// The number of bytes that were appended to the stream.
@@ -504,9 +537,6 @@ public:
///
/// @param[in] uval
/// A uint64_t value that was extracted as a SLEB128 value.
- ///
- /// @param[in] format
- /// The optional printf format that can be overridden.
//------------------------------------------------------------------
size_t PutSLEB128(int64_t uval);
@@ -518,12 +548,16 @@ public:
///
/// @param[in] uval
/// A uint64_t value that was extracted as a ULEB128 value.
- ///
- /// @param[in] format
- /// The optional printf format that can be overridden.
//------------------------------------------------------------------
size_t PutULEB128(uint64_t uval);
+ //------------------------------------------------------------------
+ /// Returns a raw_ostream that forwards the data to this Stream object.
+ //------------------------------------------------------------------
+ llvm::raw_ostream &AsRawOstream() {
+ return m_forwarder;
+ }
+
protected:
//------------------------------------------------------------------
// Member variables
@@ -533,8 +567,53 @@ protected:
lldb::ByteOrder
m_byte_order; ///< Byte order to use when encoding scalar types.
int m_indent_level; ///< Indention level.
+ std::size_t m_bytes_written = 0; ///< Number of bytes written so far.
- size_t _PutHex8(uint8_t uvalue, bool add_prefix);
+ void _PutHex8(uint8_t uvalue, bool add_prefix);
+
+ //------------------------------------------------------------------
+ /// Output character bytes to the stream.
+ ///
+ /// Appends \a src_len characters from the buffer \a src to the stream.
+ ///
+ /// @param[in] src
+ /// A buffer containing at least \a src_len bytes of data.
+ ///
+ /// @param[in] src_len
+ /// A number of bytes to append to the stream.
+ ///
+ /// @return
+ /// The number of bytes that were appended to the stream.
+ //------------------------------------------------------------------
+ virtual size_t WriteImpl(const void *src, size_t src_len) = 0;
+
+ //----------------------------------------------------------------------
+ /// @class RawOstreamForward Stream.h "lldb/Utility/Stream.h"
+ /// This is a wrapper class that exposes a raw_ostream interface that just
+ /// forwards to an LLDB stream, allowing to reuse LLVM algorithms that take
+ /// a raw_ostream within the LLDB code base.
+ //----------------------------------------------------------------------
+ class RawOstreamForward : public llvm::raw_ostream {
+ // Note: This stream must *not* maintain its own buffer, but instead
+ // directly write everything to the internal Stream class. Without this,
+ // we would run into the problem that the Stream written byte count would
+ // differ from the actually written bytes by the size of the internal
+ // raw_ostream buffer.
+
+ Stream &m_target;
+ void write_impl(const char *Ptr, size_t Size) override {
+ m_target.Write(Ptr, Size);
+ }
+
+ uint64_t current_pos() const override {
+ return m_target.GetWrittenBytes();
+ }
+
+ public:
+ RawOstreamForward(Stream &target)
+ : llvm::raw_ostream(/*unbuffered*/ true), m_target(target) {}
+ };
+ RawOstreamForward m_forwarder;
};
} // namespace lldb_private
diff --git a/include/lldb/Utility/StreamCallback.h b/include/lldb/Utility/StreamCallback.h
index 0aa9d5d57b2f..63a86eeece73 100644
--- a/include/lldb/Utility/StreamCallback.h
+++ b/include/lldb/Utility/StreamCallback.h
@@ -13,8 +13,8 @@
#include "lldb/lldb-types.h"
#include "llvm/Support/raw_ostream.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint64_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
diff --git a/include/lldb/Utility/StreamGDBRemote.h b/include/lldb/Utility/StreamGDBRemote.h
index 79234cc03d86..dfc4a39de791 100644
--- a/include/lldb/Utility/StreamGDBRemote.h
+++ b/include/lldb/Utility/StreamGDBRemote.h
@@ -10,11 +10,11 @@
#ifndef liblldb_StreamGDBRemote_h_
#define liblldb_StreamGDBRemote_h_
-#include "lldb/Utility/StreamString.h" // for StreamString
-#include "lldb/lldb-enumerations.h" // for ByteOrder
+#include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-enumerations.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
diff --git a/include/lldb/Utility/StreamString.h b/include/lldb/Utility/StreamString.h
index 0ae3e82a3498..dd2f9f67466e 100644
--- a/include/lldb/Utility/StreamString.h
+++ b/include/lldb/Utility/StreamString.h
@@ -10,14 +10,14 @@
#ifndef liblldb_StreamString_h_
#define liblldb_StreamString_h_
-#include "lldb/Utility/Stream.h" // for Stream
-#include "lldb/lldb-enumerations.h" // for ByteOrder
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/StringRef.h"
-#include <string> // for string
+#include <string>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
namespace lldb_private {
@@ -31,8 +31,6 @@ public:
void Flush() override;
- size_t Write(const void *s, size_t length) override;
-
void Clear();
bool Empty() const;
@@ -49,6 +47,7 @@ public:
protected:
std::string m_packet;
+ size_t WriteImpl(const void *s, size_t length) override;
};
} // namespace lldb_private
diff --git a/include/lldb/Utility/StreamTee.h b/include/lldb/Utility/StreamTee.h
index 569ba1979978..4f8e6ab1f002 100644
--- a/include/lldb/Utility/StreamTee.h
+++ b/include/lldb/Utility/StreamTee.h
@@ -70,29 +70,6 @@ public:
}
}
- size_t Write(const void *s, size_t length) override {
- std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
- if (m_streams.empty())
- return 0;
-
- size_t min_bytes_written = SIZE_MAX;
- collection::iterator pos, end;
- for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
- // Allow for our collection to contain NULL streams. This allows the
- // StreamTee to be used with hard coded indexes for clients that might
- // want N total streams with only a few that are set to valid values.
- Stream *strm = pos->get();
- if (strm) {
- const size_t bytes_written = strm->Write(s, length);
- if (min_bytes_written > bytes_written)
- min_bytes_written = bytes_written;
- }
- }
- if (min_bytes_written == SIZE_MAX)
- return 0;
- return min_bytes_written;
- }
-
size_t AppendStream(const lldb::StreamSP &stream_sp) {
size_t new_idx = m_streams.size();
std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
@@ -131,6 +108,29 @@ protected:
typedef std::vector<lldb::StreamSP> collection;
mutable std::recursive_mutex m_streams_mutex;
collection m_streams;
+
+ size_t WriteImpl(const void *s, size_t length) override {
+ std::lock_guard<std::recursive_mutex> guard(m_streams_mutex);
+ if (m_streams.empty())
+ return 0;
+
+ size_t min_bytes_written = SIZE_MAX;
+ collection::iterator pos, end;
+ for (pos = m_streams.begin(), end = m_streams.end(); pos != end; ++pos) {
+ // Allow for our collection to contain NULL streams. This allows the
+ // StreamTee to be used with hard coded indexes for clients that might
+ // want N total streams with only a few that are set to valid values.
+ Stream *strm = pos->get();
+ if (strm) {
+ const size_t bytes_written = strm->Write(s, length);
+ if (min_bytes_written > bytes_written)
+ min_bytes_written = bytes_written;
+ }
+ }
+ if (min_bytes_written == SIZE_MAX)
+ return 0;
+ return min_bytes_written;
+ }
};
} // namespace lldb_private
diff --git a/include/lldb/Utility/StringExtractor.h b/include/lldb/Utility/StringExtractor.h
index 4b75d5c5484d..bc24c153bae6 100644
--- a/include/lldb/Utility/StringExtractor.h
+++ b/include/lldb/Utility/StringExtractor.h
@@ -10,12 +10,10 @@
#ifndef utility_StringExtractor_h_
#define utility_StringExtractor_h_
-// Other libraries and framework includes
-// Project includes
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include <stddef.h> // for size_t
+#include <stddef.h>
#include <stdint.h>
#include <string>
diff --git a/include/lldb/Utility/StringExtractorGDBRemote.h b/include/lldb/Utility/StringExtractorGDBRemote.h
index 93e760b88112..8c2eca898e64 100644
--- a/include/lldb/Utility/StringExtractorGDBRemote.h
+++ b/include/lldb/Utility/StringExtractorGDBRemote.h
@@ -12,12 +12,12 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include <string>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint8_t
+#include <stddef.h>
+#include <stdint.h>
class StringExtractorGDBRemote : public StringExtractor {
public:
diff --git a/include/lldb/Utility/StringLexer.h b/include/lldb/Utility/StringLexer.h
index e4fc81a85e0d..32cfa4e3f6f2 100644
--- a/include/lldb/Utility/StringLexer.h
+++ b/include/lldb/Utility/StringLexer.h
@@ -1,5 +1,4 @@
-//===--------------------- StringLexer.h -------------------------*- C++
-//-*-===//
+//===--------------------- StringLexer.h ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,9 +10,9 @@
#ifndef utility_StringLexer_h_
#define utility_StringLexer_h_
-#include <initializer_list> // for initializer_list
-#include <string> // for string
-#include <utility> // for pair
+#include <initializer_list>
+#include <string>
+#include <utility>
namespace lldb_utility {
diff --git a/include/lldb/Utility/StringList.h b/include/lldb/Utility/StringList.h
index 1cb68885e771..c080230249dd 100644
--- a/include/lldb/Utility/StringList.h
+++ b/include/lldb/Utility/StringList.h
@@ -12,7 +12,7 @@
#include "llvm/ADT/StringRef.h"
-#include <stddef.h> // for size_t
+#include <stddef.h>
#include <string>
#include <vector>
diff --git a/include/lldb/Utility/StructuredData.h b/include/lldb/Utility/StructuredData.h
index d3ebab16f51d..100b4fa98ae1 100644
--- a/include/lldb/Utility/StructuredData.h
+++ b/include/lldb/Utility/StructuredData.h
@@ -13,17 +13,17 @@
#include "llvm/ADT/StringRef.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/lldb-enumerations.h" // for StructuredDataType
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/lldb-enumerations.h"
-#include <cassert> // for assert
-#include <cstddef> // for size_t
-#include <cstdint> // for uint64_t
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <string>
-#include <type_traits> // for move
+#include <type_traits>
#include <utility>
#include <vector>
@@ -170,7 +170,7 @@ public:
bool
ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
for (const auto &object_sp : m_items) {
- if (foreach_callback(object_sp.get()) == false)
+ if (!foreach_callback(object_sp.get()))
return false;
}
return true;
@@ -359,7 +359,7 @@ public:
void ForEach(std::function<bool(ConstString key, Object *object)> const
&callback) const {
for (const auto &pair : m_dict) {
- if (callback(pair.first, pair.second.get()) == false)
+ if (!callback(pair.first, pair.second.get()))
break;
}
}
diff --git a/include/lldb/Utility/Timer.h b/include/lldb/Utility/Timer.h
index 2c1e984837c2..7c41c6257254 100644
--- a/include/lldb/Utility/Timer.h
+++ b/include/lldb/Utility/Timer.h
@@ -10,10 +10,10 @@
#ifndef liblldb_Timer_h_
#define liblldb_Timer_h_
-#include "lldb/lldb-defines.h" // for DISALLOW_COPY_AND_ASSIGN
+#include "lldb/lldb-defines.h"
#include "llvm/Support/Chrono.h"
#include <atomic>
-#include <stdint.h> // for uint32_t
+#include <stdint.h>
namespace lldb_private {
class Stream;
diff --git a/include/lldb/Utility/UUID.h b/include/lldb/Utility/UUID.h
index d42c88862bfa..e082db572e46 100644
--- a/include/lldb/Utility/UUID.h
+++ b/include/lldb/Utility/UUID.h
@@ -10,8 +10,6 @@
#ifndef LLDB_UTILITY_UUID_H
#define LLDB_UTILITY_UUID_H
-// C Includes
-// C++ Includes
#include <stddef.h>
#include <stdint.h>
#include <string>
diff --git a/include/lldb/Utility/UserID.h b/include/lldb/Utility/UserID.h
index 9e15e6a43c6c..8560274bdeac 100644
--- a/include/lldb/Utility/UserID.h
+++ b/include/lldb/Utility/UserID.h
@@ -10,8 +10,8 @@
#ifndef liblldb_UserID_h_
#define liblldb_UserID_h_
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_UID
-#include "lldb/lldb-types.h" // for user_id_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
namespace lldb_private {
class Stream;
}
diff --git a/include/lldb/Utility/VMRange.h b/include/lldb/Utility/VMRange.h
index f03a1b0c1f97..a70b0cb6118c 100644
--- a/include/lldb/Utility/VMRange.h
+++ b/include/lldb/Utility/VMRange.h
@@ -10,10 +10,10 @@
#ifndef liblldb_VMRange_h_
#define liblldb_VMRange_h_
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-types.h"
-#include <stddef.h> // for size_t
-#include <stdint.h> // for uint32_t
+#include <stddef.h>
+#include <stdint.h>
#include <vector>
namespace lldb_private {
@@ -87,24 +87,6 @@ public:
void Dump(Stream *s, lldb::addr_t base_addr = 0,
uint32_t addr_width = 8) const;
- class ValueInRangeUnaryPredicate {
- public:
- ValueInRangeUnaryPredicate(lldb::addr_t value) : _value(value) {}
- bool operator()(const VMRange &range) const {
- return range.Contains(_value);
- }
- lldb::addr_t _value;
- };
-
- class RangeInRangeUnaryPredicate {
- public:
- RangeInRangeUnaryPredicate(VMRange range) : _range(range) {}
- bool operator()(const VMRange &range) const {
- return range.Contains(_range);
- }
- const VMRange &_range;
- };
-
static bool ContainsValue(const VMRange::collection &coll,
lldb::addr_t value);
diff --git a/include/lldb/lldb-defines.h b/include/lldb/lldb-defines.h
index edb70be09fd9..8a54b4c44364 100644
--- a/include/lldb/lldb-defines.h
+++ b/include/lldb/lldb-defines.h
@@ -135,6 +135,7 @@
#define LLDB_OPT_SET_8 (1U << 7)
#define LLDB_OPT_SET_9 (1U << 8)
#define LLDB_OPT_SET_10 (1U << 9)
+#define LLDB_OPT_SET_11 (1U << 10)
#define LLDB_OPT_SET_FROM_TO(A, B) \
(((1U << (B)) - 1) ^ (((1U << (A)) - 1) >> 1))
diff --git a/include/lldb/lldb-enumerations.h b/include/lldb/lldb-enumerations.h
index a1f730379534..1c4d6f509a2a 100644
--- a/include/lldb/lldb-enumerations.h
+++ b/include/lldb/lldb-enumerations.h
@@ -10,6 +10,42 @@
#ifndef LLDB_lldb_enumerations_h_
#define LLDB_lldb_enumerations_h_
+#include <type_traits>
+
+#ifndef SWIG
+// Macro to enable bitmask operations on an enum. Without this, Enum | Enum
+// gets promoted to an int, so you have to say Enum a = Enum(eFoo | eBar). If
+// you mark Enum with LLDB_MARK_AS_BITMASK_ENUM(Enum), however, you can simply
+// write Enum a = eFoo | eBar.
+// Unfortunately, swig<3.0 doesn't recognise the constexpr keyword, so remove
+// this entire block, as it is not necessary for swig processing.
+#define LLDB_MARK_AS_BITMASK_ENUM(Enum) \
+ constexpr Enum operator|(Enum a, Enum b) { \
+ return static_cast<Enum>( \
+ static_cast<std::underlying_type<Enum>::type>(a) | \
+ static_cast<std::underlying_type<Enum>::type>(b)); \
+ } \
+ constexpr Enum operator&(Enum a, Enum b) { \
+ return static_cast<Enum>( \
+ static_cast<std::underlying_type<Enum>::type>(a) & \
+ static_cast<std::underlying_type<Enum>::type>(b)); \
+ } \
+ constexpr Enum operator~(Enum a) { \
+ return static_cast<Enum>( \
+ ~static_cast<std::underlying_type<Enum>::type>(a)); \
+ } \
+ inline Enum &operator|=(Enum &a, Enum b) { \
+ a = a | b; \
+ return a; \
+ } \
+ inline Enum &operator&=(Enum &a, Enum b) { \
+ a = a & b; \
+ return a; \
+ }
+#else
+#define LLDB_MARK_AS_BITMASK_ENUM(Enum)
+#endif
+
#ifndef SWIG
// With MSVC, the default type of an enum is always signed, even if one of the
// enumerator values is too large to fit into a signed integer but would
@@ -54,9 +90,10 @@ enum StateType {
eStateCrashed, ///< Process or thread has crashed and can be examined.
eStateDetached, ///< Process has been detached and can't be examined.
eStateExited, ///< Process has exited and can't be examined.
- eStateSuspended ///< Process or thread is in a suspended state as far
+ eStateSuspended, ///< Process or thread is in a suspended state as far
///< as the debugger is concerned while other processes
///< or threads get the chance to run.
+ kLastStateType = eStateSuspended
};
//----------------------------------------------------------------------
@@ -256,6 +293,17 @@ enum ExpressionResults {
eExpressionStoppedForDebug
};
+enum SearchDepth {
+ eSearchDepthInvalid = 0,
+ eSearchDepthTarget,
+ eSearchDepthModule,
+ eSearchDepthCompUnit,
+ eSearchDepthFunction,
+ eSearchDepthBlock,
+ eSearchDepthAddress,
+ kLastSearchDepthKind = eSearchDepthAddress
+};
+
//----------------------------------------------------------------------
// Connection Status Types
//----------------------------------------------------------------------
@@ -315,43 +363,45 @@ enum InputReaderGranularity {
//------------------------------------------------------------------
FLAGS_ENUM(SymbolContextItem){
eSymbolContextTarget = (1u << 0), ///< Set when \a target is requested from
- ///a query, or was located in query
- ///results
+ /// a query, or was located in query
+ /// results
eSymbolContextModule = (1u << 1), ///< Set when \a module is requested from
- ///a query, or was located in query
- ///results
+ /// a query, or was located in query
+ /// results
eSymbolContextCompUnit = (1u << 2), ///< Set when \a comp_unit is requested
- ///from a query, or was located in query
- ///results
+ /// from a query, or was located in
+ /// query results
eSymbolContextFunction = (1u << 3), ///< Set when \a function is requested
- ///from a query, or was located in query
- ///results
+ /// from a query, or was located in
+ /// query results
eSymbolContextBlock = (1u << 4), ///< Set when the deepest \a block is
- ///requested from a query, or was located
- ///in query results
+ /// requested from a query, or was located
+ /// in query results
eSymbolContextLineEntry = (1u << 5), ///< Set when \a line_entry is
- ///requested from a query, or was
- ///located in query results
+ /// requested from a query, or was
+ /// located in query results
eSymbolContextSymbol = (1u << 6), ///< Set when \a symbol is requested from
- ///a query, or was located in query
- ///results
+ /// a query, or was located in query
+ /// results
eSymbolContextEverything = ((eSymbolContextSymbol << 1) -
1u), ///< Indicates to try and lookup everything
- ///up during a routine symbol context
- ///query.
- eSymbolContextVariable = (1u << 7) ///< Set when \a global or static
- ///variable is requested from a query, or
- ///was located in query results.
+ /// up during a routine symbol context
+ /// query.
+ eSymbolContextVariable = (1u << 7), ///< Set when \a global or static
+ /// variable is requested from a query,
+ /// or was located in query results.
///< eSymbolContextVariable is potentially expensive to lookup so it isn't
- ///included in
+ /// included in
///< eSymbolContextEverything which stops it from being used during frame PC
- ///lookups and
+ /// lookups and
///< many other potential address to symbol context lookups.
};
+LLDB_MARK_AS_BITMASK_ENUM(SymbolContextItem)
FLAGS_ENUM(Permissions){ePermissionsWritable = (1u << 0),
ePermissionsReadable = (1u << 1),
ePermissionsExecutable = (1u << 2)};
+LLDB_MARK_AS_BITMASK_ENUM(Permissions)
enum InputReaderAction {
eInputReaderActivate, // reader is newly pushed onto the reader stack
@@ -661,7 +711,14 @@ enum SectionType {
eSectionTypeDWARFGNUDebugAltLink,
eSectionTypeDWARFDebugTypes, // DWARF .debug_types section
eSectionTypeDWARFDebugNames, // DWARF v5 .debug_names
- eSectionTypeOther
+ eSectionTypeOther,
+ eSectionTypeDWARFDebugLineStr, // DWARF v5 .debug_line_str
+ eSectionTypeDWARFDebugRngLists, // DWARF v5 .debug_rnglists
+ eSectionTypeDWARFDebugLocLists, // DWARF v5 .debug_loclists
+ eSectionTypeDWARFDebugAbbrevDwo,
+ eSectionTypeDWARFDebugInfoDwo,
+ eSectionTypeDWARFDebugStrDwo,
+ eSectionTypeDWARFDebugStrOffsetsDwo,
};
FLAGS_ENUM(EmulateInstructionOptions){
@@ -689,6 +746,7 @@ FLAGS_ENUM(FunctionNameType){
eFunctionNameTypeAny =
eFunctionNameTypeAuto // DEPRECATED: use eFunctionNameTypeAuto
};
+LLDB_MARK_AS_BITMASK_ENUM(FunctionNameType)
//----------------------------------------------------------------------
// Basic types enumeration for the public API SBType::GetBasicType()
@@ -763,6 +821,7 @@ FLAGS_ENUM(TypeClass){
eTypeClassOther = (1u << 31),
// Define a mask that can be used for any type when finding types
eTypeClassAny = (0xffffffffu)};
+LLDB_MARK_AS_BITMASK_ENUM(TypeClass)
enum TemplateArgumentKind {
eTemplateArgumentKindNull = 0,
@@ -1071,7 +1130,6 @@ enum TypeSummaryCapping {
eTypeSummaryCapped = true,
eTypeSummaryUncapped = false
};
-
} // namespace lldb
#endif // LLDB_lldb_enumerations_h_
diff --git a/include/lldb/lldb-forward.h b/include/lldb/lldb-forward.h
index e3964268dfda..92aa5bb611c3 100644
--- a/include/lldb/lldb-forward.h
+++ b/include/lldb/lldb-forward.h
@@ -107,7 +107,6 @@ class File;
class FileSpec;
class FileSpecList;
class Flags;
-class GoASTContext;
class TypeCategoryImpl;
class FormatManager;
class FormattersMatchCandidate;
@@ -126,13 +125,14 @@ class JITLoaderList;
class Language;
class LanguageCategory;
class LanguageRuntime;
-class MemoryRegionInfo;
class LineTable;
class Listener;
class Log;
class Mangled;
class Materializer;
class MemoryHistory;
+class MemoryRegionInfo;
+class MemoryRegionInfos;
class Module;
class ModuleList;
class ModuleSpec;
@@ -184,6 +184,7 @@ class ProcessInstanceInfoMatch;
class ProcessLaunchInfo;
class Property;
struct PropertyDefinition;
+class RecognizedStackFrame;
class RegisterCheckpoint;
class RegisterContext;
class RegisterLocation;
@@ -191,6 +192,7 @@ class RegisterLocationList;
class RegisterValue;
class RegularExpression;
class REPL;
+class RichManglingContext;
class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
@@ -207,6 +209,8 @@ class SourceManagerImpl;
class StackFrame;
class StackFrameImpl;
class StackFrameList;
+class StackFrameRecognizer;
+class StackFrameRecognizerManager;
class StackID;
class StopInfo;
class Stoppoint;
@@ -350,7 +354,6 @@ typedef std::shared_ptr<lldb_private::File> FileSP;
typedef std::shared_ptr<lldb_private::Function> FunctionSP;
typedef std::shared_ptr<lldb_private::FunctionCaller> FunctionCallerSP;
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
-typedef std::unique_ptr<lldb_private::GoASTContext> GoASTContextUP;
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
typedef std::shared_ptr<lldb_private::Instruction> InstructionSP;
typedef std::shared_ptr<lldb_private::InstrumentationRuntime>
@@ -367,7 +370,6 @@ typedef std::shared_ptr<lldb_private::LineTable> LineTableSP;
typedef std::shared_ptr<lldb_private::Listener> ListenerSP;
typedef std::weak_ptr<lldb_private::Listener> ListenerWP;
typedef std::shared_ptr<lldb_private::MemoryHistory> MemoryHistorySP;
-typedef std::shared_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoSP;
typedef std::unique_ptr<lldb_private::MemoryRegionInfo> MemoryRegionInfoUP;
typedef std::shared_ptr<lldb_private::Module> ModuleSP;
typedef std::weak_ptr<lldb_private::Module> ModuleWP;
@@ -413,6 +415,8 @@ typedef std::shared_ptr<lldb_private::Queue> QueueSP;
typedef std::weak_ptr<lldb_private::Queue> QueueWP;
typedef std::shared_ptr<lldb_private::QueueItem> QueueItemSP;
typedef std::shared_ptr<lldb_private::REPL> REPLSP;
+typedef std::shared_ptr<lldb_private::RecognizedStackFrame>
+ RecognizedStackFrameSP;
typedef std::shared_ptr<lldb_private::ScriptSummaryFormat>
ScriptSummaryFormatSP;
typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
@@ -428,6 +432,8 @@ typedef std::shared_ptr<lldb_private::StackFrame> StackFrameSP;
typedef std::unique_ptr<lldb_private::StackFrame> StackFrameUP;
typedef std::weak_ptr<lldb_private::StackFrame> StackFrameWP;
typedef std::shared_ptr<lldb_private::StackFrameList> StackFrameListSP;
+typedef std::shared_ptr<lldb_private::StackFrameRecognizer>
+ StackFrameRecognizerSP;
typedef std::shared_ptr<lldb_private::StopInfo> StopInfoSP;
typedef std::shared_ptr<lldb_private::StoppointLocation> StoppointLocationSP;
typedef std::shared_ptr<lldb_private::Stream> StreamSP;
@@ -492,5 +498,15 @@ typedef std::shared_ptr<lldb_private::Watchpoint> WatchpointSP;
} // namespace lldb
+//----------------------------------------------------------------------
+// llvm forward declarations
+//----------------------------------------------------------------------
+namespace llvm {
+
+struct ItaniumPartialDemangler;
+class StringRef;
+
+} // namespace llvm
+
#endif // #if defined(__cplusplus)
#endif // LLDB_lldb_forward_h_
diff --git a/include/lldb/lldb-private-forward.h b/include/lldb/lldb-private-forward.h
index 65d303281164..975d92d95727 100644
--- a/include/lldb/lldb-private-forward.h
+++ b/include/lldb/lldb-private-forward.h
@@ -10,26 +10,15 @@
#ifndef LLDB_lldb_private_forward_h_
#define LLDB_lldb_private_forward_h_
-#if defined(__cplusplus)
-
-#include <memory>
-
namespace lldb_private {
// --------------------------------------------------------------- Class
// forward decls.
// ---------------------------------------------------------------
-class NativeBreakpoint;
-class NativeBreakpointList;
class NativeProcessProtocol;
class NativeRegisterContext;
class NativeThreadProtocol;
class ResumeActionList;
class UnixSignals;
-
-// --------------------------------------------------------------- SP/WP decls.
-// ---------------------------------------------------------------
-typedef std::shared_ptr<NativeBreakpoint> NativeBreakpointSP;
}
-#endif // #if defined(__cplusplus)
#endif // #ifndef LLDB_lldb_private_forward_h_
diff --git a/include/lldb/lldb-private-interfaces.h b/include/lldb/lldb-private-interfaces.h
index 806068ece7b6..76a9fad9f135 100644
--- a/include/lldb/lldb-private-interfaces.h
+++ b/include/lldb/lldb-private-interfaces.h
@@ -84,10 +84,10 @@ typedef void (*OptionValueChangedCallback)(void *baton,
OptionValue *option_value);
typedef bool (*ThreadPlanShouldStopHereCallback)(
ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation,
- void *baton);
+ Status &status, void *baton);
typedef lldb::ThreadPlanSP (*ThreadPlanStepFromHereCallback)(
ThreadPlan *current_plan, Flags &flags, lldb::FrameComparison operation,
- void *baton);
+ Status &status, void *baton);
typedef UnwindAssembly *(*UnwindAssemblyCreateInstance)(const ArchSpec &arch);
typedef lldb::MemoryHistorySP (*MemoryHistoryCreateInstance)(
const lldb::ProcessSP &process_sp);
diff --git a/include/lldb/lldb-private-types.h b/include/lldb/lldb-private-types.h
index 7ba7350e868c..e0f0e413cef4 100644
--- a/include/lldb/lldb-private-types.h
+++ b/include/lldb/lldb-private-types.h
@@ -95,6 +95,8 @@ struct OptionEnumValueElement {
const char *usage;
};
+using OptionEnumValues = llvm::ArrayRef<OptionEnumValueElement>;
+
struct OptionValidator {
virtual ~OptionValidator() {}
virtual bool IsValid(Platform &platform,
@@ -112,9 +114,8 @@ struct OptionDefinition {
int short_option; // Single character for this option.
int option_has_arg; // no_argument, required_argument or optional_argument
OptionValidator *validator; // If non-NULL, option is valid iff
- // |validator->IsValid()|, otherwise always
- // valid.
- OptionEnumValueElement *enum_values; // If non-NULL an array of enum values.
+ // |validator->IsValid()|, otherwise always valid.
+ OptionEnumValues enum_values; // If not empty, an array of enum values.
uint32_t completion_type; // Cookie the option class can use to do define the
// argument completion.
lldb::CommandArgumentType argument_type; // Type of argument this option takes
diff --git a/include/lldb/lldb-types.h b/include/lldb/lldb-types.h
index 79f441569304..09dfc5c8a5ed 100644
--- a/include/lldb/lldb-types.h
+++ b/include/lldb/lldb-types.h
@@ -47,7 +47,8 @@ typedef unsigned int __w64 socket_t; // Host socket type
typedef void *thread_arg_t; // Host thread argument type
typedef unsigned thread_result_t; // Host thread result type
typedef thread_result_t (*thread_func_t)(void *); // Host thread function type
-}
+typedef void *pipe_t; // Host pipe type is HANDLE
+} // namespace lldb
#else
@@ -65,6 +66,7 @@ typedef int socket_t; // Host socket type
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
+typedef int pipe_t; // Host pipe type
} // namespace lldb
#endif
@@ -76,10 +78,11 @@ typedef bool (*CommandOverrideCallbackWithResult)(
void *baton, const char **argv, lldb_private::CommandReturnObject &result);
typedef bool (*ExpressionCancelCallback)(ExpressionEvaluationPhase phase,
void *baton);
-}
+} // namespace lldb
#define LLDB_INVALID_PROCESS ((lldb::process_t)-1)
#define LLDB_INVALID_HOST_THREAD ((lldb::thread_t)NULL)
+#define LLDB_INVALID_PIPE ((lldb::pipe_t)-1)
namespace lldb {
typedef uint64_t addr_t;
@@ -91,6 +94,6 @@ typedef int32_t break_id_t;
typedef int32_t watch_id_t;
typedef void *opaque_compiler_type_t;
typedef uint64_t queue_id_t;
-}
+} // namespace lldb
#endif // LLDB_lldb_types_h_
diff --git a/include/lldb/module.modulemap b/include/lldb/module.modulemap
index cec0428c1840..9c7f3e6f58e5 100644
--- a/include/lldb/module.modulemap
+++ b/include/lldb/module.modulemap
@@ -38,10 +38,10 @@ module lldb_Host {
module PipeBase { header "Host/PipeBase.h" export * }
module Pipe { header "Host/Pipe.h" export * }
module PosixApi { header "Host/PosixApi.h" export * }
- module Predicate { header "Host/Predicate.h" export * }
module ProcessLauncher { header "Host/ProcessLauncher.h" export * }
module ProcessRunLock { header "Host/ProcessRunLock.h" export * }
module PseudoTerminal { header "Host/PseudoTerminal.h" export * }
+ module SafeMachO { header "Host/SafeMachO.h" export * }
module SocketAddress { header "Host/SocketAddress.h" export * }
module Socket { header "Host/Socket.h" export * }
module StringConvert { header "Host/StringConvert.h" export * }
diff --git a/lit/Breakpoint/Inputs/debug_addrx.yaml b/lit/Breakpoint/Inputs/debug_addrx.yaml
new file mode 100644
index 000000000000..7d4cd74543e3
--- /dev/null
+++ b/lit/Breakpoint/Inputs/debug_addrx.yaml
@@ -0,0 +1,57 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000201000
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000201000
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C08011200048C7C11011200048C7C700112000E897010000F4CCCCCCCCCCCC55B810202000483D102020004889E57417B8000000004885C0740D5DBF10202000FFE00F1F4400005DC3660F1F440000BE10202000554881EE102020004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF10202000FFE00F1F005DC3660F1F440000803D592F0000007517554889E5E87EFFFFFFC605472F0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89CCCCCCCCCCCCCCCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC31C0C3CCCCCCCCCCCCCCCCCCCCCCCCCC415741564189FF415541544C8D25E61E000055488D2DE61E0000534989F64989D54C29E54883EC0848C1FD03E8430000004885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 44000000050000006B0000005F0000003A0000000E0000001A0000001E000000930000002E0000001600000067000000050000009A0000008E000000000000006900000095000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 74686973005F5A336261723141005F76707472244100666F6F00696E74005F5F7674626C5F7074725F74797065005F5A4E314133666F6F4576002F686F6D652F756D622F74657374735F323031382F3131326C6C64625F726C657461677300746573742E63630041006100636C616E672076657273696F6E20382E302E3020287472756E6B2033343438333429006D61696E0078006F626A410062617200
+ - Name: .debug_loc
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: E010200000000000E010200000000000030011009FE010200000000000E1102000000000000500110023019F00000000000000000000000000000000
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B25731711015517741700000213011D13360B03250B0B3A0B3B0B0000030D0003254913380B34190000040D00032549133A0B3B0B380B0000052E016E2503253A0B3B0B4C0B4D183C193F191D130000060500491334190000070F0049130000080F00491303250000091500491300000A240003253E0B0B0B00000B2E01111B1206401864137A193B0B471300000C050003254913341900000D3400021703253A0B3B0B491300000E2E01111B120640187A196E2503253A0B3B0B3F1900000F050003253A0B3B0B49130000102E01111B120640187A1903253A0B3B0B49133F19000011340003253A0B3B0B4913000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: C8000000050001080000000001000400010800000000000000020800000000000000000000000C0000000C000000022E000000040910010303035C0000000004066C0000000104080507080105010210002E000000067000000000000761000000086700000005096C0000000A040504072E0000000B000100000001578600000008480000000C0DC60000000D000000000601096C000000000E010100000001570A0B010D0F0E010D2E0000000010020300000001570C01116C000000110F01122E00000000072E00000000
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 27000000050008000000000007E0102000000000000107F010200000000000010700112000000000000300
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 1C00000005000800E010200000000000F0102000000000000011200000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 97000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E02250000000066F622AD4EB40BCEA506478235D9D438250000000066F622AD4EB40BCEA506478235D9D438000902E0102000000000001905010A150201000101000902F010200000000000030C0105010A140201000101000902001120000000000003100105030A170203000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F3131326C6C64625F726C657461677300746573742E636300
+Symbols:
diff --git a/lit/Breakpoint/Inputs/debug_rnglist_basic.yaml b/lit/Breakpoint/Inputs/debug_rnglist_basic.yaml
new file mode 100644
index 000000000000..6a6db28790e3
--- /dev/null
+++ b/lit/Breakpoint/Inputs/debug_rnglist_basic.yaml
@@ -0,0 +1,50 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400440
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400440
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0C005400048C7C15005400048C7C730054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89900F1F840000000000554889E5B8010000005DC30F1F440000554889E54883EC10C745FC00000000E8DCFFFFFF4883C4105DC3660F1F440000415741564189FF415541544C8D25A618000055488D2DA6180000534989F64989D54C29E54883EC0848C1FD03E86FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 200000000500000000000000230000002C0000005D00000065000000690000006D000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 636C616E672076657273696F6E20382E302E3020287472756E6B203334333438372900746573742E637070002F686F6D652F756D622F74657374735F323031382F313033726E676C697374732F6C6C64622F63726561746574657374005F5A337A656476007A656400696E74006D61696E00
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B251101551774170000022E001101120640186E2503253A0B3B0B49133F190000032E0011011206401803253A0B3B0B49133F19000004240003253E0B0B0B000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 580000000500010800000000010004000108000000000000000200000000000000000C0000000C0000000220054000000000000B000000015603040101570000000330054000000000001A0000000156060105570000000405050400
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 1D00000005000800000000000720054000000000000B0730054000000000001A00
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 82000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E023100000000F7B7492A97F18E69F7EC76B19E9024873100000000F7B7492A97F18E69F7EC76B19E90248700090220054000000000000105020A4B020700010100090230054000000000001605090AE5050206580206000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F313033726E676C697374732F6C6C64622F6372656174657465737400746573742E63707000
+Symbols:
+...
diff --git a/lit/Breakpoint/Inputs/debug_rnglist_offset_pair.yaml b/lit/Breakpoint/Inputs/debug_rnglist_offset_pair.yaml
new file mode 100644
index 000000000000..b919e3e4d1cb
--- /dev/null
+++ b/lit/Breakpoint/Inputs/debug_rnglist_offset_pair.yaml
@@ -0,0 +1,53 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400440
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400440
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0C005400048C7C15005400048C7C740054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89660F1F840000000000B9020000008B05F91A00000F1F44000021F883C1FF75F98905E71A0000C3669050BF01000000E8D5FFFFFF31C059C390415741564189FF415541544C8D25A618000055488D2DA6180000534989F64989D54C29E54883EC0848C1FD03E86FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 300000000500000000000000230000002C0000004F00000051000000550000005D0000006100000066000000680000006A000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 636C616E672076657273696F6E20382E302E3020287472756E6B203334343033352900746573742E637070002F686F6D652F756D622F74657374735F323031382F3130365F726E676C6973747332004300696E74005F5A33666F6F6900666F6F006D61696E00500049005700
+ - Name: .debug_loc
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 05000000000000001000000000000000030011009F00000000000000000000000000000000
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B251101120674170000023400032549133F193A0B3B0B0218000003240003253E0B0B0B0000042E011101120640187A196E2503253A0B3B0B3F190000050500021803253A0B3B0B49130000060B01110112060000073400021703253A0B3B0B49130000080B015517000009340003253A0B3B0B491300000A2E011101120640187A1903253A0B3B0B49133F1900000B48007F137D0100000C0F004913000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: AC0000000500010800000000010004000108000000000000000220054000000000002F0000000C00000002033C000000010309032420400000000000030405040420054000000000001E0000000157050601040501550801043C0000000625054000000000001800000007000000000901063C000000080C000000090A0107AA0000000000000A40054000000000000F000000015707010E3C0000000B400000004B05400000000000000C3C00000000
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 18000000050008000000000005200540000000000004051204171D00
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 7F000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E0223000000003D8C80E874CE6D5F1FC4A6544BE9D5B323000000003D8C80E874CE6D5F1FC4A6544BE9D5B300090220054000000000001605080A5B0515C60503063C0508063005016805004105030A21A00204000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F3130365F726E676C697374733200746573742E63707000
+Symbols:
diff --git a/lit/Breakpoint/Inputs/debug_rnglist_rlestartend.yaml b/lit/Breakpoint/Inputs/debug_rnglist_rlestartend.yaml
new file mode 100644
index 000000000000..79807773432f
--- /dev/null
+++ b/lit/Breakpoint/Inputs/debug_rnglist_rlestartend.yaml
@@ -0,0 +1,49 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000201000
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000201000
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C08011200048C7C11011200048C7C7F0102000E897010000F4CCCCCCCCCCCC55B810202000483D102020004889E57417B8000000004885C0740D5DBF10202000FFE00F1F4400005DC3660F1F440000BE10202000554881EE102020004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF10202000FFE00F1F005DC3660F1F440000803D592F0000007517554889E5E87EFFFFFFC605472F0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89CCCCCCCCCCCCCCCCCC554889E5B8010000005DC3CCCCCCCCCC554889E54883EC10C745FC00000000E8DCFFFFFF4883C4105DC3CCCCCCCCCCCC415741564189FF415541544C8D25E61E000055488D2DE61E0000534989F64989D54C29E54883EC0848C1FD03E8430000004885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2000000005000000040000002B0000003900000062000000270000000000000034000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 696E7400636C616E672076657273696F6E20382E302E3020287472756E6B2033343430333529007A656400746573742E637070006D61696E002F686F6D652F756D622F74657374735F323031382F3130375F726E676C6973747374617274656E64005F5A337A65647600
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B251101551774170000022E001101120640186E2503253A0B3B0B49133F190000032E0011011206401803253A0B3B0B49133F19000004240003253E0B0B0B000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 580000000500010800000000010004000108000000000000000200000000000000000C0000000C00000002E0102000000000000B0000000156030401015700000003F0102000000000001A0000000156060105570000000405050400
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2B000000050008000000000006E010200000000000EB1020000000000006F0102000000000000A1120000000000000
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 82000000050008004C000000010101FB0E0D00010101010000000100000101011F010900000003011F020F051E020000000000C404455D157064301CF8C713A4AC4CEE0000000000C404455D157064301CF8C713A4AC4CEE000902E0102000000000000105030A4B0207000101000902F01020000000000016050A0AE5050306580206000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 746573742E637070002F686F6D652F756D622F74657374735F323031382F3130375F726E676C6973747374617274656E6400
+Symbols:
diff --git a/lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml b/lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml
new file mode 100644
index 000000000000..15b95e2a1750
--- /dev/null
+++ b/lit/Breakpoint/Inputs/debug_rnglistx_rlex.yaml
@@ -0,0 +1,57 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000201000
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000201000
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C08011200048C7C11011200048C7C700112000E897010000F4CCCCCCCCCCCC55B810202000483D102020004889E57417B8000000004885C0740D5DBF10202000FFE00F1F4400005DC3660F1F440000BE10202000554881EE102020004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF10202000FFE00F1F005DC3660F1F440000803D592F0000007517554889E5E87EFFFFFFC605472F0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89CCCCCCCCCCCCCCCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC31C0C3CCCCCCCCCCCCCCCCCCCCCCCCCC415741564189FF415541544C8D25E61E000055488D2DE61E0000534989F64989D54C29E54883EC0848C1FD03E8430000004885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 28000000050000003000000067000000000000002800000076000000240000006F0000007400000022000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F3131345F726E676C69737473007900696E74005F5A336261726900636C616E672076657273696F6E20382E302E3020287472756E6B203334353639392920286C6C766D2F7472756E6B203334353530362900746573742E6363006D61696E00780062617200
+ - Name: .debug_loclists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '15000000050008000000000003000301005503020101005000'
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B2573171101552374178C01170000022E01111B120640187A196E2503253A0B3B0B49133F190000030500021703253A0B3B0B49130000042E01111B120640187A1903253A0B3B0B49133F1900000534001C0D03253A0B3B0B4913000006240003253E0B0B0B000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 6600000005000108000000000100040001080000000000000002080000000000000000000000000C0000000C00000002000400000001570304010365000000030C0000000701036500000000040106000000015706010765000000050108010865000000000605050400
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '1300000005000800010000000400000003000403010600'
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 1C00000005000800E010200000000000F010200000000000E310200000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 82000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E022200000000FC42F1EAF1396417A8FBE442FBADC7032200000000FC42F1EAF1396417A8FBE442FBADC703000902E01020000000000014050B0A130504063C0201000101000902F0102000000000001805030A140206000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F3131345F726E676C6973747300746573742E636300
+Symbols:
diff --git a/lit/Breakpoint/Inputs/implicit_const_form_support.yaml b/lit/Breakpoint/Inputs/implicit_const_form_support.yaml
new file mode 100644
index 000000000000..f1d8373923b4
--- /dev/null
+++ b/lit/Breakpoint/Inputs/implicit_const_form_support.yaml
@@ -0,0 +1,41 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x00000000004004A0
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x00000000004004A0
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C01006400048C7C1A005400048C7C77E054000E8B7FFFFFFF4660F1F440000B820204000483D202040007413B8000000004885C07409BF20204000FFE06690C30F1F440000662E0F1F840000000000BE202040004881EE2020400048C1FE034889F048C1E83F4801C648D1FE7411B8000000004885C07407BF20204000FFE0C30F1F440000662E0F1F840000000000803DD91A0000007517554889E5E87EFFFFFFC605C71A0000015DC30F1F440000C30F1F440000662E0F1F840000000000EB8EB800000000C3B800000000C3554889E5534883EC08E8E6FFFFFF89C3E8E5FFFFFF01D84883C4085B5DC30F1F4000415741564189FF415541544C8D251618000055488D2D16180000534989F64989D54C29E54883EC0848C1FD03E877FEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_frame
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000008
+ Content: 14000000FFFFFFFF03000178100C0708900100000000000014000000000000007205400000000000060000000000000014000000000000007805400000000000060000000000000034000000000000007E054000000000001E0000000000000004010000000E10860204030000000D060405000000830304140000000C070800
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 900000000500010800000000023A00000021310000000000000072054000000000002A0000000000000000000000039A0000000109054C0000007E054000000000001E00000000000000019C040405696E7400012C000000059F0000004C00000078054000000000000600000000000000019C018C00000001910000004C00000072054000000000000600000000000000019C00
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 012E003F19030E3A21013B0B3921056E0E49131101120740187A190000021101250E130B030E1B0E1101120710170000032E003F19030E3A0B3B0B390B49131101120740187C1900000424000B0B3E0B0308000000
+ - Name: .debug_aranges
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2C00000002000000000008000000000072054000000000002A0000000000000000000000000000000000000000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 5600000002001F0000000101FB0E0D00010101010000000100000100746573742E6370700000000000050C000902720540000000000001050913050159050C22050913050159050C22050D9105167405175805012F0207000101
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F3130315F696D706C696369745F636F6E73742F6E657700666F6F3200746573742E63707000474E5520432B2B313420382E302E3120323031383033313920286578706572696D656E74616C29202D6D74756E653D67656E65726963202D6D617263683D7838362D3634202D67202D6764776172662D3500666F6F31005F5A34666F6F3176006D61696E005F5A34666F6F327600
+Symbols:
+...
diff --git a/lit/Breakpoint/Inputs/single-file-split-dwarf.o.yaml b/lit/Breakpoint/Inputs/single-file-split-dwarf.o.yaml
new file mode 100644
index 000000000000..5adc9d82fcad
--- /dev/null
+++ b/lit/Breakpoint/Inputs/single-file-split-dwarf.o.yaml
@@ -0,0 +1,84 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000010
+ Content: 554889E531C0C745FC000000005DC390554889E55DC3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 0C000000050000000000000000000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 746573742E6F002F686F6D652F756D622F74657374735F323031382F39355F6C6C64622F726570726F2F6477617266355F73706C69745F73696E676C655F66696C652F707265706172655F73616D706C65006D61696E00666F6F005F5A33666F6F7600696E7400
+ - Name: .debug_loc.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 01110010177217B042251B25B44219B3421711011206000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2B00000005000408000000003F4B7684A29835B9010000000000000000000100000000000000000000000016000000
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_str_offsets.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 200000000500000000000000070000002A00000033000000380000003C00000044000000
+ - Name: .debug_str.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 746573742E6F00636C616E672076657273696F6E20382E302E3020287472756E6B203334323731382900746573742E637070006D61696E00696E74005F5A33666F6F7600666F6F00
+ - Name: .debug_info.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 3600000005000508000000003F4B7684A29835B901000104000202000F0000000156030101350000000301060000000156050601050404050400
+ - Name: .debug_abbrev.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 011101B042252525130503250000022E0011813E1206401803253A0B3B0B49133F190000032E0011813E120640186E2503253A0B3B0B3F19000004240003253E0B0B0B000000
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '140000000500080000000000000000000000000000000000'
+ - Name: .debug_names
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000004
+ Content: A00000000500000001000000000000000000000004000000040000000D000000080000004C4C564D3037303000000000010000000200000003000000040000003080880B8973880B6A7F9A7C0B3D06B5000000000000000000000000000000000000000009000000120000001B0000002E2E03130000242403130000002435000000000000002E29000000000000002E1A000000000000002E2900000000000000000000
+ - Name: .debug_gnu_pubnames
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 210000000200000000002F0000002900000030666F6F001A000000306D61696E0000000000
+ - Name: .debug_gnu_pubtypes
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 170000000200000000002F0000003500000090696E740000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 70000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E020000000000FD7C0F2E46BA561F7BDA351B04E677090000000000FD7C0F2E46BA561F7BDA351B04E6770900090200000000000000000105030AC905003F05010A4B0202000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F39355F6C6C64622F726570726F2F6477617266355F73706C69745F73696E676C655F66696C652F707265706172655F73616D706C6500746573742E63707000
+...
diff --git a/lit/Breakpoint/Inputs/single-file-split-dwarf.yaml b/lit/Breakpoint/Inputs/single-file-split-dwarf.yaml
new file mode 100644
index 000000000000..da3e160a26e5
--- /dev/null
+++ b/lit/Breakpoint/Inputs/single-file-split-dwarf.yaml
@@ -0,0 +1,61 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400440
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400440
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0B005400048C7C14005400048C7C720054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89660F1F840000000000554889E531C0C745FC000000005DC390554889E55DC3662E0F1F840000000000415741564189FF415541544C8D25B618000055488D2DB6180000534989F64989D54C29E54883EC0848C1FD03E87FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 0C000000050000000000000007000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 746573742E6F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006D61696E00666F6F005F5A33666F6F7600696E7400
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 01110010177217B042251B25B44219B3421711011206000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2B00000005000408000000003F4B7684A29835B9010000000008000000000108000000200540000000000016000000
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '140000000500080020054000000000003005400000000000'
+ - Name: .debug_names
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000004
+ Content: A00000000500000001000000000000000000000004000000040000000D000000080000004C4C564D3037303000000000010000000200000003000000040000003080880B8973880B6A7F9A7C0B3D06B56300000057000000520000005B0000000000000009000000120000001B0000002E2E03130000242403130000002435000000000000002E29000000000000002E1A000000000000002E2900000000000000000000
+ - Name: .debug_gnu_pubnames
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 210000000200000000002F0000002900000030666F6F001A000000306D61696E0000000000
+ - Name: .debug_gnu_pubtypes
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 170000000200000000002F0000003500000090696E740000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 70000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E024B00000000FD7C0F2E46BA561F7BDA351B04E677094B00000000FD7C0F2E46BA561F7BDA351B04E6770900090220054000000000000105030AC905003F05010A4B0202000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000746573742E63707000
+...
diff --git a/lit/Breakpoint/Inputs/split-dwarf-5-addrbase.dwo.yaml b/lit/Breakpoint/Inputs/split-dwarf-5-addrbase.dwo.yaml
new file mode 100644
index 000000000000..acacc9b95370
--- /dev/null
+++ b/lit/Breakpoint/Inputs/split-dwarf-5-addrbase.dwo.yaml
@@ -0,0 +1,35 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_loc.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .debug_str_offsets.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 200000000500000000000000090000002C000000340000003C0000004000000045000000
+ - Name: .debug_str.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 746573742E64776F00636C616E672076657273696F6E20382E302E3020287472756E6B203334373239392900746573742E6363005F5A3362617A760062617A006D61696E00696E7400
+ - Name: .debug_info.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 360000000500050800000000E93484C441B7E84A01000104000202000600000001560304010103011C0000000156050104350000000406050400
+ - Name: .debug_abbrev.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 011101B042252525130503250000022E00111B120640186E2503253A0B3B0B3F190000032E00111B1206401803253A0B3B0B49133F19000004240003253E0B0B0B000000
+Symbols: {}
+DynamicSymbols: {}
+...
diff --git a/lit/Breakpoint/Inputs/split-dwarf-5-addrbase.yaml b/lit/Breakpoint/Inputs/split-dwarf-5-addrbase.yaml
new file mode 100644
index 000000000000..3a362b0d02dd
--- /dev/null
+++ b/lit/Breakpoint/Inputs/split-dwarf-5-addrbase.yaml
@@ -0,0 +1,61 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400440
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400440
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0C005400048C7C15005400048C7C730054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89660F1F840000000000554889E55DC3662E0F1F840000000000554889E54883EC10C745FC00000000E8DCFFFFFF31C04883C4105DC30F1F4000415741564189FF415541544C8D25A618000055488D2DA6180000534989F64989D54C29E54883EC0848C1FD03E86FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 0C000000050000000000000009000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 746573742E64776F002F686F6D652F756D622F74657374735F323031382F3132322F69737375652F6477617266355F73706C69740062617A005F5A3362617A76006D61696E00696E7400
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 01110010177217B042251B25B442197317111B1206000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 240000000500040800000000E93484C441B7E84A010000000008000000000108000000002C000000
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '140000000500080020054000000000003005400000000000'
+ - Name: .debug_names
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000004
+ Content: A00000000500000001000000000000000000000004000000040000000D000000080000004C4C564D3037303000000000010000000000000003000000000000003080880B64D103B5C260880B6A7F9A7C460000003900000035000000410000000000000009000000120000001B0000002E2E03130000242403130000002435000000000000002E1A000000000000002E1A000000000000002E2600000000000000000000
+ - Name: .debug_gnu_pubnames
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 210000000200000000002800000026000000306D61696E001A0000003062617A0000000000
+ - Name: .debug_gnu_pubtypes
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '17000000020000000000280000003500000090696E740000000000'
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 71000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E022C000000004B61BD987753AF9C38389263DC08E24F2C000000004B61BD987753AF9C38389263DC08E24F00090220054000000000000105010A4B0500BC05030AE5750206000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F74657374735F323031382F3132322F69737375652F6477617266355F73706C697400746573742E636300
+
diff --git a/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file1.dwo.yaml b/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file1.dwo.yaml
new file mode 100644
index 000000000000..6346f6c8eac7
--- /dev/null
+++ b/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file1.dwo.yaml
@@ -0,0 +1,40 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_loc.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .debug_str_offsets.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 5C00000005000000000000000A0000002D000000370000004000000050000000520000005A000000600000006200000066000000760000007F000000840000008A0000008F0000009400000096000000990000009C000000A5000000B5000000
+ - Name: .debug_str.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 66696C65312E64776F00636C616E672076657273696F6E20382E302E3020287472756E6B20333437323939290066696C65312E637070007E73747275637431005F5A4E37737472756374313166457600660073747275637431005F5A316776006700696E74005F5A4E377374727563743144324576005F5A347465737476007465737400666C6F6174006D61696E00746869730078007331007332007E73747275637432005F5A4E377374727563743231664576007374727563743200
+ - Name: .debug_info.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: D900000005000508000000008D03E0CB5B41F18901000104000202000B000000015607080103B400000003040601020104030202054000000000060405020300072A00000008013200000001565800000001070A30000000090291780FBC0000000A000B029174100108B400000000000C02060000000156010B3A00000002030900000001560B0C010DB80000000D046E00000001560E0111B40000000B0291781101152A0000000B029170120116C1000000000E0905040E0D0404072A0000000304150102060413020705D70000000006140502080007C100000000
+ - Name: .debug_abbrev.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 011101B042252525130503250000022E00111B120640186E2503253A0B3B0B49133F190000031301360B03250B0B3A0B3B0B0000042E0103253A0B3B0B3C193F190000050500491334190000062E006E2503253A0B3B0B3C193F190000070F0049130000082E01111B1206401864133A0B3B0B6E2547130000090500021803254913341900000A0B01552300000B3400021803253A0B3B0B491300000C2E00111B120640183A0B3B0B471300000D2E01111B1206401803253A0B3B0B49133F1900000E240003253E0B0B0B000000
+ - Name: .debug_rnglists.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 150000000500080001000000040000000101040C1F04253200
+Symbols: {}
+DynamicSymbols: {}
+...
diff --git a/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file2.dwo.yaml b/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file2.dwo.yaml
new file mode 100644
index 000000000000..b506415ef8b4
--- /dev/null
+++ b/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-file2.dwo.yaml
@@ -0,0 +1,40 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_loc.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .debug_str_offsets.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 3000000005000000000000000A0000002D000000370000004000000050000000520000005A0000006A0000006F00000071000000
+ - Name: .debug_str.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE, SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 66696C65322E64776F00636C616E672076657273696F6E20382E302E3020287472756E6B20333437323939290066696C65322E637070007E73747275637432005F5A4E37737472756374323166457600660073747275637432005F5A4E3773747275637432443245760074686973007800696E7400
+ - Name: .debug_info.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 740000000500050800000000B90811685AA26A1801000104000202040601020603030207043000000000050405020800061A0000000700320000000156480000000103072000000008029178086E00000009000A0291740901047300000000000B0106000000015601072A000000061A0000000C0A050400
+ - Name: .debug_abbrev.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 011101B042252525130503250000021301360B03250B0B3A0B3B0B0000032E0103253A0B3B0B3C193F190000040500491334190000052E006E2503253A0B3B0B3C193F190000060F0049130000072E01111B1206401864133A0B3B0B6E254713000008050002180325491334190000090B01552300000A3400021803253A0B3B0B491300000B2E00111B120640183A0B3B0B471300000C240003253E0B0B0B000000
+ - Name: .debug_rnglists.dwo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXCLUDE ]
+ AddressAlign: 0x0000000000000001
+ Content: 150000000500080001000000040000000100040C1F04253200
+Symbols: {}
+DynamicSymbols: {}
+...
diff --git a/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-main.yaml b/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-main.yaml
new file mode 100644
index 000000000000..ee998b4969f5
--- /dev/null
+++ b/lit/Breakpoint/Inputs/split-dwarf5-debug-stroffsets-main.yaml
@@ -0,0 +1,70 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400630
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400630
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0C008400048C7C15008400048C7C790074000E877FFFFFFF4660F1F44000055B840204000483D402040004889E57417B8000000004885C0740D5DBF40204000FFE00F1F4400005DC3660F1F440000BE40204000554881EE402040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF40204000FFE00F1F005DC3660F1F440000803D69190000007517554889E5E87EFFFFFFC60557190000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89900F1F840000000000554889E5B8010000005DC30F1F440000554889E54883EC2048897DF8E8DFFFFFFF8945F0E9000000008B45F08945F44883C4205DC389D14889C7894DECE80E00000066666666662E0F1F84000000000050E88AFEFFFF48890424E891FEFFFF90554889E55DC3662E0F1F840000000000554889E50F57C05DC30F1F8000000000554889E54883EC20C745FC00000000E8CCFFFFFFE897000000E8D2FFFFFFF30F1145E0E900000000C745FC00000000488D7DF0E838000000488D7DF8E84FFFFFFF8B45FC4883C4205DC389D1488945E8894DE4488D7DF0E814000000488D7DF8E82BFFFFFF488B7DE8E812FEFFFF6690554889E54883EC2048897DF8E8FFFEFFFF8945F0E9000000008B45F08945F44883C4205DC389D14889C7894DECE82EFFFFFF66666666662E0F1F840000000000554889E55DC3662E0F1F840000000000415741564189FF415541544C8D257615000055488D2D76150000534989F64989D54C29E54883EC0848C1FD03E81FFDFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .eh_frame_hdr
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0000000000400B1C
+ AddressAlign: 0x0000000000000004
+ Content: 011B033BE8FDFFFF0C000000A4FAFFFF04FFFFFF14FBFFFF44FFFFFFF4FBFFFF04FEFFFF04FCFFFF7CFFFFFF44FCFFFF24FEFFFF54FCFFFF3CFEFFFF64FCFFFF5CFEFFFF74FCFFFFA4FFFFFFE4FCFFFFD4FFFFFF24FDFFFF7CFEFFFF34FDFFFFA4FEFFFFA4FDFFFFECFEFFFF
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 0C00000005000000000000000A0000000C000000050000008F0000000A000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 66696C65312E64776F000000000000000000000000000000000000000000000000000000000000000000000000000067005F5A3167760073747275637431007E73747275637431005F5A4E3773747275637431443245760066005F5A4E3773747275637431316645760074657374005F5A347465737476006D61696E00696E7400666C6F617400737472756374320066696C65322E64776F007E73747275637432005F5A4E377374727563743244324576005F5A4E37737472756374323166457600
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 01110010177217B042251B25B44219731711015523741700000001110010177217B042251B25B442197317110155237417000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2C00000005000408000000008D03E0CB5B41F1890100000000080000000001080000000000000000000000000C0000002C000000050004081A000000B90811685AA26A1801F4000000180000000001380000000000000000000000002C000000
+ - Name: .debug_rnglists
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 1C00000005000800010000000400000003000B03013203020603030903046E001300000005000800010000000400000003003203010600
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '0000'
+ - Name: .debug_addr
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 2C0000000500080010074000000000002007400000000000700740000000000080074000000000009007400000000000140000000500080000084000000000004008400000000000
+ - Name: .debug_names
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000004
+ Content: 84010000050000000100000000000000000000000D0000000D00000013000000080000004C4C564D3037303000000000000000000000000001000000050000000600000007000000000000000800000000000000000000000B0000000C0000000D0000006CDCF90ECAA55B7A6A7F9A7C1B1710AF1C1710AF0BB602000CB602003080880B88F31A59AB8B407A65689E7C798A6A6F9BE1710F3100000048000000780000003700000087000000580000002F0000007D0000006F0000005A0000006A0000003F000000810000000000000009000000120000001B000000240000002D000000360000003F00000048000000510000005A000000630000006C0000002E2E03130000242403130000131303130000002E1A000000000000002E45000000000000002E8E00000000000000132A0000000000000013C1000000000000002E70000000000000002E1A0000000000000024B4000000000000002E7E000000000000002E70000000000000002E7E000000000000002E450000000000000024B800000000000000D800000005000000010000000000000000000000060000000600000013000000080000004C4C564D30373030300000000100000002000000030000000500000006000000000000007A8A6A6F4BBE6D7A3080880B1C1710AF0BB602002CA4527A99000000A20000007D0000008700000058000000B20000000000000009000000120000001B000000240000002D0000002E2E03130000242403130000131303130000002E35000000000000002E3500000000000000247300000000000000131A000000000000002E60000000000000002E6000000000000000000000
+ - Name: .debug_gnu_pubnames
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 50000000020000000000300000007000000030737472756374313A3A66007E0000003074657374008E000000306D61696E001A0000003067004500000030737472756374313A3A7E73747275637431000000000035000000020030000000300000003500000030737472756374323A3A7E73747275637432006000000030737472756374323A3A660000000000
+ - Name: .debug_gnu_pubtypes
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 3C000000020000000000300000002A000000107374727563743100B800000090666C6F617400C1000000107374727563743200B400000090696E74000000000024000000020030000000300000001A0000001073747275637432007300000090696E740000000000
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: F00000000500080065000000010101FB0E0D00010101010000000100000101011F02000000002500000003011F020F051E0327000000004195A4D2AC12B4F174DBFAD42A0CB9B227000000004195A4D2AC12B4F174DBFAD42A0CB9B2310000000193DBF7D5AE9184526D2D968251B49D0200090210074000000000001405030A4B0207000101000902200740000000000018050B0ABB060378C80507440501063D050B65020D0001010009027007400000000000030A0105140A4A02020001010009028007400000000000030C0105020A4B0205000101000902900740000000000003100105030AE5595DE6050175023F000101A30000000500080065000000010101FB0E0D00010101010000000100000101011F02000000002500000003011F020F051E03390000000040CCBAC21BCB1E430C6A1484F8570F05390000000040CCBAC21BCB1E430C6A1484F8570F05310000000193DBF7D5AE9184526D2D968251B49D02000902000840000000000014050B0ABB06C40507400501063D050B65020D00010100090240084000000000001805140A4A0202000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 000000000000000000000000000000000000000000000000000000000000000000000000002E0066696C65312E637070006465636C732E680066696C65322E63707000
diff --git a/lit/Breakpoint/case-insensitive.test b/lit/Breakpoint/case-insensitive.test
index 841448c42990..f6330b5f4320 100644
--- a/lit/Breakpoint/case-insensitive.test
+++ b/lit/Breakpoint/case-insensitive.test
@@ -1,8 +1,6 @@
-# REQUIRES: windows
-# XFAIL: windows
-# -> llvm.org/pr24528
-#
-# RUN: %cc %p/Inputs/case-sensitive.c -g -o %t
+# REQUIRES: system-windows
+
+# RUN: %build %p/Inputs/case-sensitive.c --nodefaultlib -o %t
# RUN: lldb-test breakpoints %t %s | FileCheck %s
breakpoint set -f case-sensitive.c -l 3
diff --git a/lit/Breakpoint/case-sensitive.test b/lit/Breakpoint/case-sensitive.test
index dd5635b952d6..3f47974c295d 100644
--- a/lit/Breakpoint/case-sensitive.test
+++ b/lit/Breakpoint/case-sensitive.test
@@ -1,6 +1,6 @@
# REQUIRES: nowindows
#
-# RUN: %cc %p/Inputs/case-sensitive.c -g -o %t
+# RUN: %build %p/Inputs/case-sensitive.c --nodefaultlib -o %t
# RUN: lldb-test breakpoints %t %s | FileCheck %s
breakpoint set -f case-sensitive.c -l 3
diff --git a/lit/Breakpoint/debug_addrx.test b/lit/Breakpoint/debug_addrx.test
new file mode 100644
index 000000000000..d5813cb96686
--- /dev/null
+++ b/lit/Breakpoint/debug_addrx.test
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %p/Inputs/debug_addrx.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# The following code and invocation were used.
+# clang -gdwarf-5 test.cc -o test_v5 -fuse-ld=lld -fno-rtti -O2 -ffunction-sections
+# Then output was converted to yaml and reduced.
+#
+# struct A {
+# void foo() {};
+# };
+#
+# void bar(struct A a) {
+# a.foo();
+# }
+#
+# int main() {
+# A objA;
+# bar(objA);
+#
+# return 0;
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 344834)
+#
+# Output file contains DW_FORM_addrx forms.
+
+b bar
+
+# CHECK-LABEL: b bar
+# CHECK: Address: {{.*}}`bar(A) at test.cc:15:1
diff --git a/lit/Breakpoint/debug_rnglist_basic.test b/lit/Breakpoint/debug_rnglist_basic.test
new file mode 100644
index 000000000000..268e4a0ed301
--- /dev/null
+++ b/lit/Breakpoint/debug_rnglist_basic.test
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %p/Inputs/debug_rnglist_basic.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# The following code and invocation were used to produce yaml file,
+# which was manually reduced after that.
+# clang -O0 -gdwarf-5 test.cpp -o test -fuse-ld=lld -ffunction-sections
+#
+# //test.cpp:
+# int zed() {
+# return 1;
+# }
+#
+# int main() {
+# return zed();
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 343487)
+#
+# Output file contains .debug_rnglists section with basic entries:
+# DW_RLE_start_length and DW_RLE_end_of_list.
+# If LLDB would not be able to parse the section and entries correctly,
+# then reported location would be incorrect.
+
+b main
+# CHECK-LABEL: b main
+# CHECK: Address: {{.*}}`main + 15 at test.cpp:6:9
+
+b zed
+# CHECK-LABEL: b zed
+# CHECK: Address: {{.*}}`zed() + 4 at test.cpp:2:2
diff --git a/lit/Breakpoint/debug_rnglist_offset_pair.test b/lit/Breakpoint/debug_rnglist_offset_pair.test
new file mode 100644
index 000000000000..8edf3ee4f000
--- /dev/null
+++ b/lit/Breakpoint/debug_rnglist_offset_pair.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %p/Inputs/debug_rnglist_offset_pair.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# The following code and invocation were used to produce asm file,
+# which was manually edited to add DW_RLE_base_address entry.
+# clang -S -g -gdwarf-5 -O1 test.cpp -o test.s
+# Then it was compiled and converted to yaml.
+#
+# int C = 0;
+# void foo(int P)
+# {
+# for (int I = 0; I < 2; ++I) {
+# int *W = &C;
+# *W &= P;
+# }
+# }
+#
+# int main ()
+# {
+# foo (1);
+# return 0;
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 344035)
+#
+# Output file contains .debug_rnglists section with entries:
+# DW_RLE_offset_pair and DW_RLE_base_address.
+
+b foo
+# CHECK-LABEL: b foo
+# CHECK: Address: {{.*}}`foo(int) + 5 at test.cpp:8:8
+
+
diff --git a/lit/Breakpoint/debug_rnglist_rlestartend.test b/lit/Breakpoint/debug_rnglist_rlestartend.test
new file mode 100644
index 000000000000..9c8beb82c529
--- /dev/null
+++ b/lit/Breakpoint/debug_rnglist_rlestartend.test
@@ -0,0 +1,28 @@
+# RUN: yaml2obj %p/Inputs/debug_rnglist_rlestartend.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# Test shows that LDLB is able to handle DW_RLE_start_end entries properly.
+
+# The following code and invocation were used to produce asm file.
+# clang -O0 -gdwarf-5 test.cpp -S -o test.s -fuse-ld=lld -ffunction-sections
+# It was edited to use DW_RLE_start_end, compiled and converted to yaml.
+# The yaml was manually reduced.
+#
+# //test.cpp:
+# int zed() {
+# return 1;
+# }
+#
+# int main() {
+# return zed();
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 344035)
+
+b main
+# CHECK-LABEL: b main
+# CHECK: Address: {{.*}}`main + 15 at test.cpp:6:10
+
+b zed
+# CHECK-LABEL: b zed
+# CHECK: Address: {{.*}}`zed() + 4 at test.cpp:2:3
diff --git a/lit/Breakpoint/debug_rnglistx_rlex.test b/lit/Breakpoint/debug_rnglistx_rlex.test
new file mode 100644
index 000000000000..79a80479e72c
--- /dev/null
+++ b/lit/Breakpoint/debug_rnglistx_rlex.test
@@ -0,0 +1,28 @@
+# RUN: yaml2obj %p/Inputs/debug_rnglistx_rlex.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+# The following code and invocation were used.
+# clang -gdwarf-5 test.cc -o test_v5 -fuse-ld=lld -fno-rtti -O2 -ffunction-sections
+# Then output was converted to yaml and reduced.
+#
+# int bar(int x) {
+# return ++x;
+# }
+#
+# int main() {
+# int y = 1;
+# return bar(y);
+# }
+#
+# clang and LLD versions were 8.0.0 (trunk 345699)
+#
+# Output file contains DW_FORM_rnglistx and DW_RLE_startx_length.
+
+b bar
+b main
+
+# CHECK-LABEL: b bar
+# CHECK: Address: {{.*}}`bar(int) at test.cc:4:11
+
+# CHECK-LABEL: b main
+# CHECK: Address: {{.*}}`main at test.cc:9:3
diff --git a/lit/Breakpoint/implicit_const_form_support.test b/lit/Breakpoint/implicit_const_form_support.test
new file mode 100644
index 000000000000..183181d2f307
--- /dev/null
+++ b/lit/Breakpoint/implicit_const_form_support.test
@@ -0,0 +1,33 @@
+# RUN: yaml2obj %p/Inputs/implicit_const_form_support.yaml > %ttest
+# RUN: lldb-test breakpoints %ttest %s | FileCheck %s
+
+## The intention of the test is to check that DW_FORM_implicit_const
+## is supported and handled properly.
+
+## About implicit_const_form_support.yaml:
+## The following invocation and code were used to produce the binary
+## which was converted to yaml and reduced:
+## gcc version 8.0.1 20180319 (experimental) (GCC)
+##
+## g++ test.cpp -g -gdwarf-5 -o test
+##
+## // test.cpp
+## int foo1() {
+## return 0;
+## }
+##
+## int foo2() {
+## return 0;
+## }
+##
+## int main() {
+## return foo1() + foo2();
+## }
+
+b foo1
+# CHECK-LABEL: b foo1
+# CHECK: Address: {{.*}}foo1() at test.cpp:2:9
+
+b foo2
+# CHECK-LABEL: b foo2
+# CHECK: Address: {{.*}}foo2() at test.cpp:6:9
diff --git a/lit/Breakpoint/single-file-split-dwarf.test b/lit/Breakpoint/single-file-split-dwarf.test
new file mode 100644
index 000000000000..d0cc003bf210
--- /dev/null
+++ b/lit/Breakpoint/single-file-split-dwarf.test
@@ -0,0 +1,44 @@
+# RUN: rm -rf %t.dir
+# RUN: mkdir %t.dir
+# RUN: cd %t.dir
+# RUN: yaml2obj %p/Inputs/single-file-split-dwarf.yaml > %t.dir/test
+# RUN: yaml2obj %p/Inputs/single-file-split-dwarf.o.yaml > %t.dir/test.o
+# RUN: lldb-test breakpoints %t.dir/test %s | FileCheck %s
+
+# This test checks that source code location is shown correctly
+# when single split file debug information is used (when .dwo sections are in .o files).
+#
+# single-file-split-dwarf.yaml and single-file-split-dwarf.o.yaml are
+# reduced yaml files produces from the object file and the corresponding executable.
+#
+# The following code was used initially:
+# int main() {
+# return 0;
+# }
+#
+# void foo() {
+# }
+#
+# Invocation used to produce .o file was:
+# clang test.cpp -gdwarf-5 -gsplit-dwarf=single -c -o test.o -v
+#
+# The full invocation used to produce the executable was:
+# "/usr/local/bin/ld" -z relro --hash-style=gnu --eh-frame-hdr -m elf_x86_64 -dynamic-linker
+# /lib64/ld-linux-x86-64.so.2 -o test /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crt1.o
+# /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/7.3.0/crtbegin.o
+# -L/usr/lib/gcc/x86_64-linux-gnu/7.3.0 -L/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu
+# -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../..
+# -L/home/umb/LLVM/build/bin/../lib -L/lib -L/usr/lib test.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc
+# --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/7.3.0/crtend.o
+# /usr/lib/gcc/x86_64-linux-gnu/7.3.0/../../../x86_64-linux-gnu/crtn.o
+#
+# Also, the DW_AT_comp_dir string value set to empty in yaml produced.
+# Build bots had different path there and failed to find object.
+
+b main
+# CHECK-LABEL: b main
+# CHECK: Address: {{.*}}main + 13 at test.cpp:2:3
+
+b foo
+# CHECK-LABEL: b foo
+# CHECK: Address: {{.*}}foo() + 4 at test.cpp:6:1
diff --git a/lit/Breakpoint/split-dwarf-5-addrbase.test b/lit/Breakpoint/split-dwarf-5-addrbase.test
new file mode 100644
index 000000000000..72a717d609dc
--- /dev/null
+++ b/lit/Breakpoint/split-dwarf-5-addrbase.test
@@ -0,0 +1,30 @@
+# RUN: rm -rf %t.dir
+# RUN: mkdir %t.dir
+# RUN: cd %t.dir
+# RUN: yaml2obj %p/Inputs/split-dwarf-5-addrbase.dwo.yaml > %t.dir/test.dwo
+# RUN: yaml2obj %p/Inputs/split-dwarf-5-addrbase.yaml > %t.dir/test
+# RUN: lldb-test breakpoints %t.dir/test %s | FileCheck %s
+
+# This test checks that source code location is shown correctly
+# when -gsplit-dwarf and DWARF 5 are used.
+#
+# split-dwarf-5-addrbase.dwo.yaml and split-dwarf-5-addrbase.yamlare
+# reduced yaml files produces from the dwo file and the corresponding executable.
+#
+# The following code was used initially:
+# void baz() {
+# }
+#
+# int main() {
+# baz();
+# return 0;
+# }
+#
+# Invocation used to produce outputs was:
+# clang test.cc -g -fno-rtti -c -gdwarf-5 -gsplit-dwarf
+# clang test.o -g -fno-rtti -gdwarf-5 -o test -gsplit-dwarf
+# clang version 8.0.0 (trunk 347299)
+
+b baz
+# CHECK-LABEL: b baz
+# CHECK: Address: {{.*}}baz() + 4 at test.cc:2:1
diff --git a/lit/Breakpoint/split-dwarf5-debug-stroffsets.test b/lit/Breakpoint/split-dwarf5-debug-stroffsets.test
new file mode 100644
index 000000000000..c1418ebb0d52
--- /dev/null
+++ b/lit/Breakpoint/split-dwarf5-debug-stroffsets.test
@@ -0,0 +1,84 @@
+# RUN: rm -rf %t.dir
+# RUN: mkdir %t.dir
+# RUN: cd %t.dir
+# RUN: yaml2obj %p/Inputs/split-dwarf5-debug-stroffsets-file1.dwo.yaml > %t.dir/file1.dwo
+# RUN: yaml2obj %p/Inputs/split-dwarf5-debug-stroffsets-file2.dwo.yaml > %t.dir/file2.dwo
+# RUN: yaml2obj %p/Inputs/split-dwarf5-debug-stroffsets-main.yaml > %t.dir/test
+# RUN: lldb-test breakpoints %t.dir/test %s | FileCheck %s
+
+# This test checks that source code location is shown correctly
+# when split DWARF 5 is used and both DWO/executable file contains
+# .debug_str_offsets/.debug_str_offsets.dwo sections.
+# Used clang version 8.0.0 (trunk 347299)
+#
+# split-dwarf5-debug-stroffsets-file1.dwo.yaml, split-dwarf5-debug-stroffsets-file2.dwo.yaml
+# and split-dwarf5-debug-stroffsets-main.yaml are reduced yaml files produces
+# from the DWO files and the corresponding executable.
+#
+# Code:
+# // decl.h
+# struct struct1 {
+# ~struct1();
+# static void f();
+# };
+#
+# struct struct2 {
+# ~struct2();
+# static void f();
+# };
+#
+# int g();
+#
+# // file1.cpp
+# #include "decls.h"
+#
+# int g() {
+# return 1;
+# }
+#
+# struct1::~struct1() {
+# int x = g();
+# }
+#
+# void struct1::f() {}
+#
+# float test() {
+# return 0.0f;
+# }
+#
+# int main() {
+# struct1::f();
+# struct2::f();
+#
+# struct1 s1;
+# struct2 s2;
+#
+# test();
+#
+# return 0;
+# }
+#
+# // file2.cpp
+#
+#
+# #include "decls.h"
+#
+# struct2::~struct2() {
+# int x = g();
+# }
+#
+# void struct2::f() {}
+#
+#
+# Invocation used was:
+# clang++ file1.cpp -o file1.o -g -fno-rtti -c -gdwarf-5 -gsplit-dwarf -ffunction-sections
+# clang++ file2.cpp -o file2.o -g -fno-rtti -c -gdwarf-5 -gsplit-dwarf -ffunction-sections
+# clang++ file1.o file2.o -g -fno-rtti -gdwarf-5 -o test -gsplit-dwarf -ffunction-sections
+
+b struct1::f
+# CHECK-LABEL: b struct1::f
+# CHECK: Address: {{.*}}struct1::f() + 4 at file1.cpp:11:20
+
+b struct2::f
+# CHECK-LABEL: b struct2::f
+# CHECK: Address: {{.*}}struct2::f() + 4 at file2.cpp:7:20
diff --git a/lit/BuildScript/modes.test b/lit/BuildScript/modes.test
new file mode 100644
index 000000000000..02311f712d77
--- /dev/null
+++ b/lit/BuildScript/modes.test
@@ -0,0 +1,35 @@
+RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \
+RUN: | FileCheck --check-prefix=COMPILE %s
+
+RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \
+RUN: | FileCheck --check-prefix=COMPILE-MULTI %s
+
+RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foo.exe foobar.obj \
+RUN: | FileCheck --check-prefix=LINK %s
+
+RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foobar.exe foo.obj bar.obj \
+RUN: | FileCheck --check-prefix=LINK-MULTI %s
+
+RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foobar.c \
+RUN: | FileCheck --check-prefix=BOTH %s
+
+RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foo.c bar.c \
+RUN: | FileCheck --check-prefix=BOTH-MULTI %s
+
+
+COMPILE: compiling foobar.c -> foo.out
+
+COMPILE-MULTI: compiling foo.c -> foo.o{{(bj)?}}
+COMPILE-MULTI: compiling bar.c -> bar.o{{(bj)?}}
+
+
+LINK: linking foobar.obj -> foo.exe
+
+LINK-MULTI: linking foo.obj+bar.obj -> foobar.exe
+
+BOTH: compiling foobar.c -> [[OBJFOO:foobar.exe-foobar.o(bj)?]]
+BOTH: linking [[OBJFOO]] -> foobar.exe
+
+BOTH-MULTI: compiling foo.c -> [[OBJFOO:foobar.exe-foo.o(bj)?]]
+BOTH-MULTI: compiling bar.c -> [[OBJBAR:foobar.exe-bar.o(bj)?]]
+BOTH-MULTI: linking [[OBJFOO]]+[[OBJBAR]] -> foobar.exe
diff --git a/lit/BuildScript/script-args.test b/lit/BuildScript/script-args.test
new file mode 100644
index 000000000000..13e8a5160942
--- /dev/null
+++ b/lit/BuildScript/script-args.test
@@ -0,0 +1,32 @@
+RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \
+RUN: | FileCheck %s
+RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \
+RUN: | FileCheck --check-prefix=MULTI-INPUT %s
+
+
+CHECK: Script Arguments:
+CHECK-NEXT: Arch: 32
+CHECK: Compiler: any
+CHECK: Outdir: {{.*}}script-args.test.tmp
+CHECK: Output: {{.*}}script-args.test.tmp{{.}}foo.out
+CHECK: Nodefaultlib: False
+CHECK: Opt: none
+CHECK: Mode: compile
+CHECK: Clean: True
+CHECK: Verbose: True
+CHECK: Dryrun: True
+CHECK: Inputs: foobar.c
+
+MULTI-INPUT: Script Arguments:
+MULTI-INPUT-NEXT: Arch: 32
+MULTI-INPUT-NEXT: Compiler: any
+MULTI-INPUT-NEXT: Outdir: {{.*}}script-args.test.tmp
+MULTI-INPUT-NEXT: Output:
+MULTI-INPUT-NEXT: Nodefaultlib: False
+MULTI-INPUT-NEXT: Opt: none
+MULTI-INPUT-NEXT: Mode: compile
+MULTI-INPUT-NEXT: Clean: True
+MULTI-INPUT-NEXT: Verbose: True
+MULTI-INPUT-NEXT: Dryrun: True
+MULTI-INPUT-NEXT: Inputs: foo.c
+MULTI-INPUT-NEXT: bar.c
diff --git a/lit/BuildScript/toolchain-clang-cl.test b/lit/BuildScript/toolchain-clang-cl.test
new file mode 100644
index 000000000000..cc219aca158f
--- /dev/null
+++ b/lit/BuildScript/toolchain-clang-cl.test
@@ -0,0 +1,49 @@
+REQUIRES: lld, system-windows
+
+RUN: %build -n --verbose --arch=32 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \
+RUN: | FileCheck --check-prefix=CHECK-32 %s
+
+RUN: %build -n --verbose --arch=64 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \
+RUN: | FileCheck --check-prefix=CHECK-64 %s
+
+CHECK-32: Script Arguments:
+CHECK-32: Arch: 32
+CHECK-32: Compiler: clang-cl
+CHECK-32: Outdir: {{.*}}
+CHECK-32: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe
+CHECK-32: Nodefaultlib: False
+CHECK-32: Opt: none
+CHECK-32: Mode: compile
+CHECK-32: Clean: True
+CHECK-32: Verbose: True
+CHECK-32: Dryrun: True
+CHECK-32: Inputs: foobar.c
+CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk
+CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe-foobar.obj
+CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb
+CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe
+CHECK-32: compiling foobar.c -> foo.exe-foobar.obj
+CHECK-32: {{.*}}clang-cl{{(.exe)?}} -m32
+CHECK-32: linking foo.exe-foobar.obj -> foo.exe
+CHECK-32: {{.*}}lld-link
+
+CHECK-64: Script Arguments:
+CHECK-64: Arch: 64
+CHECK-64: Compiler: clang-cl
+CHECK-64: Outdir: {{.*}}
+CHECK-64: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe
+CHECK-64: Nodefaultlib: False
+CHECK-64: Opt: none
+CHECK-64: Mode: compile
+CHECK-64: Clean: True
+CHECK-64: Verbose: True
+CHECK-64: Dryrun: True
+CHECK-64: Inputs: foobar.c
+CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk
+CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe-foobar.obj
+CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb
+CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe
+CHECK-64: compiling foobar.c -> foo.exe-foobar.obj
+CHECK-64: {{.*}}clang-cl{{(.exe)?}} -m64
+CHECK-64: linking foo.exe-foobar.obj -> foo.exe
+CHECK-64: {{.*}}lld-link{{(.exe)?}}
diff --git a/lit/BuildScript/toolchain-clang.test b/lit/BuildScript/toolchain-clang.test
new file mode 100644
index 000000000000..416dc30f6c96
--- /dev/null
+++ b/lit/BuildScript/toolchain-clang.test
@@ -0,0 +1,14 @@
+RUN: %build -n --verbose --arch=32 --compiler=clang --mode=compile-and-link -o %t/foo.exe foobar.c \
+RUN: | FileCheck --check-prefix=CHECK --check-prefix=CHECK-32 %s
+
+RUN: %build -n --verbose --arch=64 --compiler=clang --mode=compile-and-link -o %t/foo.exe foobar.c \
+RUN: | FileCheck --check-prefix=CHECK --check-prefix=CHECK-64 %s
+
+CHECK: Cleaning {{.*}}toolchain-clang.test.tmp{{.}}foo.exe-foobar.o
+CHECK: Cleaning {{.*}}toolchain-clang.test.tmp{{.}}foo.exe
+CHECK: compiling foobar.c -> foo.exe-foobar.o
+CHECK-32: {{.*}}clang++{{(.exe)?}} -m32 -g -O0 -c -o {{.*}}foo.exe-foobar.o {{.*}}foobar.c
+CHECK-64: {{.*}}clang++{{(.exe)?}} -m64 -g -O0 -c -o {{.*}}foo.exe-foobar.o {{.*}}foobar.c
+CHECK: linking foo.exe-foobar.o -> foo.exe
+CHECK-32: {{.*}}clang++{{(.exe)?}} -m32 -o {{.*}}foo.exe {{.*}}foo.exe-foobar.o
+CHECK-64: {{.*}}clang++{{(.exe)?}} -m64 -o {{.*}}foo.exe {{.*}}foo.exe-foobar.o
diff --git a/lit/BuildScript/toolchain-msvc.test b/lit/BuildScript/toolchain-msvc.test
new file mode 100644
index 000000000000..85a8f0d62f0c
--- /dev/null
+++ b/lit/BuildScript/toolchain-msvc.test
@@ -0,0 +1,62 @@
+REQUIRES: system-windows, msvc
+
+RUN: %build -n --verbose --arch=32 --compiler=msvc --mode=compile-and-link -o %t/foo.exe foobar.c \
+RUN: | FileCheck --check-prefix=X86 %s
+
+RUN: %build -n --verbose --arch=64 --compiler=msvc --mode=compile-and-link -o %t/foo.exe foobar.c \
+RUN: | FileCheck --check-prefix=X64 %s
+
+X86: Script Arguments:
+X86: Arch: 32
+X86: Compiler: msvc
+X86: Outdir: {{.*}}
+X86: Output: {{.*}}toolchain-msvc.test.tmp\foo.exe
+X86: Nodefaultlib: False
+X86: Opt: none
+X86: Mode: compile
+X86: Clean: True
+X86: Verbose: True
+X86: Dryrun: True
+X86: Inputs: foobar.c
+X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foobar.ilk
+X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.exe-foobar.obj
+X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.pdb
+X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.exe
+X86: compiling foobar.c -> foo.exe-foobar.obj
+X86: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x86\cl.exe
+X86: linking foo.exe-foobar.obj -> foo.exe
+X86: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x86\link.exe
+X86: Env
+X86: LIB = {{.*}}\ATLMFC\lib\x86
+X86: {{.*}}\lib\x86
+X86: {{.*}}\ucrt\x86
+X86: {{.*}}\um\x86
+X86: PATH = {{.*}}\bin\{{[Hh]ost[Xx]64}}\x64
+
+
+X64: Script Arguments:
+X64: Arch: 64
+X64: Compiler: msvc
+X64: Outdir: {{.*}}
+X64: Output: {{.*}}toolchain-msvc.test.tmp\foo.exe
+X64: Nodefaultlib: False
+X64: Opt: none
+X64: Mode: compile
+X64: Clean: True
+X64: Verbose: True
+X64: Dryrun: True
+X64: Inputs: foobar.c
+X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foobar.ilk
+X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.exe-foobar.obj
+X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.pdb
+X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.exe
+X64: compiling foobar.c -> foo.exe-foobar.obj
+X64: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x64\cl.exe
+X64: linking foo.exe-foobar.obj -> foo.exe
+X64: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x64\link.exe
+X64: Env
+X64: LIB = {{.*}}\ATLMFC\lib\x64
+X64: {{.*}}\lib\x64
+X64: {{.*}}\ucrt\x64
+X64: {{.*}}\um\x64
+X64: PATH = {{.*}}\bin\{{[Hh]ost[Xx]64}}\x64
diff --git a/lit/CMakeLists.txt b/lit/CMakeLists.txt
index 8a93236d2cf0..1ac013b2eed3 100644
--- a/lit/CMakeLists.txt
+++ b/lit/CMakeLists.txt
@@ -7,13 +7,9 @@ else ()
set(LLVM_BUILD_MODE "%(build_mode)s")
endif ()
-if (NOT LLDB_TEST_USE_CUSTOM_C_COMPILER)
- string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_C_COMPILER ${LLDB_TEST_C_COMPILER})
-endif ()
-
-if (NOT LLDB_TEST_USE_CUSTOM_CXX_COMPILER)
- string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_CXX_COMPILER ${LLDB_TEST_CXX_COMPILER})
-endif ()
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ set(LLDB_IS_64_BITS 1)
+endif()
get_property(LLDB_DOTEST_ARGS GLOBAL PROPERTY LLDB_DOTEST_ARGS_PROPERTY)
@@ -24,56 +20,43 @@ string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_DOTEST_ARGS "${LLDB_D
list(APPEND LLDB_TEST_DEPS
LLDBUnitTests
dsymutil
+ llc
lldb
lldb-test
llvm-config
llvm-mc
llvm-objcopy
+ FileCheck
+ count
+ not
)
if(TARGET lld)
list(APPEND LLDB_TEST_DEPS lld)
- set(LLDB_HAVE_LLD 1)
-else()
- set(LLDB_HAVE_LLD 0)
endif()
-if(BUILD_SHARED_LIBS)
- set(ENABLE_SHARED 1)
-else()
- set(ENABLE_SHARED 0)
-endif(BUILD_SHARED_LIBS)
-
# the value is not canonicalized within LLVM
llvm_canonicalize_cmake_booleans(
LLDB_DISABLE_PYTHON
- LLVM_ENABLE_ZLIB)
+ LLVM_ENABLE_ZLIB
+ LLDB_IS_64_BITS)
configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg)
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
+ MAIN_CONFIG
+ ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py)
configure_lit_site_cfg(
- ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.in
- ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg)
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.site.cfg.py.in
+ ${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg.py
+ MAIN_CONFIG
+ ${CMAKE_CURRENT_SOURCE_DIR}/Unit/lit.cfg.py)
configure_lit_site_cfg(
${CMAKE_CURRENT_SOURCE_DIR}/Suite/lit.site.cfg.in
${CMAKE_CURRENT_BINARY_DIR}/Suite/lit.site.cfg)
-if(NOT LLDB_BUILT_STANDALONE)
- list(APPEND LLDB_TEST_DEPS
- FileCheck
- not
- )
-endif()
-
-set(LLDB_TEST_PARAMS
- lldb_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
- )
-
add_lit_testsuite(check-lldb-lit "Running lldb lit test suite"
${CMAKE_CURRENT_BINARY_DIR}
- PARAMS lldb_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
- lldb_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
DEPENDS ${LLDB_TEST_DEPS}
)
@@ -86,8 +69,6 @@ if (TARGET clang)
endif()
add_lit_testsuites(LLDB
- ${CMAKE_CURRENT_BINARY_DIR}
- PARAMS lldb_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg
- lldb_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg
+ ${CMAKE_CURRENT_SOURCE_DIR}
DEPENDS ${LLDB_TEST_DEPS}
)
diff --git a/lit/Driver/Inputs/Print0.in b/lit/Driver/Inputs/Print0.in
new file mode 100644
index 000000000000..cb545cc15ab0
--- /dev/null
+++ b/lit/Driver/Inputs/Print0.in
@@ -0,0 +1 @@
+expr 0
diff --git a/lit/Driver/Inputs/Print2.in b/lit/Driver/Inputs/Print2.in
new file mode 100644
index 000000000000..f51389a02a07
--- /dev/null
+++ b/lit/Driver/Inputs/Print2.in
@@ -0,0 +1 @@
+expr 2
diff --git a/lit/Driver/Inputs/Print4.in b/lit/Driver/Inputs/Print4.in
new file mode 100644
index 000000000000..a2d49f30b990
--- /dev/null
+++ b/lit/Driver/Inputs/Print4.in
@@ -0,0 +1 @@
+expr 4
diff --git a/lit/Driver/Inputs/Print6.in b/lit/Driver/Inputs/Print6.in
new file mode 100644
index 000000000000..dee6212b87c1
--- /dev/null
+++ b/lit/Driver/Inputs/Print6.in
@@ -0,0 +1 @@
+expr 6
diff --git a/lit/Driver/Inputs/convenience.in b/lit/Driver/Inputs/convenience.in
new file mode 100644
index 000000000000..6d5603c43513
--- /dev/null
+++ b/lit/Driver/Inputs/convenience.in
@@ -0,0 +1,9 @@
+breakpoint set -f hello.cpp -p Hello
+run
+script print(lldb.debugger)
+script print(lldb.target)
+script print(lldb.process)
+script print(lldb.thread.GetStopDescription(100))
+script lldb.frame.GetLineEntry().GetLine()
+script lldb.frame.GetLineEntry().GetFileSpec().GetFilename()
+script lldb.frame.GetFunctionName()
diff --git a/lit/Driver/Inputs/hello.cpp b/lit/Driver/Inputs/hello.cpp
new file mode 100644
index 000000000000..1ec0677aeb2c
--- /dev/null
+++ b/lit/Driver/Inputs/hello.cpp
@@ -0,0 +1,11 @@
+// The build.py script always runs the compiler in C++ mode, regardless of the
+// file extension. This results in mangled names presented to the linker which
+// in turn cannot find the printf symbol.
+extern "C" {
+int printf(const char *format, ...);
+
+int main(int argc, char **argv) {
+ printf("Hello World\n");
+ return 0;
+}
+}
diff --git a/lit/Driver/TestCommands.test b/lit/Driver/TestCommands.test
new file mode 100644
index 000000000000..3589abb8278c
--- /dev/null
+++ b/lit/Driver/TestCommands.test
@@ -0,0 +1,41 @@
+# RUN: %lldb -x -b \
+# RUN: -S %S/Inputs/Print0.in \
+# RUN: -O 'expr 1' \
+# RUN: -S %S/Inputs/Print2.in \
+# RUN: -O 'expr 3' \
+# RUN: -s %S/Inputs/Print4.in \
+# RUN: -o 'expr 5' \
+# RUN: -s %S/Inputs/Print6.in \
+# RUN: -o 'expr 7' \
+# RUN: | FileCheck %s
+#
+# RUN: %lldb -x -b \
+# RUN: -s %S/Inputs/Print4.in \
+# RUN: -o 'expr 5' \
+# RUN: -s %S/Inputs/Print6.in \
+# RUN: -o 'expr 7' \
+# RUN: -S %S/Inputs/Print0.in \
+# RUN: -O 'expr 1' \
+# RUN: -S %S/Inputs/Print2.in \
+# RUN: -O 'expr 3' \
+# RUN: | FileCheck %s
+#
+# RUN: %lldb -x -b \
+# RUN: -s %S/Inputs/Print4.in \
+# RUN: -S %S/Inputs/Print0.in \
+# RUN: -o 'expr 5' \
+# RUN: -O 'expr 1' \
+# RUN: -s %S/Inputs/Print6.in \
+# RUN: -S %S/Inputs/Print2.in \
+# RUN: -o 'expr 7' \
+# RUN: -O 'expr 3' \
+# RUN: | FileCheck %s
+
+# CHECK: (int) $0 = 0
+# CHECK: (int) $1 = 1
+# CHECK: (int) $2 = 2
+# CHECK: (int) $3 = 3
+# CHECK: (int) $4 = 4
+# CHECK: (int) $5 = 5
+# CHECK: (int) $6 = 6
+# CHECK: (int) $7 = 7
diff --git a/lit/Driver/TestConvenienceVariables.test b/lit/Driver/TestConvenienceVariables.test
new file mode 100644
index 000000000000..99536e4c0290
--- /dev/null
+++ b/lit/Driver/TestConvenienceVariables.test
@@ -0,0 +1,22 @@
+RUN: %build %p/Inputs/hello.cpp -o %t
+RUN: %lldb %t -s %p/Inputs/convenience.in -o quit | FileCheck %s
+
+script print(lldb.debugger)
+
+CHECK: stop reason = breakpoint 1.1
+CHECK: Debugger (instance: {{.*}}, id: {{[0-9]+}})
+CHECK: script print(lldb.target)
+CHECK: TestConvenienceVariables.test
+CHECK: script print(lldb.process)
+CHECK: SBProcess: pid = {{[0-9]+}},
+CHECK-SAME: state = stopped,
+CHECK-SAME: threads = {{[0-9]+}},
+CHECK-SAME: executable = TestConvenienceVariables.test
+CHECK: script print(lldb.thread.GetStopDescription(100))
+CHECK: breakpoint 1.1
+CHECK: script lldb.frame.GetLineEntry().GetLine()
+CHECK: 8
+CHECK: script lldb.frame.GetLineEntry().GetFileSpec().GetFilename()
+CHECK: hello.c
+CHECK: script lldb.frame.GetFunctionName()
+CHECK: main \ No newline at end of file
diff --git a/lit/Driver/TestCore.test b/lit/Driver/TestCore.test
new file mode 100644
index 000000000000..cca8171da631
--- /dev/null
+++ b/lit/Driver/TestCore.test
@@ -0,0 +1,2 @@
+# RUN: not %lldb -c /bogus/path 2>&1 | FileCheck %s
+# CHECK: error: file specified in --core (-c) option doesn't exist
diff --git a/lit/Driver/TestFile.test b/lit/Driver/TestFile.test
new file mode 100644
index 000000000000..0e80594aeb1b
--- /dev/null
+++ b/lit/Driver/TestFile.test
@@ -0,0 +1,2 @@
+# RUN: not %lldb -f /bogus/path 2>&1 | FileCheck %s
+# CHECK: error: file specified in --file (-f) option doesn't exist
diff --git a/lit/Driver/TestNoUseColor.test b/lit/Driver/TestNoUseColor.test
new file mode 100644
index 000000000000..62735301fca8
--- /dev/null
+++ b/lit/Driver/TestNoUseColor.test
@@ -0,0 +1,4 @@
+# RUN: %lldb --no-use-color -s %s | FileCheck %s
+settings show use-color
+# CHECK: use-color (boolean) = false
+q
diff --git a/lit/ExecControl/StopHook/Inputs/stop-hook-1.lldbinit b/lit/ExecControl/StopHook/Inputs/stop-hook-1.lldbinit
new file mode 100644
index 000000000000..4ab5d56f0364
--- /dev/null
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook-1.lldbinit
@@ -0,0 +1 @@
+target stop-hook add -n b -o "expr ptr"
diff --git a/lit/ExecControl/StopHook/Inputs/stop-hook-2.lldbinit b/lit/ExecControl/StopHook/Inputs/stop-hook-2.lldbinit
new file mode 100644
index 000000000000..906c18b004df
--- /dev/null
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook-2.lldbinit
@@ -0,0 +1 @@
+target stop-hook add -f stop-hook.c -l 30 -e 34 -o "expr ptr" \ No newline at end of file
diff --git a/lit/ExecControl/StopHook/Inputs/stop-hook-3.lldbinit b/lit/ExecControl/StopHook/Inputs/stop-hook-3.lldbinit
new file mode 100644
index 000000000000..98ed59ca46b2
--- /dev/null
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook-3.lldbinit
@@ -0,0 +1,3 @@
+target stop-hook add -f stop-hook.c -l 30 -e 34
+expr ptr
+DONE \ No newline at end of file
diff --git a/lit/ExecControl/StopHook/Inputs/stop-hook-threads-1.lldbinit b/lit/ExecControl/StopHook/Inputs/stop-hook-threads-1.lldbinit
new file mode 100644
index 000000000000..f192d9952e97
--- /dev/null
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook-threads-1.lldbinit
@@ -0,0 +1,7 @@
+break set -f stop-hook-threads.cpp -p "Break here to test that the stop-hook"
+run
+target stop-hook add
+frame variable --show-globals g_val
+thread list
+continue
+DONE
diff --git a/lit/ExecControl/StopHook/Inputs/stop-hook-threads-2.lldbinit b/lit/ExecControl/StopHook/Inputs/stop-hook-threads-2.lldbinit
new file mode 100644
index 000000000000..467f60b1e1e0
--- /dev/null
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook-threads-2.lldbinit
@@ -0,0 +1,4 @@
+break set -f stop-hook-threads.cpp -p "Break here to test that the stop-hook"
+run
+target stop-hook add -x 2 -o "frame variable thread_index"
+target stop-hook add -o continue
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp b/lit/ExecControl/StopHook/Inputs/stop-hook-threads.cpp
index e193ae18e2c1..dab133d9d952 100644
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/main.cpp
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook-threads.cpp
@@ -14,7 +14,7 @@
#include <thread>
std::default_random_engine g_random_engine{std::random_device{}()};
-std::uniform_int_distribution<> g_distribution{0, 3000000};
+std::uniform_int_distribution<> g_distribution{0, 3000};
uint32_t g_val = 0;
@@ -42,14 +42,14 @@ thread_func (uint32_t thread_index)
uint32_t count = 0;
uint32_t val;
- while (count++ < 15)
+ while (count++ < 4)
{
- // random micro second sleep from zero to 3 seconds
+ // random micro second sleep from zero to .3 seconds
int usec = g_distribution(g_random_engine);
printf ("%s (thread = %u) doing a usleep (%d)...\n", __FUNCTION__, thread_index, usec);
- std::this_thread::sleep_for(std::chrono::microseconds{usec});
+ std::this_thread::sleep_for(std::chrono::microseconds{usec}); // Set break point at this line
- if (count < 7)
+ if (count < 2)
val = access_pool ();
else
val = access_pool (true);
@@ -64,7 +64,6 @@ int main (int argc, char const *argv[])
{
std::thread threads[3];
- printf ("Before turning all three threads loose...\n"); // Set break point at this line, and add a stop-hook.
// Create 3 threads
for (auto &thread : threads)
thread = std::thread{thread_func, std::distance(threads, &thread)};
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp b/lit/ExecControl/StopHook/Inputs/stop-hook.c
index c10c1e5ef0d2..c10c1e5ef0d2 100644
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/main.cpp
+++ b/lit/ExecControl/StopHook/Inputs/stop-hook.c
diff --git a/lit/ExecControl/StopHook/stop-hook-threads.test b/lit/ExecControl/StopHook/stop-hook-threads.test
new file mode 100644
index 000000000000..aa6b668340c7
--- /dev/null
+++ b/lit/ExecControl/StopHook/stop-hook-threads.test
@@ -0,0 +1,33 @@
+# RUN: %clangxx %p/Inputs/stop-hook-threads.cpp -g -o %t
+# RUN: %lldb -b -s %p/Inputs/stop-hook-threads-1.lldbinit -s %s -f %t \
+# RUN: | FileCheck --check-prefix=CHECK --check-prefix=CHECK-NO-FILTER %s
+# RUN: %lldb -b -s %p/Inputs/stop-hook-threads-2.lldbinit -s %s -f %t \
+# RUN: | FileCheck --check-prefix=CHECK --check-prefix=CHECK-FILTER %s
+# XFAIL: system-windows
+
+thread list
+break set -f stop-hook-threads.cpp -p "Set break point at this line"
+target stop-hook list
+
+# CHECK: Hook: 1
+# CHECK-NEXT: State: enabled
+# CHECK-FILTER-NEXT: Thread
+# CHECK-FILTER-NEXT: index: 2
+# CHECK-NEXT: Commands:
+# CHECK-NEXT: frame variable
+
+# CHECK-FILTER: Hook: 2
+# CHECK-FILTER-NEXT: State: enabled
+# CHECK-FILTER-NEXT: Commands:
+# CHECK-FILTER-NEXT: continue
+
+# Get the threads going
+continue
+
+# When we filter per thread, we expect exactly 4 identical "frame var" results
+# CHECK-FILTER: (uint32_t) thread_index = [[THREAD_INDEX:[0-9]*]]
+# CHECK-FILTER-COUNT-3: (uint32_t) thread_index = [[THREAD_INDEX]]
+# CHECK-FILTER-NOT: thread_index
+
+# When we don't filter, we expect to count 12 stopped threads in the thread list output
+# CHECK-NO-FILTER-COUNT-12: at stop-hook-threads.cpp{{.*}} stop reason = breakpoint \ No newline at end of file
diff --git a/lit/ExecControl/StopHook/stop-hook.test b/lit/ExecControl/StopHook/stop-hook.test
new file mode 100644
index 000000000000..ca6495ef14ad
--- /dev/null
+++ b/lit/ExecControl/StopHook/stop-hook.test
@@ -0,0 +1,76 @@
+# RUN: %clang %p/Inputs/stop-hook.c -g -o %t
+# Test setting stop-hook per-function
+# RUN: %lldb -b -s %p/Inputs/stop-hook-1.lldbinit -s %s -f %t \
+# RUN: | FileCheck --check-prefix=CHECK --check-prefix=CHECK-FUNC %s
+# Test setting stop-hook per-line range
+# RUN: %lldb -b -s %p/Inputs/stop-hook-2.lldbinit -s %s -f %t | FileCheck %s
+# Test setting stop-hook with multi-line expression
+# RUN: %lldb -b -s %p/Inputs/stop-hook-3.lldbinit -s %s -f %t | FileCheck %s
+# This test is not "unsupported" on Windows, but it fails because "expr ptr"
+# does not evaluate correctly. However, the error message contains the expected
+# string, so the test "passes" despite the fact that the commands failed
+# llvm.org/pr40119
+# UNSUPPORTED: system-windows
+
+break set -f stop-hook.c -p "// Set breakpoint here to test target stop-hook"
+break set -f stop-hook.c -p "// Another breakpoint which is outside of the stop-hook range"
+target stop-hook list
+
+# CHECK: Hook: 1
+# CHECK-NEXT: State: enabled
+# CHECK-NEXT: Specifier:
+# CHECK-FUNC-NEXT: Function: b.
+# CHECK-NEXT: Commands:
+# CHECK-NEXT: expr ptr
+
+target stop-hook disable
+
+target stop-hook list
+# CHECK: Hook: 1
+# CHECK-NEXT: State: disabled
+# CHECK-NEXT: Specifier:
+# CHECK-FUNC-NEXT: Function: b.
+# CHECK-NEXT: Commands:
+# CHECK-NEXT: expr ptr
+
+target stop-hook enable
+
+target stop-hook list
+# CHECK: Hook: 1
+# CHECK-NEXT: State: enabled
+# CHECK-NEXT: Specifier:
+# CHECK-FUNC-NEXT: Function: b.
+# CHECK-NEXT: Commands:
+# CHECK-NEXT: expr ptr
+
+run
+# Stopping inside of the stop hook range
+# CHECK: (lldb) run
+# CHECK-NEXT: (void *) $0 = 0x
+
+thread step-over
+# Stepping inside of the stop hook range
+# CHECK: (lldb) thread step-over
+# CHECK-NEXT: (void *) $1 = 0x
+# CHECK: ->{{.*}} // We should stop here after stepping.
+
+process continue
+# Stopping outside of the stop hook range
+# CHECK: (lldb) process continue
+# CHECK-NOT: (void *)
+# CHECK: ->{{.*}} // Another breakpoint which is outside of the stop-hook range.
+
+thread step-over
+# Stepping inside of the stop hook range
+# CHECK: (lldb) thread step-over
+# CHECK-NOT: (void *)
+
+settings set auto-confirm true
+target stop-hook delete
+
+target stop-hook list
+# CHECK: (lldb) target stop-hook list
+# CHECK-NOT: Hook: 1
+# CHECK: No stop hooks
+# CHECK-NOT: Hook: 1
+
diff --git a/lit/Expr/TestIRMemoryMap.test b/lit/Expr/TestIRMemoryMap.test
index 23595945011d..0741c31af38b 100644
--- a/lit/Expr/TestIRMemoryMap.test
+++ b/lit/Expr/TestIRMemoryMap.test
@@ -1,6 +1,6 @@
-# XFAIL: windows
+# UNSUPPORTED: windows
-# RUN: %cxx %p/Inputs/call-function.cpp -g -o %t
+# RUN: %clangxx %p/Inputs/call-function.cpp -g -o %t
# RUN: lldb-test ir-memory-map %t %S/Inputs/ir-memory-map-basic
# RUN: lldb-test ir-memory-map -host-only %t %S/Inputs/ir-memory-map-basic
diff --git a/lit/Expr/TestIRMemoryMapWindows.test b/lit/Expr/TestIRMemoryMapWindows.test
new file mode 100644
index 000000000000..f25db591fa51
--- /dev/null
+++ b/lit/Expr/TestIRMemoryMapWindows.test
@@ -0,0 +1,13 @@
+# REQUIRES: system-windows
+
+# RUN: %clang_cl /Zi /GS- %p/Inputs/call-function.cpp /c /o %t.obj
+# RUN: %msvc_link /debug:full %t.obj /out:%t
+
+# RUN: lldb-test ir-memory-map %t %S/Inputs/ir-memory-map-basic
+# RUN: lldb-test ir-memory-map -host-only %t %S/Inputs/ir-memory-map-basic
+
+# RUN: lldb-test ir-memory-map %t %S/Inputs/ir-memory-map-overlap1
+# RUN: lldb-test ir-memory-map -host-only %t %S/Inputs/ir-memory-map-overlap1
+
+# RUN: lldb-test ir-memory-map %t %S/Inputs/ir-memory-map-mix-malloc-free
+# RUN: lldb-test ir-memory-map -host-only %t %S/Inputs/ir-memory-map-mix-malloc-free
diff --git a/lit/Expr/TestMultilineExpr.test b/lit/Expr/TestMultilineExpr.test
new file mode 100644
index 000000000000..ae02407b5767
--- /dev/null
+++ b/lit/Expr/TestMultilineExpr.test
@@ -0,0 +1,9 @@
+# RUN: %lldb -b -s %s | FileCheck %s
+
+# In terminal sessions LLDB hides input from subsequent lines so it's not visible in the output we check below.
+expression
+2+
+3
+
+# CHECK: (lldb) expression
+# CHECK: (int) {{.*}} = 5
diff --git a/lit/Heap/Inputs/cstr.c b/lit/Heap/Inputs/cstr.c
new file mode 100644
index 000000000000..2f9117b635e5
--- /dev/null
+++ b/lit/Heap/Inputs/cstr.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+int main(void) {
+ char *str;
+ int size = 9; //strlen("patatino") + 1
+ str = (char *)malloc(sizeof(char)*size);
+ *(str+0) = 'p';
+ *(str+1) = 'a';
+ *(str+2) = 't';
+ *(str+3) = 'a';
+ *(str+4) = 't';
+ *(str+5) = 'i';
+ *(str+6) = 'n';
+ *(str+7) = 'o';
+ *(str+8) = '\0';
+ return 0;
+}
diff --git a/lit/Heap/heap-cstr.test b/lit/Heap/heap-cstr.test
new file mode 100644
index 000000000000..00d19ffbe47f
--- /dev/null
+++ b/lit/Heap/heap-cstr.test
@@ -0,0 +1,10 @@
+# REQUIRES: system-darwin
+# RUN: %clang %p/Inputs/cstr.c -g -o %t
+# RUN: %lldb -b -s %s -f %t | FileCheck %s
+
+br set -p return
+command script import lldb.macosx.heap
+run
+cstr "patatino"
+
+# CHECK: {{.*}}: malloc( 16) -> {{.*}}
diff --git a/lit/Minidump/Inputs/dump-content.dmp b/lit/Minidump/Inputs/dump-content.dmp
new file mode 100644
index 000000000000..18eb59ffb7e6
--- /dev/null
+++ b/lit/Minidump/Inputs/dump-content.dmp
Binary files differ
diff --git a/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.cpp b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.cpp
new file mode 100644
index 000000000000..6bf78b5dc43b
--- /dev/null
+++ b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.cpp
@@ -0,0 +1,40 @@
+
+// nodefaultlib build: cl -Zi sigsegv.cpp /link /nodefaultlib
+
+#ifdef USE_CRT
+#include <stdio.h>
+#else
+int main();
+extern "C"
+{
+ int _fltused;
+ void mainCRTStartup() { main(); }
+ void printf(const char*, ...) {}
+}
+#endif
+
+void crash(bool crash_self)
+{
+ printf("Before...\n");
+ if(crash_self)
+ {
+ printf("Crashing in 3, 2, 1 ...\n");
+ *(volatile int*)nullptr = 0;
+ }
+ printf("After...\n");
+}
+
+int foo(int x, float y, const char* msg)
+{
+ bool flag = x > y;
+ if(flag)
+ printf("x = %d, y = %f, msg = %s\n", x, y, msg);
+ crash(flag);
+ return x << 1;
+}
+
+int main()
+{
+ foo(10, 3.14, "testing");
+}
+
diff --git a/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.dmp b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.dmp
new file mode 100644
index 000000000000..c918a6c64e55
--- /dev/null
+++ b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.dmp
Binary files differ
diff --git a/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.lldbinit b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.lldbinit
new file mode 100644
index 000000000000..dff1f1a295e4
--- /dev/null
+++ b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.lldbinit
@@ -0,0 +1,2 @@
+bt all
+dis
diff --git a/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.pdb b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.pdb
new file mode 100644
index 000000000000..d60f9cffddac
--- /dev/null
+++ b/lit/Minidump/Windows/Sigsegv/Inputs/sigsegv.pdb
Binary files differ
diff --git a/lit/Minidump/Windows/Sigsegv/sigsegv.test b/lit/Minidump/Windows/Sigsegv/sigsegv.test
new file mode 100644
index 000000000000..dfa98c566561
--- /dev/null
+++ b/lit/Minidump/Windows/Sigsegv/sigsegv.test
@@ -0,0 +1,13 @@
+// RUN: cd %p/Inputs
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 \
+// RUN: %lldb -c sigsegv.dmp -s sigsegv.lldbinit | FileCheck %s
+
+CHECK: * thread #1, stop reason = Exception 0xc0000005 encountered at address 0x7ff7a13110d9
+CHECK: * frame #0: 0x00007ff7a13110d9 sigsegv.exe
+
+CHECK: -> 0x7ff7a13110d9: movl $0x0, 0x0
+CHECK: 0x7ff7a13110e4: leaq 0x1f45(%rip), %rcx
+CHECK: 0x7ff7a13110eb: callq 0x7ff7a1311019
+CHECK: 0x7ff7a13110f0: addq $0x28, %rsp
+CHECK: 0x7ff7a13110f4: retq
+CHECK: 0x7ff7a13110f5: int3
diff --git a/lit/Minidump/dump-all.test b/lit/Minidump/dump-all.test
new file mode 100644
index 000000000000..9af319760456
--- /dev/null
+++ b/lit/Minidump/dump-all.test
@@ -0,0 +1,86 @@
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --all' | \
+# RUN: FileCheck --check-prefix=CHECKDIR --check-prefix=CHECKCPU \
+# RUN: --check-prefix=CHECKSTATUS --check-prefix=CHECKLSB \
+# RUN: --check-prefix=CHECKCMD --check-prefix=CHECKENV \
+# RUN: --check-prefix=CHECKAUX --check-prefix=CHECKMAP \
+# RUN: --check-prefix=CHECKSTAT --check-prefix=CHECKUP --check-prefix=CHECKFD %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump -a' | \
+# RUN: FileCheck --check-prefix=CHECKDIR --check-prefix=CHECKCPU \
+# RUN: --check-prefix=CHECKSTATUS --check-prefix=CHECKLSB \
+# RUN: --check-prefix=CHECKCMD --check-prefix=CHECKENV \
+# RUN: --check-prefix=CHECKAUX --check-prefix=CHECKMAP \
+# RUN: --check-prefix=CHECKSTAT --check-prefix=CHECKUP --check-prefix=CHECKFD %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --directory' | FileCheck --check-prefix=CHECKDIR %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --d' | FileCheck --check-prefix=CHECKDIR %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --linux' | \
+# RUN: FileCheck --check-prefix=CHECKCPU --check-prefix=CHECKSTATUS \
+# RUN: --check-prefix=CHECKLSB --check-prefix=CHECKCMD --check-prefix=CHECKENV \
+# RUN: --check-prefix=CHECKAUX --check-prefix=CHECKMAP --check-prefix=CHECKSTAT \
+# RUN: --check-prefix=CHECKUP --check-prefix=CHECKFD %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --cpuinfo' | FileCheck --check-prefix=CHECKCPU %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --C' | FileCheck --check-prefix=CHECKCPU %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --status' | FileCheck --check-prefix=CHECKSTATUS %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --s' | FileCheck --check-prefix=CHECKSTATUS %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --lsb-release' | FileCheck --check-prefix=CHECKLSB %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --r' | FileCheck --check-prefix=CHECKLSB %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --cmdline' | FileCheck --check-prefix=CHECKCMD %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --c' | FileCheck --check-prefix=CHECKCMD %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --environ' | FileCheck --check-prefix=CHECKENV %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --e' | FileCheck --check-prefix=CHECKENV %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --auxv' | FileCheck --check-prefix=CHECKAUX %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --x' | FileCheck --check-prefix=CHECKAUX %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --maps' | FileCheck --check-prefix=CHECKMAP %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --m' | FileCheck --check-prefix=CHECKMAP %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --stat' | FileCheck --check-prefix=CHECKSTAT %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --S' | FileCheck --check-prefix=CHECKSTAT %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --uptime' | FileCheck --check-prefix=CHECKUP %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --u' | FileCheck --check-prefix=CHECKUP %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --fd' | FileCheck --check-prefix=CHECKFD %s
+# RUN: %lldb -c %p/Inputs/dump-content.dmp -o 'process plugin dump --f' | FileCheck --check-prefix=CHECKFD %s
+# CHECKDIR: RVA SIZE TYPE MinidumpStreamType
+# CHECKDIR-NEXT: ---------- ---------- ---------- --------------------------
+# CHECKDIR-NEXT: 0x000000b0 0x00000038 0x00000007 SystemInfo
+# CHECKDIR-NEXT: 0x0000015d 0x0000001b 0x47670007 LinuxEnviron
+# CHECKDIR-NEXT: 0x00000190 0x000000bc 0x47670009 LinuxMaps
+# CHECKDIR-NEXT: 0x00000110 0x0000001a 0x47670004 LinuxProcStatus
+# CHECKDIR-NEXT: 0x0000024c 0x00000018 0x4767000b LinuxProcStat
+# CHECKDIR-NEXT: 0x00000142 0x0000001b 0x47670006 LinuxCMDLine
+# CHECKDIR-NEXT: 0x00000272 0x00000016 0x4767000d LinuxProcFD
+# CHECKDIR-NEXT: 0x00000178 0x00000018 0x47670008 LinuxAuxv
+# CHECKDIR-NEXT: 0x000000e8 0x00000018 0x0000000f MiscInfo
+# CHECKDIR-NEXT: 0x00000100 0x00000010 0x47670003 LinuxCPUInfo
+# CHECKDIR-NEXT: 0x0000012a 0x00000018 0x47670005 LinuxLSBRelease
+# CHECKDIR-NEXT: 0x00000264 0x0000000e 0x4767000c LinuxProcUptime
+
+# CHECKCPU: /proc/cpuinfo:
+# CHECKCPU-NEXT: cpu info output
+
+# CHECKSTATUS: /proc/PID/status:
+# CHECKSTATUS-NEXT: /proc/<pid>/status output
+
+# CHECKLSB: /etc/lsb-release:
+# CHECKLSB-NEXT: /etc/lsb-release output
+
+# CHECKCMD: /proc/PID/cmdline:
+# CHECKCMD-NEXT: /proc/<pid>/cmdline output
+
+# CHECKENV: /proc/PID/environ:
+# CHECKENV-NEXT: /proc/<pid>/environ output
+
+# CHECKAUX: /proc/PID/auxv:
+# CHECKAUX-NEXT: 0x00000000: 2f 70 72 6f 63 2f 3c 70 69 64 3e 2f 61 75 78 76 /proc/<pid>/auxv
+# CHECKAUX-NEXT: 0x00000010: 20 6f 75 74 70 75 74 00 output.
+
+# CHECKMAP: /proc/PID/maps:
+# CHECKMAP-NEXT: 400d9000-400db000 r-xp 00000000 b3:04 227 /system/bin/app_process
+# CHECKMAP-NEXT: 400db000-400dc000 r--p 00001000 b3:04 227 /system/bin/app_process
+# CHECKMAP-NEXT: 400dc000-400dd000 rw-p 00000000 00:00 0
+
+# CHECKSTAT: /proc/PID/stat:
+# CHECKSTAT-NEXT: /proc/<pid>/stat output
+
+# CHECKUP: uptime:
+# CHECKUP-NEXT: uptime output
+
+# CHECKFD: /proc/PID/fd:
+# CHECKFD-NEXT: /proc/<pid>/fd output
diff --git a/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms b/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms
new file mode 100644
index 000000000000..0241d512862c
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/bad-module-id-1.syms
@@ -0,0 +1,2 @@
+MODULE Linux x86_64 E5894855+C35D+CCCCCCCCCCCCCCCCCCCC0 linux.out
+PUBLIC 1000 0 _start
diff --git a/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms b/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms
new file mode 100644
index 000000000000..4ae10438f309
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/bad-module-id-2.syms
@@ -0,0 +1,2 @@
+MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCC linux.out
+PUBLIC 1000 0 _start
diff --git a/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms b/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms
new file mode 100644
index 000000000000..2e6d72a37d58
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/bad-module-id-3.syms
@@ -0,0 +1,2 @@
+MODULE Linux x86_64 E58X4855C35DCCCCCCCCXCCCCCCCCCCC0 linux.out
+PUBLIC 1000 0 _start
diff --git a/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms b/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms
new file mode 100644
index 000000000000..bf0a21bc6e09
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/discontiguous-sections.syms
@@ -0,0 +1,5 @@
+MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 linux.out
+INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
+FILE 0 /tmp/a.c
+PUBLIC 1010 0 _start
+FILE 1 /tmp/b.c
diff --git a/lit/Modules/Breakpad/Inputs/identification-linux.syms b/lit/Modules/Breakpad/Inputs/identification-linux.syms
new file mode 100644
index 000000000000..d82e30c4a05d
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/identification-linux.syms
@@ -0,0 +1,6 @@
+MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 linux.out
+INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC
+PUBLIC 1000 0 _start
+STACK CFI INIT 1000 6 .cfa: $rsp 8 + .ra: .cfa -8 + ^
+STACK CFI 1001 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
+STACK CFI 1004 .cfa: $rbp 16 +
diff --git a/lit/Modules/Breakpad/Inputs/identification-macosx.syms b/lit/Modules/Breakpad/Inputs/identification-macosx.syms
new file mode 100644
index 000000000000..56e0635e5f69
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/identification-macosx.syms
@@ -0,0 +1,6 @@
+MODULE mac x86_64 D98C0E682089AA1BEACD6A8C1F16707B0 mac.out
+PUBLIC 0 0 _mh_execute_header
+PUBLIC f30 0 start
+STACK CFI INIT f30 6 .cfa: $rsp 8 + .ra: .cfa -8 + ^
+STACK CFI f31 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
+STACK CFI f34 .cfa: $rbp 16 +
diff --git a/lit/Modules/Breakpad/Inputs/identification-windows.syms b/lit/Modules/Breakpad/Inputs/identification-windows.syms
new file mode 100644
index 000000000000..8fa5f305209b
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/identification-windows.syms
@@ -0,0 +1,4 @@
+MODULE windows x86 A0C9165780B5490981A1925EA62165C01 a.pdb
+INFO CODE_ID 5C01672A4000 a.exe
+FILE 1 c:\tmp\a.cpp
+PUBLIC 1000 0 main
diff --git a/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms b/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms
new file mode 100644
index 000000000000..6176d35143cd
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/sections-trailing-func.syms
@@ -0,0 +1,8 @@
+MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 linux.out
+INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
+FILE 0 /tmp/a.c
+FUNC 1010 10 0 _start
+1010 4 4 0
+1014 5 5 0
+1019 5 6 0
+101e 2 7 0
diff --git a/lit/Modules/Breakpad/Inputs/sections.syms b/lit/Modules/Breakpad/Inputs/sections.syms
new file mode 100644
index 000000000000..121cca439b02
--- /dev/null
+++ b/lit/Modules/Breakpad/Inputs/sections.syms
@@ -0,0 +1,12 @@
+MODULE Linux x86_64 0000000024B5D199F0F766FFFFFF5DC30 linux.out
+INFO CODE_ID 00000000B52499D1F0F766FFFFFF5DC3
+FILE 0 /tmp/a.c
+FUNC 1010 10 0 _start
+1010 4 4 0
+1014 5 5 0
+1019 5 6 0
+101e 2 7 0
+PUBLIC 1010 0 _start
+STACK CFI INIT 1010 10 .cfa: $rsp 8 + .ra: .cfa -8 + ^
+STACK CFI 1011 $rbp: .cfa -16 + ^ .cfa: $rsp 16 +
+STACK CFI 1014 .cfa: $rbp 16 +
diff --git a/lit/Modules/Breakpad/breakpad-identification.test b/lit/Modules/Breakpad/breakpad-identification.test
new file mode 100644
index 000000000000..49758b59a1e5
--- /dev/null
+++ b/lit/Modules/Breakpad/breakpad-identification.test
@@ -0,0 +1,32 @@
+RUN: lldb-test object-file %p/Inputs/identification-linux.syms | FileCheck %s --check-prefix=LINUX
+RUN: lldb-test object-file %p/Inputs/identification-macosx.syms | FileCheck %s --check-prefix=MAC
+RUN: lldb-test object-file %p/Inputs/identification-windows.syms | FileCheck %s --check-prefix=WINDOWS
+RUN: not lldb-test object-file %p/Inputs/bad-module-id-1.syms 2>&1 | FileCheck %s --check-prefix=ERROR
+RUN: not lldb-test object-file %p/Inputs/bad-module-id-2.syms 2>&1 | FileCheck %s --check-prefix=ERROR
+RUN: not lldb-test object-file %p/Inputs/bad-module-id-3.syms 2>&1 | FileCheck %s --check-prefix=ERROR
+
+LINUX: Plugin name: breakpad
+LINUX: Architecture: x86_64--linux
+LINUX: UUID: 554889E5-5DC3-CCCC-CCCC-CCCCCCCCCCCC
+LINUX: Executable: false
+LINUX: Stripped: false
+LINUX: Type: debug info
+LINUX: Strata: user
+
+MAC: Plugin name: breakpad
+MAC: Architecture: x86_64--macosx
+MAC: UUID: 680E8CD9-8920-1BAA-EACD-6A8C1F16707B
+MAC: Executable: false
+MAC: Stripped: false
+MAC: Type: debug info
+MAC: Strata: user
+
+WINDOWS: Plugin name: breakpad
+WINDOWS: Architecture: i386--windows
+WINDOWS: UUID: 5716C9A0-B580-0949-81A1-925EA62165C0-01000000
+WINDOWS: Executable: false
+WINDOWS: Stripped: false
+WINDOWS: Type: debug info
+WINDOWS: Strata: user
+
+ERROR: not recognised as an object file
diff --git a/lit/Modules/Breakpad/discontiguous-sections.test b/lit/Modules/Breakpad/discontiguous-sections.test
new file mode 100644
index 000000000000..0c9aeea08d7e
--- /dev/null
+++ b/lit/Modules/Breakpad/discontiguous-sections.test
@@ -0,0 +1,27 @@
+# Test handling discontiguous sections.
+RUN: lldb-test object-file %p/Inputs/discontiguous-sections.syms -contents | FileCheck %s
+
+CHECK: Showing 5 sections
+
+CHECK: ID: 0x1
+CHECK-NEXT: Name: MODULE
+
+CHECK: ID: 0x2
+CHECK-NEXT: Name: INFO
+
+CHECK: ID: 0x3
+CHECK-NEXT: Name: FILE
+CHECK: File size: 16
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46494C45 2030202F 746D702F 612E630A |FILE 0 /tmp/a.c.|
+CHECK-NEXT: )
+
+CHECK: ID: 0x4
+CHECK-NEXT: Name: PUBLIC
+
+CHECK: ID: 0x5
+CHECK-NEXT: Name: FILE
+CHECK: File size: 16
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46494C45 2031202F 746D702F 622E630A |FILE 1 /tmp/b.c.|
+CHECK-NEXT: )
diff --git a/lit/Breakpoint/lit.local.cfg b/lit/Modules/Breakpad/lit.local.cfg
index df9b335dd131..df9b335dd131 100644
--- a/lit/Breakpoint/lit.local.cfg
+++ b/lit/Modules/Breakpad/lit.local.cfg
diff --git a/lit/Modules/Breakpad/sections-trailing-func.test b/lit/Modules/Breakpad/sections-trailing-func.test
new file mode 100644
index 000000000000..9ea5c9da7810
--- /dev/null
+++ b/lit/Modules/Breakpad/sections-trailing-func.test
@@ -0,0 +1,15 @@
+# Test handling of a (valid) breakpad file, which ends with a line without a
+# recognised keyword.
+
+RUN: lldb-test object-file %p/Inputs/sections-trailing-func.syms -contents | FileCheck %s
+
+CHECK: Showing 4 sections
+
+CHECK: ID: 0x4
+CHECK-NEXT: Name: FUNC
+CHECK: File size: 66
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46554E43 20313031 30203130 2030205F 73746172 740A3130 31302034 20342030 |FUNC 1010 10 0 _start.1010 4 4 0|
+CHECK-NEXT: 0020: 0A313031 34203520 3520300A 31303139 20352036 20300A31 30316520 32203720 |.1014 5 5 0.1019 5 6 0.101e 2 7 |
+CHECK-NEXT: 0040: 300A |0.|
+CHECK-NEXT: )
diff --git a/lit/Modules/Breakpad/sections.test b/lit/Modules/Breakpad/sections.test
new file mode 100644
index 000000000000..32ccf848db60
--- /dev/null
+++ b/lit/Modules/Breakpad/sections.test
@@ -0,0 +1,89 @@
+RUN: lldb-test object-file %p/Inputs/sections.syms -contents | FileCheck %s
+
+CHECK: Showing 6 sections
+
+CHECK: Index: 0
+CHECK-NEXT: ID: 0x1
+CHECK-NEXT: Name: MODULE
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 64
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 4D4F4455 4C45204C 696E7578 20783836 5F363420 30303030 30303030 32344235 |MODULE Linux x86_64 0000000024B5|
+CHECK-NEXT: 0020: 44313939 46304637 36364646 46464646 35444333 30206C69 6E75782E 6F75740A |D199F0F766FFFFFF5DC30 linux.out.|
+CHECK-NEXT: )
+
+CHECK: Index: 1
+CHECK-NEXT: ID: 0x2
+CHECK-NEXT: Name: INFO
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 46
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 494E464F 20434F44 455F4944 20303030 30303030 30423532 34393944 31463046 |INFO CODE_ID 00000000B52499D1F0F|
+CHECK-NEXT: 0020: 37363646 46464646 46354443 330A |766FFFFFF5DC3.|
+CHECK-NEXT: )
+
+CHECK: Index: 2
+CHECK-NEXT: ID: 0x3
+CHECK-NEXT: Name: FILE
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 16
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46494C45 2030202F 746D702F 612E630A |FILE 0 /tmp/a.c.|
+CHECK-NEXT: )
+
+CHECK: Index: 3
+CHECK-NEXT: ID: 0x4
+CHECK-NEXT: Name: FUNC
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 66
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 46554E43 20313031 30203130 2030205F 73746172 740A3130 31302034 20342030 |FUNC 1010 10 0 _start.1010 4 4 0|
+CHECK-NEXT: 0020: 0A313031 34203520 3520300A 31303139 20352036 20300A31 30316520 32203720 |.1014 5 5 0.1019 5 6 0.101e 2 7 |
+CHECK-NEXT: 0040: 300A |0.|
+CHECK-NEXT: )
+
+CHECK: Index: 4
+CHECK-NEXT: ID: 0x5
+CHECK-NEXT: Name: PUBLIC
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 21
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 5055424C 49432031 30313020 30205F73 74617274 0A |PUBLIC 1010 0 _start.|
+CHECK-NEXT: )
+
+CHECK: Index: 5
+CHECK-NEXT: ID: 0x6
+CHECK-NEXT: Name: STACK
+CHECK-NEXT: Type: regular
+CHECK-NEXT: Permissions: ---
+CHECK-NEXT: Thread specific: no
+CHECK-NEXT: VM address: 0
+CHECK-NEXT: VM size: 0
+CHECK-NEXT: File size: 136
+CHECK-NEXT: Data: (
+CHECK-NEXT: 0000: 53544143 4B204346 4920494E 49542031 30313020 3130202E 6366613A 20247273 |STACK CFI INIT 1010 10 .cfa: $rs|
+CHECK-NEXT: 0020: 70203820 2B202E72 613A202E 63666120 2D38202B 205E0A53 5441434B 20434649 |p 8 + .ra: .cfa -8 + ^.STACK CFI|
+CHECK-NEXT: 0040: 20313031 31202472 62703A20 2E636661 202D3136 202B205E 202E6366 613A2024 | 1011 $rbp: .cfa -16 + ^ .cfa: $|
+CHECK-NEXT: 0060: 72737020 3136202B 0A535441 434B2043 46492031 30313420 2E636661 3A202472 |rsp 16 +.STACK CFI 1014 .cfa: $r|
+CHECK-NEXT: 0080: 62702031 36202B0A |bp 16 +.|
+CHECK-NEXT: )
diff --git a/lit/Modules/ELF/Inputs/PT_LOAD-overlap-section.elf b/lit/Modules/ELF/Inputs/PT_LOAD-overlap-section.elf
new file mode 100644
index 000000000000..d5fd2d1fa91d
--- /dev/null
+++ b/lit/Modules/ELF/Inputs/PT_LOAD-overlap-section.elf
Binary files differ
diff --git a/lit/Modules/ELF/PT_LOAD-empty.yaml b/lit/Modules/ELF/PT_LOAD-empty.yaml
new file mode 100644
index 000000000000..9f1cb0745723
--- /dev/null
+++ b/lit/Modules/ELF/PT_LOAD-empty.yaml
@@ -0,0 +1,26 @@
+# Test behavior on unusual (and probably corrupt) files. Test that we drop an
+# empty PT_LOAD segment.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+#
+# CHECK-NOT: container
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ VAddr: 0x1000
+ Align: 0x4
diff --git a/lit/Modules/ELF/PT_LOAD-overlap-PT_INTERP.yaml b/lit/Modules/ELF/PT_LOAD-overlap-PT_INTERP.yaml
new file mode 100644
index 000000000000..e97afe9070ce
--- /dev/null
+++ b/lit/Modules/ELF/PT_LOAD-overlap-PT_INTERP.yaml
@@ -0,0 +1,50 @@
+# Test that an overlapping PT_INTERP segment does not cause us to drop the
+# subsequent PT_LOAD segment.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Index: 0
+# CHECK-NEXT: ID: 0xfffffffffffffffe
+# CHECK-NEXT: Name: PT_LOAD[0]
+# CHECK-NEXT: Type: container
+# CHECK-NEXT: Permissions: rwx
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1000
+# CHECK-NEXT: VM size: 12
+# CHECK-NEXT: File size: 12
+# CHECK-NEXT: Showing 2 subsections
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_ARM
+Sections:
+ - Name: .interp
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: 3232
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1004
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ProgramHeaders:
+ - Type: PT_INTERP
+ Flags: [ PF_R ]
+ VAddr: 0x1000
+ Align: 0x4
+ Sections:
+ - Section: .interp
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_W, PF_R ]
+ VAddr: 0x1000
+ Align: 0x4
+ Sections:
+ - Section: .interp
+ - Section: .text
diff --git a/lit/Modules/ELF/PT_LOAD-overlap-section.yaml b/lit/Modules/ELF/PT_LOAD-overlap-section.yaml
new file mode 100644
index 000000000000..3b7bde802ce0
--- /dev/null
+++ b/lit/Modules/ELF/PT_LOAD-overlap-section.yaml
@@ -0,0 +1,66 @@
+# Test behavior on strange (invalid?) elf files where the sections cross segment
+# boundary. The test input was generated from this yaml file, but the program
+# header was modified by hand, so this input is here for reference only.
+#
+# Right now lldb shortens sections to make sure every section is fully contained
+# within a segment, but other behaviors are possible too (including outright
+# rejecting such files).
+
+# RUN: lldb-test object-file %S/Inputs/PT_LOAD-overlap-section.elf | FileCheck %s
+
+# CHECK: Index: 0
+# CHECK-NEXT: ID: 0xffffffffffffffff
+# CHECK-NEXT: Name: PT_LOAD[0]
+# CHECK-NEXT: Type: container
+# CHECK-NEXT: Permissions: rwx
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1006
+# CHECK-NEXT: VM size: 8
+# CHECK-NEXT: File size: 8
+# CHECK-NEXT: Showing 1 subsections
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: ID: 0x2
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: Type: code
+# CHECK-NEXT: Permissions: r-x
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1008
+# CHECK-NEXT: VM size: 6
+# CHECK-NEXT: File size: 8
+
+# CHECK: Index: 1
+# CHECK-NEXT: ID: 0x1
+# CHECK-NEXT: Name: .interp
+# CHECK-NEXT: Type: regular
+# CHECK-NEXT: Permissions: r--
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1000
+# CHECK-NEXT: VM size: 6
+# CHECK-NEXT: File size: 8
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_ARM
+Sections:
+ - Name: .interp
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1008
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_W, PF_R ]
+ VAddr: 0x1008 # Modified by hand to start at 0x1006
+ Align: 0x4
+ Sections:
+ - Section: .text
diff --git a/lit/Modules/ELF/PT_LOAD-overlap.yaml b/lit/Modules/ELF/PT_LOAD-overlap.yaml
new file mode 100644
index 000000000000..1315f54e6c02
--- /dev/null
+++ b/lit/Modules/ELF/PT_LOAD-overlap.yaml
@@ -0,0 +1,42 @@
+# Test behavior on unusual (and probably corrupt) object files. Check that we
+# drop the second PT_LOAD segment which overlaps with the first one.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Type: container
+# CHECK-NOT: Type: container
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1008
+ AddressAlign: 0x4
+ Content: 3232
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_W, PF_R ]
+ VAddr: 0x1000
+ Align: 0x4
+ Sections:
+ - Section: .text
+ - Section: .data
+ - Type: PT_LOAD
+ Flags: [ PF_R, PF_W ]
+ VAddr: 0x1008
+ Align: 0x4
+ Sections:
+ - Section: .data
diff --git a/lit/Modules/ELF/PT_LOAD.yaml b/lit/Modules/ELF/PT_LOAD.yaml
new file mode 100644
index 000000000000..d673a69c8cd8
--- /dev/null
+++ b/lit/Modules/ELF/PT_LOAD.yaml
@@ -0,0 +1,79 @@
+# Test that sections are made child-sections of the PT_LOAD segments/sections.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Index: 0
+# CHECK-NEXT: ID: 0xffffffffffffffff
+# CHECK-NEXT: Name: PT_LOAD[0]
+# CHECK-NEXT: Type: container
+# CHECK-NEXT: Permissions: rwx
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1000
+# CHECK-NEXT: VM size: 10
+# CHECK-NEXT: File size: 10
+# CHECK-NEXT: Showing 2 subsections
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: ID: 0x1
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: Type: code
+# CHECK-NEXT: Permissions: r-x
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1000
+# CHECK-NEXT: VM size: 8
+# CHECK-NEXT: File size: 8
+# CHECK-EMPTY:
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: ID: 0x2
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Type: data
+# CHECK-NEXT: Permissions: r--
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x1008
+# CHECK-NEXT: VM size: 2
+# CHECK-NEXT: File size: 2
+# CHECK-EMPTY:
+# CHECK-EMPTY:
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: ID: 0x3
+# CHECK-NEXT: Name: .data_outside
+# CHECK-NEXT: Type: regular
+# CHECK-NEXT: Permissions: r--
+# CHECK-NEXT: Thread specific: no
+# CHECK-NEXT: VM address: 0x2000
+# CHECK-NEXT: VM size: 2
+# CHECK-NEXT: File size: 2
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_ARM
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1008
+ AddressAlign: 0x4
+ Content: 3232
+ - Name: .data_outside
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x2000
+ AddressAlign: 0x4
+ Content: 3232
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_W, PF_R ]
+ VAddr: 0x1000
+ Align: 0x4
+ Sections:
+ - Section: .text
+ - Section: .data
diff --git a/lit/Modules/ELF/base-address.yaml b/lit/Modules/ELF/base-address.yaml
new file mode 100644
index 000000000000..68f117708351
--- /dev/null
+++ b/lit/Modules/ELF/base-address.yaml
@@ -0,0 +1,34 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Base VM address: 0x400000
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400078
+Sections:
+ - Name: .pad
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0000000000400000
+ AddressAlign: 0x0000000000001000
+ Size: 0x78
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400078
+ AddressAlign: 0x0000000000000001
+ Content: 48C7C0E700000048C7C72F0000000F05CC
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ VAddr: 0x400000
+ Align: 0x200000
+ Sections:
+ - Section: .pad
+ - Section: .text
+...
diff --git a/lit/Modules/ELF/basic-info.yaml b/lit/Modules/ELF/basic-info.yaml
new file mode 100644
index 000000000000..0e1db67e9d5f
--- /dev/null
+++ b/lit/Modules/ELF/basic-info.yaml
@@ -0,0 +1,27 @@
+# REQUIRES: lld
+
+# RUN: yaml2obj %s > %t.o
+# RUN: ld.lld %t.o -o %t -image-base 0x47000
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Plugin name: elf
+# CHECK: Architecture: x86_64--
+# CHECK: Executable: true
+# CHECK: Stripped: false
+# CHECK: Type: executable
+# CHECK: Strata: user
+# CHECK: Base VM address: 0x47000
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000010
+ Content: 554889E55DC3
+...
diff --git a/lit/Modules/build-id-case.yaml b/lit/Modules/ELF/build-id-case.yaml
index 246163ad52af..843bc40fb791 100644
--- a/lit/Modules/build-id-case.yaml
+++ b/lit/Modules/ELF/build-id-case.yaml
@@ -6,8 +6,6 @@
# CHECK: Name: .debug_frame
# CHECK-NEXT: Type: dwarf-frame
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
--- !ELF
FileHeader:
diff --git a/lit/Modules/compressed-sections.yaml b/lit/Modules/ELF/compressed-sections.yaml
index c75dc857522a..df070a2d53d6 100644
--- a/lit/Modules/compressed-sections.yaml
+++ b/lit/Modules/ELF/compressed-sections.yaml
@@ -19,6 +19,7 @@ Sections:
# CHECK: Name: .hello_elf
# CHECK-NEXT: Type: regular
+# CHECK: VM address: 0
# CHECK-NEXT: VM size: 0
# CHECK-NEXT: File size: 28
# CHECK-NEXT: Data:
@@ -26,7 +27,7 @@ Sections:
# CHECK: Name: .bogus
# CHECK-NEXT: Type: regular
+# CHECK: VM address: 0
# CHECK-NEXT: VM size: 0
# CHECK-NEXT: File size: 8
-# CHECK-NEXT: Data:
-# CHECK-NEXT: DEADBEEF BAADF00D
+# CHECK-NEXT: Data: ()
diff --git a/lit/Modules/elf-duplicate-section.yaml b/lit/Modules/ELF/duplicate-section.yaml
index b4b391cc912d..b4b391cc912d 100644
--- a/lit/Modules/elf-duplicate-section.yaml
+++ b/lit/Modules/ELF/duplicate-section.yaml
diff --git a/lit/Modules/elf-many-sections.s b/lit/Modules/ELF/many-sections.s
index a5e4aee18821..15d7e8fc1589 100644
--- a/lit/Modules/elf-many-sections.s
+++ b/lit/Modules/ELF/many-sections.s
@@ -7,7 +7,7 @@
## aaaaaaaa..dddddddd, plus a couple of standard ones (.strtab, etc.)
## Check the number is correct plus the names of a couple of chosen sections.
-# CHECK: Showing 65541 sections
+# CHECK: Showing 65540 sections
# CHECK: Name: aaaaaaaa
# CHECK: Name: bbbbbbbb
# CHECK: Name: cccccccc
diff --git a/lit/Modules/ELF/section-addresses.yaml b/lit/Modules/ELF/section-addresses.yaml
new file mode 100644
index 000000000000..012abbf1f6d3
--- /dev/null
+++ b/lit/Modules/ELF/section-addresses.yaml
@@ -0,0 +1,58 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK-LABEL: Name: .one
+# CHECK: VM address: 0x0
+
+# CHECK-LABEL: Name: .nonalloc
+# CHECK: VM address: 0x0
+
+# CHECK-LABEL: Name: .two
+# CHECK: VM address: 0x8
+
+# CHECK-LABEL: Name: .three
+# CHECK: VM address: 0xc
+
+# CHECK-LABEL: Name: .four
+# CHECK: VM address: 0xc
+
+# CHECK-LABEL: Name: .five
+# CHECK: VM address: 0x1000
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+ Entry: 0x00000000000007A0
+Sections:
+ - Name: .one
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: DEADBEEFBAADF00D
+ - Name: .nonalloc
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000004
+ Content: DEADBEEFBAADF00D
+ - Name: .two
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: DE
+ - Name: .three
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ - Name: .four
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: DEADBEEFBAADF00D
+ - Name: .five
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ AddressAlign: 0x0000000000001000
+ Content: DEADBEEFBAADF00D
+...
diff --git a/lit/Modules/ELF/section-overlap.yaml b/lit/Modules/ELF/section-overlap.yaml
new file mode 100644
index 000000000000..bfbd873be41b
--- /dev/null
+++ b/lit/Modules/ELF/section-overlap.yaml
@@ -0,0 +1,51 @@
+# Test handling of (corrupt?) object files, which have sections with overlapping
+# virtual addresses.
+#
+# Right now the overlapping sections get dropped, but other behaviors
+# (including outright rejecting such files) are possible too.
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK-NOT: .overlap1
+# CHECK-NOT: .overlap2
+
+!ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_ARM
+Sections:
+ - Name: .sect1
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ - Name: .overlap1
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x1004
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ - Name: .sect2
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x2000
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ - Name: .overlap2
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x2004
+ AddressAlign: 0x4
+ Content: DEADBEEFBAADF00D
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_W, PF_R ]
+ VAddr: 0x1000
+ Align: 0x4
+ Sections:
+ - Section: .sect1
+ - Section: .overlap1
diff --git a/lit/Modules/ELF/section-permissions.yaml b/lit/Modules/ELF/section-permissions.yaml
new file mode 100644
index 000000000000..99c2773c81b3
--- /dev/null
+++ b/lit/Modules/ELF/section-permissions.yaml
@@ -0,0 +1,34 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK-LABEL: Name: .r-x
+# CHECK: Permissions: r-x
+#
+# CHECK-LABEL: Name: .rw-
+# CHECK: Permissions: rw-
+
+# CHECK-LABEL: Name: .---
+# CHECK: Permissions: ---
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+ Entry: 0x00000000000007A0
+Sections:
+ - Name: .r-x
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Content: DEADBEEFBAADF00D
+ - Name: .rw-
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: DEADBEEFBAADF00D
+ - Name: .---
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: DEADBEEFBAADF00D
+...
diff --git a/lit/Modules/ELF/section-types-edgecases.yaml b/lit/Modules/ELF/section-types-edgecases.yaml
new file mode 100644
index 000000000000..ad1fa2d9097b
--- /dev/null
+++ b/lit/Modules/ELF/section-types-edgecases.yaml
@@ -0,0 +1,35 @@
+# This test doesn't attempt to mandate a specific section classification. It is
+# here to document the existing behavior and to make sure we don't do something
+# completely crazy (like crashing).
+
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# The section is called .data, but it has the SHF_EXECINSTR flag set. Have
+# the flag take precedence over the name.
+# CHECK-LABEL: Name: .data
+# CHECK-NEXT: Type: code
+
+# Section type (SHT_SYMTAB) takes precedence over name-based deduction.
+# CHECK-LABEL: Name: .text
+# CHECK-NEXT: Type: elf-symbol-table
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x00000000000007A0
+Sections:
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_EXECINSTR, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: DEADBEEFBAADF00D
+ - Name: .text
+ Type: SHT_SYMTAB
+ Flags: [ ]
+ AddressAlign: 0x0000000000000004
+ Content: DEADBEEFBAADF00D
+...
diff --git a/lit/Modules/elf-section-types.yaml b/lit/Modules/ELF/section-types.yaml
index 64906a9acf8b..907d57b10cfe 100644
--- a/lit/Modules/elf-section-types.yaml
+++ b/lit/Modules/ELF/section-types.yaml
@@ -1,37 +1,41 @@
# RUN: yaml2obj %s > %t
# RUN: lldb-test object-file %t | FileCheck %s
-# CHECK: Name: .text
+# CHECK-LABEL: Name: .text
# CHECK-NEXT: Type: code
-# CHECK: Name: .debug_info
+# CHECK-LABEL: Name: .debug_info
# CHECK-NEXT: Type: dwarf-info
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
-# CHECK: Name: .debug_types
+# CHECK-LABEL: Name: .debug_types
# CHECK-NEXT: Type: dwarf-types
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
-# CHECK: Name: .debug_names
+# CHECK-LABEL: Name: .debug_names
# CHECK-NEXT: Type: dwarf-names
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
-# CHECK: Name: .gnu_debugaltlink
+# CHECK-LABEL: Name: .gnu_debugaltlink
# CHECK-NEXT: Type: dwarf-gnu-debugaltlink
-# CHECK-NEXT: VM size: 0
-# CHECK-NEXT: File size: 8
-# CHECK: Name: __codesection
+# CHECK-LABEL: Name: __codesection
# CHECK-NEXT: Type: code
+# CHECK-LABEL: Name: .data
+# CHECK-NEXT: Type: data
+# CHECK: Thread specific: no
+
+# CHECK-LABEL: Name: .tdata
+# CHECK-NEXT: Type: data
+# CHECK: Thread specific: yes
+
+# CHECK-LABEL: Name: .tbss
+# CHECK-NEXT: Type: zero-fill
+# CHECK: Thread specific: yes
+
--- !ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
- Type: ET_DYN
+ Type: ET_REL
Machine: EM_X86_64
Entry: 0x00000000000007A0
Sections:
@@ -59,4 +63,19 @@ Sections:
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
Content: DEADBEEFBAADF00D
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ AddressAlign: 0x0000000000000004
+ Content: 2F000000
+ - Name: .tdata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+ AddressAlign: 0x0000000000000004
+ Content: 2F000000
+ - Name: .tbss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+ AddressAlign: 0x0000000000000004
+ Size: 0x0000000000000004
...
diff --git a/lit/Modules/short-build-id.yaml b/lit/Modules/ELF/short-build-id.yaml
index 907813473920..907813473920 100644
--- a/lit/Modules/short-build-id.yaml
+++ b/lit/Modules/ELF/short-build-id.yaml
diff --git a/lit/Modules/MachO/lc_build_version.yaml b/lit/Modules/MachO/lc_build_version.yaml
new file mode 100644
index 000000000000..4479662627ff
--- /dev/null
+++ b/lit/Modules/MachO/lc_build_version.yaml
@@ -0,0 +1,209 @@
+# RUN: yaml2obj %s > %t.out
+# RUN: lldb-test symbols %t.out | FileCheck %s
+# Test that the deployment target is parsed from the load commands.
+# CHECK: x86_64-apple-macosx10.14.0
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x80000003
+ filetype: 0x00000002
+ ncmds: 14
+ sizeofcmds: 744
+ flags: 0x00200085
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __PAGEZERO
+ vmaddr: 0
+ vmsize: 4294967296
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 0
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: __TEXT
+ vmaddr: 4294967296
+ vmsize: 4096
+ fileoff: 0
+ filesize: 4096
+ maxprot: 7
+ initprot: 5
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000100000FB0
+ size: 8
+ offset: 0x00000FB0
+ align: 4
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __unwind_info
+ segname: __TEXT
+ addr: 0x0000000100000FB8
+ size: 72
+ offset: 0x00000FB8
+ align: 2
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4294971392
+ vmsize: 4096
+ fileoff: 4096
+ filesize: 152
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_DYLD_INFO_ONLY
+ cmdsize: 48
+ rebase_off: 0
+ rebase_size: 0
+ bind_off: 0
+ bind_size: 0
+ weak_bind_off: 0
+ weak_bind_size: 0
+ lazy_bind_off: 0
+ lazy_bind_size: 0
+ export_off: 4096
+ export_size: 48
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 4152
+ nsyms: 3
+ stroff: 4200
+ strsize: 48
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 2
+ iundefsym: 2
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+ - cmd: LC_LOAD_DYLINKER
+ cmdsize: 32
+ name: 12
+ PayloadString: /usr/lib/dyld
+ ZeroPadBytes: 7
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: 8F41E140-23B9-3720-AC28-4E7AF9D159BA
+ - cmd: LC_BUILD_VERSION
+ cmdsize: 32
+ platform: 1
+ minos: 658944
+ sdk: 658944
+ ntools: 1
+ Tools:
+ - tool: 3
+ version: 26738944
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+ - cmd: LC_MAIN
+ cmdsize: 24
+ entryoff: 4016
+ stacksize: 0
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 82102276
+ compatibility_version: 65536
+ PayloadString: /usr/lib/libSystem.B.dylib
+ ZeroPadBytes: 6
+ - cmd: LC_FUNCTION_STARTS
+ cmdsize: 16
+ dataoff: 4144
+ datasize: 8
+ - cmd: LC_DATA_IN_CODE
+ cmdsize: 16
+ dataoff: 4152
+ datasize: 0
+LinkEditData:
+ ExportTrie:
+ TerminalSize: 0
+ NodeOffset: 0
+ Name: ''
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000000
+ Other: 0x0000000000000000
+ ImportName: ''
+ Children:
+ - TerminalSize: 0
+ NodeOffset: 5
+ Name: _
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000000
+ Other: 0x0000000000000000
+ ImportName: ''
+ Children:
+ - TerminalSize: 2
+ NodeOffset: 33
+ Name: _mh_execute_header
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000000
+ Other: 0x0000000000000000
+ ImportName: ''
+ - TerminalSize: 3
+ NodeOffset: 37
+ Name: main
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000FB0
+ Other: 0x0000000000000000
+ ImportName: ''
+ NameList:
+ - n_strx: 2
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 16
+ n_value: 4294967296
+ - n_strx: 22
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294971312
+ - n_strx: 28
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 256
+ n_value: 0
+ StringTable:
+ - ' '
+ - __mh_execute_header
+ - _main
+ - dyld_stub_binder
+ - ''
+ - ''
+ - ''
+...
diff --git a/lit/Modules/MachO/lc_build_version_notools.yaml b/lit/Modules/MachO/lc_build_version_notools.yaml
new file mode 100644
index 000000000000..f84c71aff6aa
--- /dev/null
+++ b/lit/Modules/MachO/lc_build_version_notools.yaml
@@ -0,0 +1,206 @@
+# RUN: yaml2obj %s > %t.out
+# RUN: lldb-test symbols %t.out | FileCheck %s
+# Test that the deployment target is parsed from the load commands.
+# CHECK: x86_64-apple-macosx10.14.0
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x80000003
+ filetype: 0x00000002
+ ncmds: 14
+ sizeofcmds: 738
+ flags: 0x00200085
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __PAGEZERO
+ vmaddr: 0
+ vmsize: 4294967296
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 0
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 232
+ segname: __TEXT
+ vmaddr: 4294967296
+ vmsize: 4096
+ fileoff: 0
+ filesize: 4096
+ maxprot: 7
+ initprot: 5
+ nsects: 2
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000100000FB0
+ size: 8
+ offset: 0x00000FB0
+ align: 4
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __unwind_info
+ segname: __TEXT
+ addr: 0x0000000100000FB8
+ size: 72
+ offset: 0x00000FB8
+ align: 2
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 4294971392
+ vmsize: 4096
+ fileoff: 4096
+ filesize: 152
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_DYLD_INFO_ONLY
+ cmdsize: 48
+ rebase_off: 0
+ rebase_size: 0
+ bind_off: 0
+ bind_size: 0
+ weak_bind_off: 0
+ weak_bind_size: 0
+ lazy_bind_off: 0
+ lazy_bind_size: 0
+ export_off: 4096
+ export_size: 48
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 4152
+ nsyms: 3
+ stroff: 4200
+ strsize: 48
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 0
+ iextdefsym: 0
+ nextdefsym: 2
+ iundefsym: 2
+ nundefsym: 1
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 0
+ nlocrel: 0
+ - cmd: LC_LOAD_DYLINKER
+ cmdsize: 32
+ name: 12
+ PayloadString: /usr/lib/dyld
+ ZeroPadBytes: 7
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: 8F41E140-23B9-3720-AC28-4E7AF9D159BA
+ - cmd: LC_BUILD_VERSION
+ cmdsize: 24
+ platform: 1
+ minos: 658944
+ sdk: 658944
+ ntools: 0
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+ - cmd: LC_MAIN
+ cmdsize: 24
+ entryoff: 4016
+ stacksize: 0
+ - cmd: LC_LOAD_DYLIB
+ cmdsize: 56
+ dylib:
+ name: 24
+ timestamp: 2
+ current_version: 82102276
+ compatibility_version: 65536
+ PayloadString: /usr/lib/libSystem.B.dylib
+ ZeroPadBytes: 6
+ - cmd: LC_FUNCTION_STARTS
+ cmdsize: 16
+ dataoff: 4144
+ datasize: 8
+ - cmd: LC_DATA_IN_CODE
+ cmdsize: 16
+ dataoff: 4152
+ datasize: 0
+LinkEditData:
+ ExportTrie:
+ TerminalSize: 0
+ NodeOffset: 0
+ Name: ''
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000000
+ Other: 0x0000000000000000
+ ImportName: ''
+ Children:
+ - TerminalSize: 0
+ NodeOffset: 5
+ Name: _
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000000
+ Other: 0x0000000000000000
+ ImportName: ''
+ Children:
+ - TerminalSize: 2
+ NodeOffset: 33
+ Name: _mh_execute_header
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000000
+ Other: 0x0000000000000000
+ ImportName: ''
+ - TerminalSize: 3
+ NodeOffset: 37
+ Name: main
+ Flags: 0x0000000000000000
+ Address: 0x0000000000000FB0
+ Other: 0x0000000000000000
+ ImportName: ''
+ NameList:
+ - n_strx: 2
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 16
+ n_value: 4294967296
+ - n_strx: 22
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 4294971312
+ - n_strx: 28
+ n_type: 0x01
+ n_sect: 0
+ n_desc: 256
+ n_value: 0
+ StringTable:
+ - ' '
+ - __mh_execute_header
+ - _main
+ - dyld_stub_binder
+ - ''
+ - ''
+ - ''
+...
diff --git a/lit/Modules/lc_version_min.yaml b/lit/Modules/MachO/lc_version_min.yaml
index e79107069f33..e79107069f33 100644
--- a/lit/Modules/lc_version_min.yaml
+++ b/lit/Modules/MachO/lc_version_min.yaml
diff --git a/lit/Modules/MachO/subsections.yaml b/lit/Modules/MachO/subsections.yaml
new file mode 100644
index 000000000000..a92ef41d79fc
--- /dev/null
+++ b/lit/Modules/MachO/subsections.yaml
@@ -0,0 +1,126 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+#CHECK: Showing 2 sections
+#CHECK-NEXT: Index: 0
+#CHECK-NEXT: ID: 0x100
+#CHECK-NEXT: Name: __PAGEZERO
+#CHECK-NEXT: Type: container
+#CHECK-NEXT: Permissions: ---
+#CHECK-NEXT: Thread specific: no
+#CHECK-NEXT: VM address: 0x0
+#CHECK-NEXT: VM size: 4294967296
+#CHECK-NEXT: File size: 0
+#CHECK-NEXT: There are no subsections
+#CHECK-EMPTY:
+#CHECK-NEXT: Index: 1
+#CHECK-NEXT: ID: 0x200
+#CHECK-NEXT: Name: __TEXT
+#CHECK-NEXT: Type: container
+#CHECK-NEXT: Permissions: r-x
+#CHECK-NEXT: Thread specific: no
+#CHECK-NEXT: VM address: 0x100000000
+#CHECK-NEXT: VM size: 4096
+#CHECK-NEXT: File size: 4096
+#CHECK-NEXT: Showing 3 subsections
+#CHECK-NEXT: Index: 0
+#CHECK-NEXT: ID: 0x1
+#CHECK-NEXT: Name: __text
+#CHECK-NEXT: Type: code
+#CHECK-NEXT: Permissions: r-x
+#CHECK-NEXT: Thread specific: no
+#CHECK-NEXT: VM address: 0x100000f30
+#CHECK-NEXT: VM size: 22
+#CHECK-NEXT: File size: 22
+#CHECK-EMPTY:
+#CHECK-NEXT: Index: 1
+#CHECK-NEXT: ID: 0x2
+#CHECK-NEXT: Name: __unwind_info
+#CHECK-NEXT: Type: compact-unwind
+#CHECK-NEXT: Permissions: r-x
+#CHECK-NEXT: Thread specific: no
+#CHECK-NEXT: VM address: 0x100000f48
+#CHECK-NEXT: VM size: 76
+#CHECK-NEXT: File size: 76
+#CHECK-EMPTY:
+#CHECK-NEXT: Index: 2
+#CHECK-NEXT: ID: 0x3
+#CHECK-NEXT: Name: __eh_frame
+#CHECK-NEXT: Type: eh-frame
+#CHECK-NEXT: Permissions: r-x
+#CHECK-NEXT: Thread specific: no
+#CHECK-NEXT: VM address: 0x100000f98
+#CHECK-NEXT: VM size: 104
+#CHECK-NEXT: File size: 104
+
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x00000002
+ ncmds: 12
+ sizeofcmds: 728
+ flags: 0x00000085
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __PAGEZERO
+ vmaddr: 0
+ vmsize: 4294967296
+ fileoff: 0
+ filesize: 0
+ maxprot: 0
+ initprot: 0
+ nsects: 0
+ flags: 0
+ - cmd: LC_SEGMENT_64
+ cmdsize: 312
+ segname: __TEXT
+ vmaddr: 4294967296
+ vmsize: 4096
+ fileoff: 0
+ filesize: 4096
+ maxprot: 7
+ initprot: 5
+ nsects: 3
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000100000F30
+ size: 22
+ offset: 0x00000F30
+ align: 4
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __unwind_info
+ segname: __TEXT
+ addr: 0x0000000100000F48
+ size: 76
+ offset: 0x00000F48
+ align: 2
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - sectname: __eh_frame
+ segname: __TEXT
+ addr: 0x0000000100000F98
+ size: 104
+ offset: 0x00000F98
+ align: 3
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x0000000B
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+...
diff --git a/lit/Modules/PECOFF/dep-modules.yaml b/lit/Modules/PECOFF/dep-modules.yaml
new file mode 100644
index 000000000000..75a27e895234
--- /dev/null
+++ b/lit/Modules/PECOFF/dep-modules.yaml
@@ -0,0 +1,170 @@
+# REQUIRES: system-windows
+# RUN: yaml2obj < %p/export-dllfunc.yaml > %t.export-dllfunc.obj
+# RUN: yaml2obj < %s > %t.obj
+#
+# RUN: lld-link /machine:x64 /out:%t.export-dllfunc.dll /noentry /nodefaultlib /dll %t.export-dllfunc.obj /export:DllFunc
+# RUN: lld-link /out:%t.exe %t.obj %t.export-dllfunc.lib /nodefaultlib /entry:main /include:DllFunc
+#
+# RUN: lldb-test object-file -dep-modules %t.exe | FileCheck -check-prefix=DEPS %s
+
+
+# DEPS: Showing 1 dependent module(s)
+
+# Ignore checking the directory and any tentative string in the path.
+# DEPS: Name: {{.*}}dep-modules.yaml.{{.*}}export-dllfunc.dll
+
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC48C7442444000000004889542438894C2434B904000000E80000000089442430B908000000E8000000008944242C8B4424300344242C4883C448C3
+ Relocations:
+ - VirtualAddress: 27
+ SymbolName: 'DllFunc'
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 41
+ SymbolName: 'DllFunc'
+ Type: IMAGE_REL_AMD64_REL32
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: .bss
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: .xdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '0104010004820000'
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962
+ - Name: .pdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '000000003E00000000000000'
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 4
+ SymbolName: main
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 8
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: .llvm_addrsig
+ Characteristics: [ IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: '10'
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 62
+ NumberOfRelocations: 2
+ NumberOfLinenumbers: 0
+ CheckSum: 373303044
+ Number: 1
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: .bss
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 2657791889
+ Number: 4
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 48
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 149686238
+ Number: 5
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 2420588879
+ Number: 6
+ - Name: .llvm_addrsig
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 1
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 498536548
+ Number: 7
+ - Name: '@feat.00'
+ Value: 0
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: 'DllFunc'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lit/Modules/PECOFF/export-dllfunc.yaml b/lit/Modules/PECOFF/export-dllfunc.yaml
new file mode 100644
index 000000000000..55156e8c792f
--- /dev/null
+++ b/lit/Modules/PECOFF/export-dllfunc.yaml
@@ -0,0 +1,172 @@
+# REQUIRES: system-windows
+# RUN: yaml2obj < %s > %t.obj
+#
+# RUN: lld-link /machine:x64 /out:%t.dll /noentry /nodefaultlib /dll %t.obj /export:DllFunc
+#
+# RUN: lldb-test object-file %t.dll | FileCheck -check-prefix=BASIC-CHECK %s
+# RUN: lldb-test object-file -dep-modules %t.dll | FileCheck -check-prefix=DEPS %s
+
+
+# BASIC-CHECK: Showing 3 sections
+# BASIC-CHECK: Index: 0
+# BASIC-CHECK: Name: .text
+# BASIC-CHECK: Type: code
+# BASIC-CHECK: VM size: 22
+# BASIC-CHECK: File size: 512
+#
+# BASIC-CHECK: Index: 1
+# BASIC-CHECK: Name: .rdata
+# BASIC-CHECK: Type: data
+# BASIC-CHECK: VM size: {{.}}
+# BASIC-CHECK: File size: 512
+#
+# BASIC-CHECK: Index: 2
+# BASIC-CHECK: Name: .pdata
+# BASIC-CHECK: Type: data
+# BASIC-CHECK: VM size: 12
+# BASIC-CHECK: File size: 512
+#
+# DEPS: Showing 0 dependent module(s)
+
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 50894C24048B4C24040FAF4C2404890C248B042459C3
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: .bss
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: .xdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '0101010001020000'
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962
+ - Name: .pdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '000000001600000000000000'
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: 'DllFunc'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 4
+ SymbolName: 'DllFunc'
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 8
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: .llvm_addrsig
+ Characteristics: [ IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 1
+ SectionData: ''
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 22
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 3054557294
+ Number: 1
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: .bss
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 8
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 448359300
+ Number: 4
+ - Name: .drectve
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 48
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 149686238
+ Number: 5
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 3
+ NumberOfLinenumbers: 0
+ CheckSum: 3134470316
+ Number: 6
+ - Name: .llvm_addrsig
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 7
+ - Name: '@feat.00'
+ Value: 0
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: 'DllFunc'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/lit/Modules/PECOFF/lit.local.cfg b/lit/Modules/PECOFF/lit.local.cfg
new file mode 100644
index 000000000000..9ef350be1dee
--- /dev/null
+++ b/lit/Modules/PECOFF/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.yaml', '.test']
diff --git a/lit/Modules/PECOFF/sections-names.yaml b/lit/Modules/PECOFF/sections-names.yaml
new file mode 100644
index 000000000000..b62c0bc0426f
--- /dev/null
+++ b/lit/Modules/PECOFF/sections-names.yaml
@@ -0,0 +1,52 @@
+# RUN: yaml2obj %s > %t
+# RUN: lldb-test object-file %t | FileCheck %s
+
+# CHECK: Name: .text{{$}}
+# CHECK: Name: 1234567{{$}}
+# CHECK: Name: 12345678{{$}}
+# CHECK: Name: 123456789{{$}}
+
+--- !COFF
+OptionalHeader:
+ AddressOfEntryPoint: 4616
+ ImageBase: 1073741824
+ SectionAlignment: 4096
+ FileAlignment: 512
+ MajorOperatingSystemVersion: 6
+ MinorOperatingSystemVersion: 0
+ MajorImageVersion: 0
+ MinorImageVersion: 0
+ MajorSubsystemVersion: 6
+ MinorSubsystemVersion: 0
+ Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
+ DLLCharacteristics: [ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE ]
+ SizeOfStackReserve: 1048576
+ SizeOfStackCommit: 4096
+ SizeOfHeapReserve: 1048576
+ SizeOfHeapCommit: 4096
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 4096
+ VirtualSize: 64 # '@', if it makes its way into the name field
+ SectionData: DEADBEEFBAADF00D
+ - Name: 1234567
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 442368
+ VirtualSize: 64
+ SectionData: DEADBEEFBAADF00D
+ - Name: 12345678
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 446464
+ VirtualSize: 64
+ SectionData: DEADBEEFBAADF00D
+ - Name: 123456789
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 450560
+ VirtualSize: 64
+ SectionData: DEADBEEFBAADF00D
+symbols: []
+...
diff --git a/lit/Python/crashlog.test b/lit/Python/crashlog.test
new file mode 100644
index 000000000000..93d9cbabbe2d
--- /dev/null
+++ b/lit/Python/crashlog.test
@@ -0,0 +1,99 @@
+# -*- python -*-
+# REQUIRES: system-darwin
+# RUN: cd %S/../../examples/python && %lldb -S %s | FileCheck %s
+# CHECK-LABEL: {{S}}KIP BEYOND CHECKS
+script
+import crashlog
+cl = crashlog.CrashLog
+images = [
+"0x10b60b000 - 0x10f707fff com.apple.LLDB.framework (1.1000.11.38.2 - 1000.11.38.2) <96E36F5C-1A83-39A1-8713-5FDD9701C3F1> /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/LLDB",
+# CHECK: 0x10b60b000
+# CHECK: 0x10f707fff
+# CHECK: com.apple.LLDB.framework
+# CHECK: 96E36F5C-1A83-39A1-8713-5FDD9701C3F1
+# CHECK: /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/LLDB
+
+"0x104591000 - 0x1055cfff7 +llvm-dwarfdump (0) <B104CFA1-046A-36A6-8EB4-07DDD7CC2DF3> /Users/USER 1/Documents/*/llvm-dwarfdump",
+# CHECK: 0x104591000
+# CHECK: 0x1055cfff7
+# CHECK: llvm-dwarfdump
+# CHECK: (0)
+# CHECK: B104CFA1-046A-36A6-8EB4-07DDD7CC2DF3
+# CHECK: /Users/USER 1/Documents/*/llvm-dwarfdump
+
+"0x7fff63f20000 - 0x7fff63f77ff7 libc++.1.dylib (400.9.4) <D4AB366F-48A9-3C7D-91BD-41198F69DD57> /usr/lib/libc++.1.dylib",
+# CHECK: 0x7fff63f20000
+# CHECK: 0x7fff63f77ff7
+# CHECK: libc++.1.dylib
+# CHECK: (400.9.4)
+# CHECK: D4AB366F-48A9-3C7D-91BD-41198F69DD57
+# CHECK: /usr/lib/libc++.1.dylib
+
+"0x1111111 - 0x22222 +MyApp Pro arm64 <01234> /tmp/MyApp Pro.app/MyApp Pro",
+# CHECK: 0x1111111
+# CHECK: 0x22222
+# CHECK: MyApp Pro arm64
+# CHECK: None
+# CHECK: 01234
+# CHECK: /tmp/MyApp Pro.app/MyApp Pro
+
+"0x1111111 - 0x22222 +MyApp Pro (0) <01234> /tmp/MyApp Pro.app/MyApp Pro",
+# CHECK: 0x1111111
+# CHECK: 0x22222
+# CHECK: MyApp Pro
+# CHECK: (0)
+# CHECK: 01234
+# CHECK: /tmp/MyApp Pro.app/MyApp Pro
+
+"0x7fff63f20000 - 0x7fff63f77ff7 libc++.1.dylib (400.9.4) /usr/lib/libc++.1.dylib"
+# CHECK: 0x7fff63f20000
+# CHECK: 0x7fff63f77ff7
+# CHECK: libc++.1.dylib
+# CHECK: (400.9.4)
+# CHECK: None
+# CHECK: /usr/lib/libc++.1.dylib
+]
+# CHECK-LABEL: FRAMES
+frames = [
+"0 libsystem_kernel.dylib 0x00007fff684b78a6 read + 10",
+# CHECK: 0
+# CHECK: libsystem_kernel.dylib
+# CHECK: 0x00007fff684b78a6
+# CHECK: read + 10
+"1 com.apple.LLDB.framework 0x000000010f7954af lldb_private::HostNativeThreadBase::ThreadCreateTrampoline(void*) + 105",
+# CHECK: 1
+# CHECK: com.apple.LLDB.framework
+# CHECK: 0x000000010f7954af
+# CHECK: lldb_private{{.*}} + 105
+"2 MyApp Pro arm64 0x000000019b0db3a8 foo + 72",
+# CHECK: 2
+# CHECK: MyApp Pro arm64
+# CHECK: 0x000000019b0db3a8
+# CHECK: foo + 72
+"3 He 0x1 0x000000019b0db3a8 foo + 72"
+# CHECK: 3
+# CHECK: He 0x1
+# CHECK: 0x000000019b0db3a8
+# CHECK: foo + 72
+]
+
+
+# Avoid matching the text inside the input.
+print("SKIP BEYOND CHECKS")
+for image in images:
+ print('"%s"'%image)
+ print("--------------")
+ match = cl.image_regex_uuid.search(image)
+ for group in match.groups():
+ print(group)
+
+print("FRAMES")
+for frame in frames:
+ print('"%s"'%frame)
+ print("--------------")
+ match = cl.frame_regex.search(frame)
+ for group in match.groups():
+ print(group)
+
+exit()
+quit
diff --git a/lit/Quit/TestQuitExitCode-30.test b/lit/Quit/TestQuitExitCode-30.test
index 0f6eff927f0c..5e74c9db79c4 100644
--- a/lit/Quit/TestQuitExitCode-30.test
+++ b/lit/Quit/TestQuitExitCode-30.test
@@ -1,3 +1,3 @@
# UNSUPPORTED: windows
-# RUN: python %S/expect_exit_code.py 226 %lldb -b -s %s
+# RUN: %python %S/expect_exit_code.py 226 %lldb -b -s %s
q -30
diff --git a/lit/Quit/TestQuitExitCode30.test b/lit/Quit/TestQuitExitCode30.test
index b5249400ec2f..687d048c480d 100644
--- a/lit/Quit/TestQuitExitCode30.test
+++ b/lit/Quit/TestQuitExitCode30.test
@@ -1,3 +1,3 @@
# UNSUPPORTED: windows
-# RUN: python %S/expect_exit_code.py 30 %lldb -b -s %s
+# RUN: %python %S/expect_exit_code.py 30 %lldb -b -s %s
q 30
diff --git a/lit/Quit/TestQuitExitCodeHexA.test b/lit/Quit/TestQuitExitCodeHexA.test
index e06c25b0619f..43cfd591961e 100644
--- a/lit/Quit/TestQuitExitCodeHexA.test
+++ b/lit/Quit/TestQuitExitCodeHexA.test
@@ -1,3 +1,3 @@
# UNSUPPORTED: windows
-# RUN: python %S/expect_exit_code.py 10 %lldb -b -s %s
+# RUN: %python %S/expect_exit_code.py 10 %lldb -b -s %s
q 0xA
diff --git a/lit/Quit/lit.local.cfg b/lit/Quit/lit.local.cfg
deleted file mode 100644
index df9b335dd131..000000000000
--- a/lit/Quit/lit.local.cfg
+++ /dev/null
@@ -1 +0,0 @@
-config.suffixes = ['.test']
diff --git a/lit/Reproducer/Inputs/GDBRemoteCapture.in b/lit/Reproducer/Inputs/GDBRemoteCapture.in
new file mode 100644
index 000000000000..8df7ca42fee0
--- /dev/null
+++ b/lit/Reproducer/Inputs/GDBRemoteCapture.in
@@ -0,0 +1,6 @@
+breakpoint set -f simple.c -l 13
+run
+bt
+cont
+reproducer status
+reproducer generate
diff --git a/lit/Reproducer/Inputs/GDBRemoteReplay.in b/lit/Reproducer/Inputs/GDBRemoteReplay.in
new file mode 100644
index 000000000000..1364c7e72764
--- /dev/null
+++ b/lit/Reproducer/Inputs/GDBRemoteReplay.in
@@ -0,0 +1,5 @@
+reproducer status
+breakpoint set -f simple.c -l 13
+run
+bt
+cont
diff --git a/lit/Reproducer/Inputs/simple.c b/lit/Reproducer/Inputs/simple.c
new file mode 100644
index 000000000000..a4585b380ca6
--- /dev/null
+++ b/lit/Reproducer/Inputs/simple.c
@@ -0,0 +1,19 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+
+void foo() {
+ printf("testing\n");
+}
+
+int main (int argc, char const *argv[]) {
+ foo();
+ return 0;
+}
diff --git a/lit/Reproducer/TestDriverOptions.test b/lit/Reproducer/TestDriverOptions.test
new file mode 100644
index 000000000000..c0713295685d
--- /dev/null
+++ b/lit/Reproducer/TestDriverOptions.test
@@ -0,0 +1,7 @@
+# Check that errors are propagated to the driver.
+
+# RUN: not %lldb --capture %t/bogus/bogus 2>&1 | FileCheck %s --check-prefix CAPTURE
+# RUN: not %lldb --replay %t/bogus/bogus 2>&1 | FileCheck %s --check-prefix REPLAY
+
+# CAPTURE: unable to create reproducer directory
+# REPLAY: unable to load reproducer index
diff --git a/lit/Reproducer/TestGDBRemoteRepro.test b/lit/Reproducer/TestGDBRemoteRepro.test
new file mode 100644
index 000000000000..6a6bdd780a85
--- /dev/null
+++ b/lit/Reproducer/TestGDBRemoteRepro.test
@@ -0,0 +1,26 @@
+# UNSUPPORTED: system-windows, system-freebsd
+
+# This tests the replaying of GDB remote packets.
+#
+# We issue the same commands and ensure the output is identical to the original
+# process. To ensure we're not actually running the original binary we check
+# that the string "testing" is not printed.
+
+# RUN: %clang %S/Inputs/simple.c -g -o %t.out
+# RUN: %lldb -x -b -s %S/Inputs/GDBRemoteCapture.in --capture %T/reproducer -- %t.out | FileCheck %s --check-prefix CHECK --check-prefix CAPTURE
+# RUN: %lldb -x -b -s %S/Inputs/GDBRemoteReplay.in --replay %T/reproducer -- %t.out | FileCheck %s --check-prefix CHECK --check-prefix REPLAY
+
+# CHECK: Breakpoint 1
+# CHECK: Process {{.*}} stopped
+# CHECK: Process {{.*}} launched
+# CHECK: thread {{.*}} stop reason = breakpoint
+# CHECK: frame {{.*}} simple.c
+
+# CAPTURE: testing
+# REPLAY-NOT: testing
+
+# CHECK: Process {{.*}} resuming
+# CHECK: Process {{.*}} exited
+
+# CAPTURE: Reproducer is in capture mode.
+# CAPTURE: Reproducer written
diff --git a/lit/Settings/Inputs/EchoCommandsAll.out b/lit/Settings/Inputs/EchoCommandsAll.out
new file mode 100644
index 000000000000..45b772919760
--- /dev/null
+++ b/lit/Settings/Inputs/EchoCommandsAll.out
@@ -0,0 +1,6 @@
+# CHECK: (lldb) command source -s {{.*\n}}
+# CHECK: (lldb) command source -s {{.*\n}}
+# CHECK-NEXT: Executing commands in {{.*\n}}
+# CHECK-NEXT: Evaluate expr 1+2
+# CHECK-NEXT: expr 1+2
+# CHECK-NEXT: (int) $0 = 3
diff --git a/lit/Settings/Inputs/EchoCommandsNoComments.out b/lit/Settings/Inputs/EchoCommandsNoComments.out
new file mode 100644
index 000000000000..a0b653a8f4cc
--- /dev/null
+++ b/lit/Settings/Inputs/EchoCommandsNoComments.out
@@ -0,0 +1,5 @@
+# CHECK: (lldb) command source -s {{.*\n}}
+# CHECK: (lldb) command source -s {{.*\n}}
+# CHECK-NEXT: Executing commands in {{.*\n}}
+# CHECK-NEXT: expr 1+2
+# CHECK-NEXT: (int) $0 = 3
diff --git a/lit/Settings/Inputs/EchoCommandsNone.out b/lit/Settings/Inputs/EchoCommandsNone.out
new file mode 100644
index 000000000000..fca1bbb50ca0
--- /dev/null
+++ b/lit/Settings/Inputs/EchoCommandsNone.out
@@ -0,0 +1,4 @@
+# CHECK: (lldb) command source -s {{.*\n}}
+# CHECK: (lldb) command source -s {{.*\n}}
+# CHECK-NEXT: Executing commands in {{.*\n}}
+# CHECK-NEXT: (int) $0 = 3
diff --git a/lit/Settings/Inputs/EchoCommandsQuiet.out b/lit/Settings/Inputs/EchoCommandsQuiet.out
new file mode 100644
index 000000000000..12ad094292de
--- /dev/null
+++ b/lit/Settings/Inputs/EchoCommandsQuiet.out
@@ -0,0 +1,2 @@
+# CHECK: (lldb) command source -s 1 {{.*\n}}
+# CHECK-NEXT: (lldb) command source -s 1 {{.*\n}}
diff --git a/lit/Settings/Inputs/EchoCommandsTest.in b/lit/Settings/Inputs/EchoCommandsTest.in
new file mode 100644
index 000000000000..304648e81e10
--- /dev/null
+++ b/lit/Settings/Inputs/EchoCommandsTest.in
@@ -0,0 +1,2 @@
+# Evaluate expr 1+2
+expr 1+2
diff --git a/lit/Settings/TestDisableColor.test b/lit/Settings/TestDisableColor.test
new file mode 100644
index 000000000000..659e2073fa21
--- /dev/null
+++ b/lit/Settings/TestDisableColor.test
@@ -0,0 +1,7 @@
+# RUN: %lldb -x -b -s %s | FileCheck %s
+settings show use-color
+q
+# This tests that LLDB turns off use-color if the output file is not an
+# interactive terminal. In this example, use-color should be off because LLDB
+# is run just by the non-interactive lit test runner.
+# CHECK: use-color (boolean) = false
diff --git a/lit/Settings/TestDisassemblyFormat.test b/lit/Settings/TestDisassemblyFormat.test
new file mode 100644
index 000000000000..29975a1b0163
--- /dev/null
+++ b/lit/Settings/TestDisassemblyFormat.test
@@ -0,0 +1,2 @@
+# RUN: %lldb -x -b -o "settings show disassembly-format" | FileCheck %s
+# CHECK: disassembly-format (format-string) = "{${function.initial-function}{${module.file.basename}\`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}\`}{${function.name-without-args}}:\n}{${current-pc-arrow} }${addr-file-or-load}{ <${function.concrete-only-addr-offset-no-padding}>}: "
diff --git a/lit/Settings/TestEchoCommands.test b/lit/Settings/TestEchoCommands.test
new file mode 100644
index 000000000000..67547eaabf89
--- /dev/null
+++ b/lit/Settings/TestEchoCommands.test
@@ -0,0 +1,4 @@
+# RUN: %lldb -x -b -o 'settings set interpreter.echo-comment-commands true' -s %S/Inputs/EchoCommandsTest.in | FileCheck %S/Inputs/EchoCommandsAll.out
+# RUN: %lldb -x -b -o 'settings set interpreter.echo-comment-commands false' -s %S/Inputs/EchoCommandsTest.in | FileCheck %S/Inputs/EchoCommandsNoComments.out
+# RUN: %lldb -x -b -o 'settings set interpreter.echo-commands false' -s %S/Inputs/EchoCommandsTest.in | FileCheck %S/Inputs/EchoCommandsNone.out
+# RUN: %lldb -x -b --source-quietly -s %S/Inputs/EchoCommandsTest.in | FileCheck %S/Inputs/EchoCommandsQuiet.out
diff --git a/lit/Settings/TestSettingsSet.test b/lit/Settings/TestSettingsSet.test
new file mode 100644
index 000000000000..0def3faaadbb
--- /dev/null
+++ b/lit/Settings/TestSettingsSet.test
@@ -0,0 +1,15 @@
+# This tests setting setting values.
+
+# Check that setting an empty value with -f(orce) clears the value.
+# RUN: %lldb -b -s %s 2>&1 | FileCheck %s
+
+settings set tab-size 16
+settings show tab-size
+# CHECK: tab-size (unsigned) = 16
+
+settings set -f tab-size
+settings show tab-size
+# CHECK: tab-size (unsigned) = 4
+
+settings set tab-size
+# CHECK: error: 'settings set' takes more arguments
diff --git a/lit/Settings/TestSettingsWrite.test b/lit/Settings/TestSettingsWrite.test
new file mode 100644
index 000000000000..72dcd73e33f0
--- /dev/null
+++ b/lit/Settings/TestSettingsWrite.test
@@ -0,0 +1,32 @@
+# This tests writing and reading settings from LLDB.
+
+# Check that the settings can be written to file and read again without
+# altering the values.
+# RUN: %lldb -b -o 'settings write -f %t.foo' -o 'settings read -f %t.foo' -o 'settings write -f %t.bar' -o 'settings read -f %t.bar' 2>&1 | FileCheck %s --check-prefix SUCCESS
+# RUN: diff -w %t.foo %t.bar
+# SUCCESS-NOT: error:
+
+# Check that exporting target settings only export target settings and nothing else.
+# RUN: %lldb -b -o 'settings write -f %t.target target' 2>&1 | FileCheck %s --check-prefix SUCCESS
+# RUN: cat %t.target | FileCheck %s --check-prefix TARGET
+# TARGET: settings set -f target
+# TARGET-NOT: settings set -f platform
+# TARGET-NOT: settings set -f symbols
+# TARGET-NOT: settings set -f interpreter
+# TARGET-NOT: settings set -f plugin
+
+# Check that settings appear twice when appending.
+# RUN: %lldb -b -o 'settings write -a -f %t.append target' -o 'settings write -a -f %t.append target' 2>&1 | FileCheck %s --check-prefix SUCCESS
+# RUN: cat %t.append | FileCheck %s --check-prefix APPEND
+# APPEND: settings set -f target.language
+# APPEND: settings set -f target.language
+
+# Check that an error is printed for non-existing setting.
+# RUN: echo "settings set -f bogus" > %t.bogus_setting
+# RUN: %lldb -b -o 'settings read -f %t.bogus_setting' 2>&1 | FileCheck %s --check-prefix BOGUS-SETTING
+# BOGUS-SETTING: error: invalid value path
+
+# Check that an error is printed for invalid value.
+# RUN: echo "settings set -f target.language bogus" > %t.bogus_value
+# RUN: %lldb -b -o 'settings read -f %t.bogus_value' 2>&1 | FileCheck %s --check-prefix BOGUS-VALUE
+# BOGUS-VALUE: error: invalid language type
diff --git a/lit/Suite/lit.cfg b/lit/Suite/lit.cfg
index eb0fac9541ac..7bc16e9a08f4 100644
--- a/lit/Suite/lit.cfg
+++ b/lit/Suite/lit.cfg
@@ -19,6 +19,19 @@ config.test_source_root = os.path.join(config.lldb_src_root, 'packages',
'Python', 'lldbsuite', 'test')
config.test_exec_root = config.test_source_root
+# macOS flags needed for LLDB built with address sanitizer.
+if 'Address' in config.llvm_use_sanitizer and \
+ 'Darwin' in config.host_os and \
+ 'x86' in config.host_triple:
+ import subprocess
+ resource_dir = subprocess.check_output(
+ config.cmake_cxx_compiler +' -print-resource-dir', shell=True).strip()
+ runtime = os.path.join(resource_dir, 'lib', 'darwin',
+ 'libclang_rt.asan_osx_dynamic.dylib')
+ config.environment['ASAN_OPTIONS'] = \
+ 'detect_stack_use_after_return=1'
+ config.environment['DYLD_INSERT_LIBRARIES'] = runtime
+
# Build dotest command.
dotest_cmd = [config.dotest_path, '-q']
dotest_cmd.extend(config.dotest_args_str.split(';'))
diff --git a/lit/Suite/lit.site.cfg.in b/lit/Suite/lit.site.cfg.in
index 40f3310c6129..1a24f8c24c2d 100644
--- a/lit/Suite/lit.site.cfg.in
+++ b/lit/Suite/lit.site.cfg.in
@@ -1,6 +1,6 @@
@LIT_SITE_CFG_IN_HEADER@
-config.test_exec_root = "@LLVM_BINARY_DIR@"
+config.test_exec_root = "@LLDB_BINARY_DIR@"
config.llvm_src_root = "@LLVM_SOURCE_DIR@"
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
@@ -9,6 +9,10 @@ config.llvm_build_mode = "@LLVM_BUILD_MODE@"
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.lldb_obj_root = "@LLDB_BINARY_DIR@"
config.lldb_src_root = "@LLDB_SOURCE_DIR@"
+config.cmake_cxx_compiler = "@CMAKE_CXX_COMPILER@"
+config.host_os = "@HOST_OS@"
+config.host_triple = "@LLVM_HOST_TRIPLE@"
+config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
config.target_triple = "@TARGET_TRIPLE@"
config.python_executable = "@PYTHON_EXECUTABLE@"
config.dotest_path = "@LLDB_SOURCE_DIR@/test/dotest.py"
diff --git a/lit/Suite/lldbtest.py b/lit/Suite/lldbtest.py
index fbdab183a4a3..12591f3ba505 100644
--- a/lit/Suite/lldbtest.py
+++ b/lit/Suite/lldbtest.py
@@ -9,6 +9,24 @@ import lit.TestRunner
import lit.util
from lit.formats.base import TestFormat
+def getBuildDir(cmd):
+ found = False
+ for arg in cmd:
+ if found:
+ return arg
+ if arg == '--build-dir':
+ found = True
+ return None
+
+def mkdir_p(path):
+ import errno
+ try:
+ os.makedirs(path)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+ if not os.path.isdir(path):
+ raise OSError(errno.ENOTDIR, "%s is not a directory"%path)
class LLDBTest(TestFormat):
def __init__(self, dotest_cmd):
@@ -44,11 +62,28 @@ class LLDBTest(TestFormat):
return (lit.Test.UNSUPPORTED, 'Test is unsupported')
testPath, testFile = os.path.split(test.getSourcePath())
- # On Windows, the system does not always correctly interpret shebang lines.
- # To make sure we can execute the tests, add python exe as the first parameter
- # of the command.
+ # On Windows, the system does not always correctly interpret
+ # shebang lines. To make sure we can execute the tests, add
+ # python exe as the first parameter of the command.
cmd = [sys.executable] + self.dotest_cmd + [testPath, '-p', testFile]
+ # The macOS system integrity protection (SIP) doesn't allow injecting
+ # libraries into system binaries, but this can be worked around by
+ # copying the binary into a different location.
+ if 'DYLD_INSERT_LIBRARIES' in test.config.environment and \
+ (sys.executable.startswith('/System/') or \
+ sys.executable.startswith('/usr/')):
+ builddir = getBuildDir(cmd)
+ mkdir_p(builddir)
+ copied_python = os.path.join(builddir, 'copied-system-python')
+ if not os.path.isfile(copied_python):
+ import shutil, subprocess
+ python = subprocess.check_output([
+ '/usr/bin/python2.7', '-c',
+ 'import sys; print sys.executable']).strip()
+ shutil.copy(python, copied_python)
+ cmd[0] = copied_python
+
try:
out, err, exitCode = lit.util.executeCommand(
cmd,
@@ -59,7 +94,10 @@ class LLDBTest(TestFormat):
litConfig.maxIndividualTestTime))
if exitCode:
- return lit.Test.FAIL, out + err
+ if 'FAIL:' in out or 'FAIL:' in err:
+ return lit.Test.FAIL, out + err
+ if 'XPASS:' in out or 'XPASS:' in err:
+ return lit.Test.XPASS, out + err
passing_test_line = 'RESULT: PASSED'
if passing_test_line not in out and passing_test_line not in err:
diff --git a/lit/SymbolFile/Breakpad/Inputs/basic-elf.yaml b/lit/SymbolFile/Breakpad/Inputs/basic-elf.yaml
new file mode 100644
index 000000000000..4d6a1e15b604
--- /dev/null
+++ b/lit/SymbolFile/Breakpad/Inputs/basic-elf.yaml
@@ -0,0 +1,33 @@
+# A very basic ELF file to serve as a recipient of breakpad info
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x00000000004000D0
+Sections:
+ - Name: .text1
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400000
+ AddressAlign: 0x0000000000001000
+ Size: 0xb0
+ - Name: .text2
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x00000000004000B0
+ AddressAlign: 0x0000000000000010
+ Size: 0x42
+Symbols:
+DynamicSymbols:
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ VAddr: 0x400000
+ Align: 0x1000
+ Sections:
+ - Section: .text1
+ - Section: .text2
+...
diff --git a/lit/SymbolFile/Breakpad/Inputs/symtab.syms b/lit/SymbolFile/Breakpad/Inputs/symtab.syms
new file mode 100644
index 000000000000..ab03b50a75a9
--- /dev/null
+++ b/lit/SymbolFile/Breakpad/Inputs/symtab.syms
@@ -0,0 +1,7 @@
+MODULE Linux x86_64 761550E08086333960A9074A9CE2895C0 a.out
+INFO CODE_ID E05015768680393360A9074A9CE2895C
+FILE 0 /tmp/a.c
+PUBLIC b0 0 f1
+PUBLIC m c0 0 f2
+PUBLIC d0 0 _start
+PUBLIC ff 0 _out_of_range_ignored
diff --git a/lit/SymbolFile/Breakpad/symtab.test b/lit/SymbolFile/Breakpad/symtab.test
new file mode 100644
index 000000000000..6bb26eb108c9
--- /dev/null
+++ b/lit/SymbolFile/Breakpad/symtab.test
@@ -0,0 +1,23 @@
+# RUN: yaml2obj %S/Inputs/basic-elf.yaml > %T/symtab.out
+# RUN: %lldb %T/symtab.out -o "target symbols add -s symtab.out %S/Inputs/symtab.syms" \
+# RUN: -s %s | FileCheck %s
+
+# CHECK-LABEL: (lldb) image dump symtab symtab.out
+# CHECK: Symtab, file = {{.*}}symtab.out, num_symbols = 3:
+# CHECK: Index UserID DSX Type File Address/Value Load Address Size Flags Name
+# CHECK: [ 0] 0 X Code 0x00000000004000b0 0x0000000000000010 0x00000000 f1
+# CHECK: [ 1] 0 X Code 0x00000000004000c0 0x0000000000000010 0x00000000 f2
+# CHECK: [ 2] 0 X Code 0x00000000004000d0 0x0000000000000022 0x00000000 _start
+
+# CHECK-LABEL: (lldb) image lookup -a 0x4000b0 -v
+# CHECK: Address: symtab.out[0x00000000004000b0] (symtab.out.PT_LOAD[0]..text2 + 0)
+# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000b0-0x00000000004000c0), name="f1"
+
+# CHECK-LABEL: (lldb) image lookup -n f2 -v
+# CHECK: Address: symtab.out[0x00000000004000c0] (symtab.out.PT_LOAD[0]..text2 + 16)
+# CHECK: Symbol: id = {0x00000000}, range = [0x00000000004000c0-0x00000000004000d0), name="f2"
+
+image dump symtab symtab.out
+image lookup -a 0x4000b0 -v
+image lookup -n f2 -v
+exit
diff --git a/lit/SymbolFile/DWARF/apple-index-is-used.cpp b/lit/SymbolFile/DWARF/apple-index-is-used.cpp
index 104d86756e48..00440531e99f 100644
--- a/lit/SymbolFile/DWARF/apple-index-is-used.cpp
+++ b/lit/SymbolFile/DWARF/apple-index-is-used.cpp
@@ -1,5 +1,5 @@
// Test that we use the apple indexes.
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols %t | FileCheck %s
// CHECK: .apple_names index present
diff --git a/lit/SymbolFile/DWARF/array-sizes.s b/lit/SymbolFile/DWARF/array-sizes.s
new file mode 100644
index 000000000000..c472d54a489c
--- /dev/null
+++ b/lit/SymbolFile/DWARF/array-sizes.s
@@ -0,0 +1,147 @@
+# This tests a bug where we would incorrectly parse the size of an array if that
+# size happened to match an existing DIE offset. This happened because we
+# misinterpreted that value as a reference to a DIE specifying the VLA size even
+# though the form was a data form (as it should be).
+
+# REQUIRES: lld
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: ld.lld %t.o -o %t
+# RUN: lldb-test symbols %t | FileCheck %s
+
+# CHECK: Variable{0xffffffff0000001e}, name = "X"
+# CHECK-SAME: type = {ffffffff00000033} 0x{{[0-9a-f]*}} (char [56])
+
+
+# Generated from "char X[47];"
+# The array size was modified by hand.
+
+ .text
+ .file "-"
+ .file 1 "/tmp" "<stdin>"
+ .type X,@object # @X
+ .comm X,63,16
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "clang version 8.0.0 (trunk 349604) (llvm/trunk 349608)" # string offset=0
+.Linfo_string1:
+ .asciz "-" # string offset=55
+.Linfo_string2:
+ .asciz "/tmp" # string offset=57
+.Linfo_string3:
+ .asciz "X" # string offset=62
+.Linfo_string4:
+ .asciz "char" # string offset=64
+.Linfo_string5:
+ .asciz "__ARRAY_SIZE_TYPE__" # string offset=69
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 1 # DW_CHILDREN_yes
+ .byte 37 # DW_AT_producer
+ .byte 14 # DW_FORM_strp
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 16 # DW_AT_stmt_list
+ .byte 23 # DW_FORM_sec_offset
+ .byte 27 # DW_AT_comp_dir
+ .byte 14 # DW_FORM_strp
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 2 # Abbreviation Code
+ .byte 52 # DW_TAG_variable
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 63 # DW_AT_external
+ .byte 25 # DW_FORM_flag_present
+ .byte 58 # DW_AT_decl_file
+ .byte 11 # DW_FORM_data1
+ .byte 59 # DW_AT_decl_line
+ .byte 11 # DW_FORM_data1
+ .byte 2 # DW_AT_location
+ .byte 24 # DW_FORM_exprloc
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 3 # Abbreviation Code
+ .byte 1 # DW_TAG_array_type
+ .byte 1 # DW_CHILDREN_yes
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 4 # Abbreviation Code
+ .byte 33 # DW_TAG_subrange_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 73 # DW_AT_type
+ .byte 19 # DW_FORM_ref4
+ .byte 55 # DW_AT_count
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 5 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 6 # Abbreviation Code
+ .byte 36 # DW_TAG_base_type
+ .byte 0 # DW_CHILDREN_no
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 11 # DW_AT_byte_size
+ .byte 11 # DW_FORM_data1
+ .byte 62 # DW_AT_encoding
+ .byte 11 # DW_FORM_data1
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x43 DW_TAG_compile_unit
+ .long .Linfo_string0 # DW_AT_producer
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long 0 # DW_AT_stmt_list
+ .long .Linfo_string2 # DW_AT_comp_dir
+ .byte 2 # Abbrev [2] 0x1e:0x15 DW_TAG_variable
+ .long .Linfo_string3 # DW_AT_name
+ .long 51 # DW_AT_type
+ # DW_AT_external
+ .byte 1 # DW_AT_decl_file
+ .byte 1 # DW_AT_decl_line
+ .byte 9 # DW_AT_location
+ .byte 3
+ .quad X
+ .byte 3 # Abbrev [3] 0x33:0xc DW_TAG_array_type
+ .long 63 # DW_AT_type
+.Ldie:
+ .byte 4 # Abbrev [4] 0x38:0x6 DW_TAG_subrange_type
+ .long 70 # DW_AT_type
+ .byte .Ldie-.Lcu_begin0 # DW_AT_count - should match the offset of an existing die
+ .byte 0 # End Of Children Mark
+ .byte 5 # Abbrev [5] 0x3f:0x7 DW_TAG_base_type
+ .long .Linfo_string4 # DW_AT_name
+ .byte 6 # DW_AT_encoding
+ .byte 1 # DW_AT_byte_size
+ .byte 6 # Abbrev [6] 0x46:0x7 DW_TAG_base_type
+ .long .Linfo_string5 # DW_AT_name
+ .byte 8 # DW_AT_byte_size
+ .byte 7 # DW_AT_encoding
+ .byte 0 # End Of Children Mark
+.Ldebug_info_end0:
diff --git a/lit/SymbolFile/DWARF/childless-compile-unit.s b/lit/SymbolFile/DWARF/childless-compile-unit.s
new file mode 100644
index 000000000000..d167e0503c52
--- /dev/null
+++ b/lit/SymbolFile/DWARF/childless-compile-unit.s
@@ -0,0 +1,45 @@
+# Test that we don't crash when parsing slightly invalid DWARF. The compile
+# unit in this file sets DW_CHILDREN_no, but it still includes an
+# end-of-children marker in its contribution.
+
+# RUN: llvm-mc -triple x86_64-pc-linux %s -filetype=obj > %t.o
+# RUN: lldb-test symbols %t.o
+
+ .section .debug_str,"MS",@progbits,1
+.Linfo_string0:
+ .asciz "Hand-written DWARF"
+.Linfo_string1:
+ .asciz "-"
+.Linfo_string2:
+ .asciz "/tmp"
+
+ .section .debug_abbrev,"",@progbits
+ .byte 1 # Abbreviation Code
+ .byte 17 # DW_TAG_compile_unit
+ .byte 0 # DW_CHILDREN_no
+ .byte 37 # DW_AT_producer
+ .byte 14 # DW_FORM_strp
+ .byte 19 # DW_AT_language
+ .byte 5 # DW_FORM_data2
+ .byte 3 # DW_AT_name
+ .byte 14 # DW_FORM_strp
+ .byte 27 # DW_AT_comp_dir
+ .byte 14 # DW_FORM_strp
+ .byte 0 # EOM(1)
+ .byte 0 # EOM(2)
+ .byte 0 # EOM(3)
+
+ .section .debug_info,"",@progbits
+.Lcu_begin0:
+ .long .Lcu_length_end-.Lcu_length_start # Length of Unit
+.Lcu_length_start:
+ .short 4 # DWARF version number
+ .long .debug_abbrev # Offset Into Abbrev. Section
+ .byte 8 # Address Size (in bytes)
+ .byte 1 # Abbrev [1] 0xb:0x30 DW_TAG_compile_unit
+ .long .Linfo_string0 # DW_AT_producer
+ .short 12 # DW_AT_language
+ .long .Linfo_string1 # DW_AT_name
+ .long .Linfo_string2 # DW_AT_comp_dir
+ .byte 0 # Bogus End Of Children Mark
+.Lcu_length_end:
diff --git a/lit/SymbolFile/DWARF/debug-names-compressed.cpp b/lit/SymbolFile/DWARF/debug-names-compressed.cpp
index 076cac192522..aeb0ff1d01b1 100644
--- a/lit/SymbolFile/DWARF/debug-names-compressed.cpp
+++ b/lit/SymbolFile/DWARF/debug-names-compressed.cpp
@@ -3,7 +3,7 @@
// REQUIRES: lld, zlib
-// RUN: clang -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %s
+// RUN: %clang -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %s
// RUN: ld.lld %t.o -o %t --compress-debug-sections=zlib
// RUN: lldb-test symbols --find=variable --name=foo %t | FileCheck %s
diff --git a/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp b/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp
index 14d2bc076d78..f5122ebadae2 100644
--- a/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp
+++ b/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp
@@ -2,7 +2,7 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf -gpubnames
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols %t | FileCheck %s
diff --git a/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp b/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp
index 3a2cf0122951..84e3b62e17bb 100644
--- a/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp
+++ b/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp
@@ -3,8 +3,8 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t-1.o --target=x86_64-pc-linux -DONE -mllvm -accel-tables=Dwarf
-// RUN: clang %s -g -c -o %t-2.o --target=x86_64-pc-linux -DTWO -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t-1.o --target=x86_64-pc-linux -DONE -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t-2.o --target=x86_64-pc-linux -DTWO -mllvm -accel-tables=Dwarf
// RUN: ld.lld %t-1.o %t-2.o -o %t
// RUN: lldb-test symbols --find=variable --name=foo %t | FileCheck %s
diff --git a/lit/SymbolFile/DWARF/find-basic-function.cpp b/lit/SymbolFile/DWARF/find-basic-function.cpp
index d04c94b38547..3d175f63e047 100644
--- a/lit/SymbolFile/DWARF/find-basic-function.cpp
+++ b/lit/SymbolFile/DWARF/find-basic-function.cpp
@@ -1,6 +1,6 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=function --function-flags=base %t | \
// RUN: FileCheck --check-prefix=BASE %s
@@ -15,7 +15,7 @@
// RUN: lldb-test symbols --name=not_there --find=function %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
//
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=foo --find=function --function-flags=base %t | \
// RUN: FileCheck --check-prefix=BASE %s
// RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
@@ -29,7 +29,7 @@
// RUN: lldb-test symbols --name=not_there --find=function %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=function --function-flags=base %t | \
// RUN: FileCheck --check-prefix=BASE %s
diff --git a/lit/SymbolFile/DWARF/find-basic-namespace.cpp b/lit/SymbolFile/DWARF/find-basic-namespace.cpp
index 11a660bfba9f..e7655a37053c 100644
--- a/lit/SymbolFile/DWARF/find-basic-namespace.cpp
+++ b/lit/SymbolFile/DWARF/find-basic-namespace.cpp
@@ -1,6 +1,6 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=namespace %t | \
// RUN: FileCheck --check-prefix=FOO %s
@@ -9,7 +9,7 @@
// RUN: lldb-test symbols --name=not_there --find=namespace %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
//
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=foo --find=namespace %t | \
// RUN: FileCheck --check-prefix=FOO %s
// RUN: lldb-test symbols --name=foo --find=namespace --context=context %t | \
@@ -17,7 +17,7 @@
// RUN: lldb-test symbols --name=not_there --find=namespace %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=namespace %t | \
// RUN: FileCheck --check-prefix=FOO %s
diff --git a/lit/SymbolFile/DWARF/find-basic-type.cpp b/lit/SymbolFile/DWARF/find-basic-type.cpp
index a470ef762e61..060a5b41eebc 100644
--- a/lit/SymbolFile/DWARF/find-basic-type.cpp
+++ b/lit/SymbolFile/DWARF/find-basic-type.cpp
@@ -1,6 +1,6 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=type %t | \
// RUN: FileCheck --check-prefix=NAME %s
@@ -9,7 +9,7 @@
// RUN: lldb-test symbols --name=not_there --find=type %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
//
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=foo --find=type %t | \
// RUN: FileCheck --check-prefix=NAME %s
// RUN: lldb-test symbols --name=foo --context=context --find=type %t | \
@@ -17,7 +17,7 @@
// RUN: lldb-test symbols --name=not_there --find=type %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=type %t | \
// RUN: FileCheck --check-prefix=NAME %s
diff --git a/lit/SymbolFile/DWARF/find-basic-variable.cpp b/lit/SymbolFile/DWARF/find-basic-variable.cpp
index 222ad420d400..bca8f27e1d4e 100644
--- a/lit/SymbolFile/DWARF/find-basic-variable.cpp
+++ b/lit/SymbolFile/DWARF/find-basic-variable.cpp
@@ -1,6 +1,6 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=variable --context=context %t | \
// RUN: FileCheck --check-prefix=CONTEXT %s
@@ -11,7 +11,7 @@
// RUN: lldb-test symbols --name=not_there --find=variable %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
//
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=foo --find=variable --context=context %t | \
// RUN: FileCheck --check-prefix=CONTEXT %s
// RUN: lldb-test symbols --name=foo --find=variable %t | \
@@ -21,7 +21,7 @@
// RUN: lldb-test symbols --name=not_there --find=variable %t | \
// RUN: FileCheck --check-prefix=EMPTY %s
//
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=variable --context=context %t | \
// RUN: FileCheck --check-prefix=CONTEXT %s
diff --git a/lit/SymbolFile/DWARF/find-function-regex.cpp b/lit/SymbolFile/DWARF/find-function-regex.cpp
index 2e099eb4fd74..b1e9d10e82ac 100644
--- a/lit/SymbolFile/DWARF/find-function-regex.cpp
+++ b/lit/SymbolFile/DWARF/find-function-regex.cpp
@@ -1,13 +1,13 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=f.o --regex --find=function %t | FileCheck %s
//
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=f.o --regex --find=function %t | FileCheck %s
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=f.o --regex --find=function %t | FileCheck %s
diff --git a/lit/SymbolFile/DWARF/find-method-local-struct.cpp b/lit/SymbolFile/DWARF/find-method-local-struct.cpp
index 19b41e77c17d..3da4a4a23f8a 100644
--- a/lit/SymbolFile/DWARF/find-method-local-struct.cpp
+++ b/lit/SymbolFile/DWARF/find-method-local-struct.cpp
@@ -1,4 +1,4 @@
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
// RUN: FileCheck %s
diff --git a/lit/SymbolFile/DWARF/find-method.cpp b/lit/SymbolFile/DWARF/find-method.cpp
index 013e13435b9f..7e7710fd472b 100644
--- a/lit/SymbolFile/DWARF/find-method.cpp
+++ b/lit/SymbolFile/DWARF/find-method.cpp
@@ -1,11 +1,11 @@
// REQUIRES: lld
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
// RUN: FileCheck %s
//
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=foo --find=function --function-flags=method %t | \
// RUN: FileCheck %s
diff --git a/lit/SymbolFile/DWARF/find-qualified-variable.cpp b/lit/SymbolFile/DWARF/find-qualified-variable.cpp
index ca1b3184fbe7..1ad3e7fbadf5 100644
--- a/lit/SymbolFile/DWARF/find-qualified-variable.cpp
+++ b/lit/SymbolFile/DWARF/find-qualified-variable.cpp
@@ -1,4 +1,4 @@
-// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx
+// RUN: %clang %s -g -c -o %t --target=x86_64-apple-macosx
// RUN: lldb-test symbols --name=A::foo --find=variable %t | FileCheck %s
// CHECK: Found 1 variables:
diff --git a/lit/SymbolFile/DWARF/find-type-in-function.cpp b/lit/SymbolFile/DWARF/find-type-in-function.cpp
index a0894284fa26..5c1b4b44523d 100644
--- a/lit/SymbolFile/DWARF/find-type-in-function.cpp
+++ b/lit/SymbolFile/DWARF/find-type-in-function.cpp
@@ -2,7 +2,7 @@
// XFAIL: *
-// RUN: clang %s -g -c -o %t.o --target=x86_64-pc-linux
+// RUN: %clang %s -g -c -o %t.o --target=x86_64-pc-linux
// RUN: ld.lld %t.o -o %t
// RUN: lldb-test symbols --name=foo --find=type %t | \
// RUN: FileCheck --check-prefix=NAME %s
diff --git a/lit/SymbolFile/DWARF/find-variable-dwo.cpp b/lit/SymbolFile/DWARF/find-variable-dwo.cpp
index 142ddc82cdab..b2fb1a375cf2 100644
--- a/lit/SymbolFile/DWARF/find-variable-dwo.cpp
+++ b/lit/SymbolFile/DWARF/find-variable-dwo.cpp
@@ -1,9 +1,9 @@
// REQUIRES: lld
-// RUN: clang %s -g -gsplit-dwarf -c -emit-llvm -o - --target=x86_64-pc-linux -DONE | \
+// RUN: %clang %s -g -gsplit-dwarf -c -emit-llvm -o - --target=x86_64-pc-linux -DONE | \
// RUN: llc -accel-tables=Dwarf -filetype=obj -split-dwarf-file=%t-1.dwo -o %t-1.o
// RUN: llvm-objcopy --split-dwo=%t-1.dwo %t-1.o
-// RUN: clang %s -g -gsplit-dwarf -c -emit-llvm -o - --target=x86_64-pc-linux -DTWO | \
+// RUN: %clang %s -g -gsplit-dwarf -c -emit-llvm -o - --target=x86_64-pc-linux -DTWO | \
// RUN: llc -accel-tables=Dwarf -filetype=obj -split-dwarf-file=%t-2.dwo -o %t-2.o
// RUN: llvm-objcopy --split-dwo=%t-2.dwo %t-2.o
// RUN: ld.lld %t-1.o %t-2.o -o %t
diff --git a/lit/SymbolFile/DWARF/find-variable-file.cpp b/lit/SymbolFile/DWARF/find-variable-file.cpp
index f71d4a2b09b6..5a95c5338f8f 100644
--- a/lit/SymbolFile/DWARF/find-variable-file.cpp
+++ b/lit/SymbolFile/DWARF/find-variable-file.cpp
@@ -1,15 +1,15 @@
// REQUIRES: lld
-// RUN: clang -g -c -o %t-1.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable %s
-// RUN: clang -g -c -o %t-2.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable %S/Inputs/find-variable-file-2.cpp
+// RUN: %clang -g -c -o %t-1.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable %s
+// RUN: %clang -g -c -o %t-2.o --target=x86_64-pc-linux -mllvm -accel-tables=Disable %S/Inputs/find-variable-file-2.cpp
// RUN: ld.lld %t-1.o %t-2.o -o %t
// RUN: lldb-test symbols --file=find-variable-file.cpp --find=variable %t | \
// RUN: FileCheck --check-prefix=ONE %s
// RUN: lldb-test symbols --file=find-variable-file-2.cpp --find=variable %t | \
// RUN: FileCheck --check-prefix=TWO %s
-// RUN: clang -g -c -o %t-1.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %s
-// RUN: clang -g -c -o %t-2.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %S/Inputs/find-variable-file-2.cpp
+// RUN: %clang -g -c -o %t-1.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %s
+// RUN: %clang -g -c -o %t-2.o --target=x86_64-pc-linux -mllvm -accel-tables=Dwarf %S/Inputs/find-variable-file-2.cpp
// RUN: ld.lld %t-1.o %t-2.o -o %t
// RUN: lldb-test symbols --file=find-variable-file.cpp --find=variable %t | \
// RUN: FileCheck --check-prefix=ONE %s
diff --git a/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit b/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
new file mode 100644
index 000000000000..c25d96c531d5
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/ast-functions.lldbinit
@@ -0,0 +1,8 @@
+
+break set -n main
+break set -n static_fn
+break set -n varargs_fn
+
+target modules dump ast
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit b/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
new file mode 100644
index 000000000000..3c0cf6d3cdfd
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/ast-types.lldbinit
@@ -0,0 +1,20 @@
+target variable TC
+target variable TS
+target variable TU
+target variable TE
+
+target variable ABCInt
+target variable ABCFloat
+target variable ABCVoid
+
+target variable AC0
+target variable ACNeg1
+
+target variable AC0D
+target variable ACNeg1D
+target variable AD
+target variable ADE
+
+target modules dump ast
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit b/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit
new file mode 100644
index 000000000000..cf06c494e678
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/bitfields.lldbinit
@@ -0,0 +1,5 @@
+settings set auto-one-line-summaries false
+
+target variable -T TheStruct
+
+target modules dump ast
diff --git a/lit/SymbolFile/NativePDB/Inputs/break-by-function.lldbinit b/lit/SymbolFile/NativePDB/Inputs/break-by-function.lldbinit
new file mode 100644
index 000000000000..ff9bf21a8864
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/break-by-function.lldbinit
@@ -0,0 +1,6 @@
+break set -n main
+break set -n OvlGlobalFn
+break set -n StaticFn
+break set -n DoesntExist
+break list
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/break-by-line.lldbinit b/lit/SymbolFile/NativePDB/Inputs/break-by-line.lldbinit
new file mode 100644
index 000000000000..7daa53ba24e0
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/break-by-line.lldbinit
@@ -0,0 +1,3 @@
+break set -f break-by-line.cpp -l 14
+break list
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/disassembly.lldbinit b/lit/SymbolFile/NativePDB/Inputs/disassembly.lldbinit
new file mode 100644
index 000000000000..2b552a0b01dd
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/disassembly.lldbinit
@@ -0,0 +1,2 @@
+disassemble --flavor=intel -m -n main
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit b/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit
new file mode 100644
index 000000000000..fe29896b5f52
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/function-types-builtins.lldbinit
@@ -0,0 +1,70 @@
+command alias dv target variable
+
+dv aa
+dv ab
+dv ac
+dv ad
+dv ae
+dv af
+dv ag
+dv ah
+dv ai
+dv aj
+dv ak
+dv al
+dv am
+dv an
+dv ao
+dv aq
+dv ar
+dv as
+dv at
+dv au
+dv av
+dv aw
+dv ax
+dv ay
+dv az
+dv aaa
+dv aab
+dv aac
+dv aad
+dv ra
+dv rb
+dv rc
+dv rd
+dv re
+dv rf
+dv rg
+dv rh
+dv ri
+dv rj
+dv rk
+dv rl
+dv rm
+dv rn
+dv ro
+dv rq
+dv rr
+dv rs
+dv rt
+dv ru
+dv rv
+dv rw
+dv rx
+dv ry
+dv rz
+dv raa
+dv rab
+dv rac
+dv rad
+dv ref
+dv ref2
+dv ref3
+dv binp
+dv binr
+dv null
+dv rae
+dv aae
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit b/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit
new file mode 100644
index 000000000000..8664881b262a
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/function-types-calling-conv.lldbinit
@@ -0,0 +1,7 @@
+target variable sfn
+target variable ffn
+target variable tfn
+target variable cfn
+target variable vfn
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit b/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit
new file mode 100644
index 000000000000..c06c650e1c45
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/function-types-classes.lldbinit
@@ -0,0 +1,14 @@
+target variable a
+target variable b
+target variable c
+target variable d
+target variable e
+target variable f
+target variable g
+target variable h
+target variable i
+target variable incomplete
+
+target modules dump ast
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/globals-bss.lldbinit b/lit/SymbolFile/NativePDB/Inputs/globals-bss.lldbinit
new file mode 100644
index 000000000000..9bf066ee2af9
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/globals-bss.lldbinit
@@ -0,0 +1,3 @@
+target variable GlobalVariable
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit b/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit
new file mode 100644
index 000000000000..cafb863d85fe
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/globals-classes.lldbinit
@@ -0,0 +1,16 @@
+settings set auto-one-line-summaries false
+
+target variable -T ClassWithPaddingInstance
+target variable -T ClassNoPaddingInstance
+target variable -T DC
+target variable -T EBOC
+target variable -T PBC
+
+target variable -T UnnamedClassInstance
+
+target variable -T PointersInstance
+target variable -T ReferencesInstance
+
+target modules dump ast
+
+quit \ No newline at end of file
diff --git a/lit/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit b/lit/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit
new file mode 100644
index 000000000000..4af8b658742b
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/globals-fundamental.lldbinit
@@ -0,0 +1,222 @@
+target variable BFalse
+target variable BTrue
+target variable CA
+target variable CZ
+target variable SCa
+target variable SCz
+target variable UC24
+target variable UC42
+target variable C16_24
+target variable C32_42
+target variable WC1
+target variable WCP
+target variable SMax
+target variable SMin
+target variable USMax
+target variable USMin
+target variable IMax
+target variable IMin
+target variable UIMax
+target variable UIMin
+target variable LMax
+target variable LMin
+target variable ULMax
+target variable ULMin
+target variable LLMax
+target variable LLMin
+target variable ULLMax
+target variable ULLMin
+target variable F
+target variable D
+
+target variable CBFalse
+target variable CBTrue
+target variable CCA
+target variable CCZ
+target variable CSCa
+target variable CSCz
+target variable CUC24
+target variable CUC42
+target variable CC16_24
+target variable CC32_42
+target variable CWC1
+target variable CWCP
+target variable CSMax
+target variable CSMin
+target variable CUSMax
+target variable CUSMin
+target variable CIMax
+target variable CIMin
+target variable CUIMax
+target variable CUIMin
+target variable CLMax
+target variable CLMin
+target variable CULMax
+target variable CULMin
+target variable CLLMax
+target variable CLLMin
+target variable CULLMax
+target variable CULLMin
+target variable CF
+target variable CD
+
+target variable ConstexprBFalse
+target variable ConstexprBTrue
+target variable ConstexprCA
+target variable ConstexprCZ
+target variable ConstexprSCa
+target variable ConstexprSCz
+target variable ConstexprUC24
+target variable ConstexprUC42
+target variable ConstexprC16_24
+target variable ConstexprC32_42
+target variable ConstexprWC1
+target variable ConstexprWCP
+target variable ConstexprSMax
+target variable ConstexprSMin
+target variable ConstexprUSMax
+target variable ConstexprUSMin
+target variable ConstexprIMax
+target variable ConstexprIMin
+target variable ConstexprUIMax
+target variable ConstexprUIMin
+target variable ConstexprLMax
+target variable ConstexprLMin
+target variable ConstexprULMax
+target variable ConstexprULMin
+target variable ConstexprLLMax
+target variable ConstexprLLMin
+target variable ConstexprULLMax
+target variable ConstexprULLMin
+target variable ConstexprF
+target variable ConstexprD
+
+target variable PBFalse
+target variable PBTrue
+target variable PCA
+target variable PCZ
+target variable PSCa
+target variable PSCz
+target variable PUC24
+target variable PUC42
+target variable PC16_24
+target variable PC32_42
+target variable PWC1
+target variable PWCP
+target variable PSMax
+target variable PSMin
+target variable PUSMax
+target variable PUSMin
+target variable PIMax
+target variable PIMin
+target variable PUIMax
+target variable PUIMin
+target variable PLMax
+target variable PLMin
+target variable PULMax
+target variable PULMin
+target variable PLLMax
+target variable PLLMin
+target variable PULLMax
+target variable PULLMin
+target variable PF
+target variable PD
+
+target variable CPBFalse
+target variable CPBTrue
+target variable CPCA
+target variable CPCZ
+target variable CPSCa
+target variable CPSCz
+target variable CPUC24
+target variable CPUC42
+target variable CPC16_24
+target variable CPC32_42
+target variable CPWC1
+target variable CPWCP
+target variable CPSMax
+target variable CPSMin
+target variable CPUSMax
+target variable CPUSMin
+target variable CPIMax
+target variable CPIMin
+target variable CPUIMax
+target variable CPUIMin
+target variable CPLMax
+target variable CPLMin
+target variable CPULMax
+target variable CPULMin
+target variable CPLLMax
+target variable CPLLMin
+target variable CPULLMax
+target variable CPULLMin
+target variable CPF
+target variable CPD
+
+target variable RBFalse
+target variable RBTrue
+target variable RCA
+target variable RCZ
+target variable RSCa
+target variable RSCz
+target variable RUC24
+target variable RUC42
+target variable RSMax
+target variable RSMin
+target variable RUSMax
+target variable RUSMin
+target variable RIMax
+target variable RIMin
+target variable RUIMax
+target variable RUIMin
+target variable RLMax
+target variable RLMin
+target variable RULMax
+target variable RULMin
+target variable RLLMax
+target variable RLLMin
+target variable RULLMax
+target variable RULLMin
+target variable RF
+target variable RD
+
+target variable CRBFalse
+target variable CRBTrue
+target variable CRCA
+target variable CRCZ
+target variable CRSCa
+target variable CRSCz
+target variable CRUC24
+target variable CRUC42
+target variable CRSMax
+target variable CRSMin
+target variable CRUSMax
+target variable CRUSMin
+target variable CRIMax
+target variable CRIMin
+target variable CRUIMax
+target variable CRUIMin
+target variable CRLMax
+target variable CRLMin
+target variable CRULMax
+target variable CRULMin
+target variable CRLLMax
+target variable CRLLMin
+target variable CRULLMax
+target variable CRULLMin
+target variable CRF
+target variable CRD
+
+target variable RC16_24
+target variable RC32_42
+target variable RWC1
+target variable RWCP
+target variable CRC16_24
+target variable CRC32_42
+target variable CRWC1
+target variable CRWCP
+
+target modules dump ast
+
+
+quit \ No newline at end of file
diff --git a/lit/SymbolFile/NativePDB/Inputs/local-variables.lldbinit b/lit/SymbolFile/NativePDB/Inputs/local-variables.lldbinit
new file mode 100644
index 000000000000..0d7371e86f1c
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/local-variables.lldbinit
@@ -0,0 +1,32 @@
+break set -n main
+run a b c d e f g
+p argc
+step
+p SomeLocal
+step
+p Param1
+p Param2
+step
+p Param1
+p Param2
+p Local1
+step
+p Param1
+p Param2
+p Local1
+p Local2
+step
+p Param1
+p Param2
+p Local1
+p Local2
+step
+p Param1
+p Param2
+p Local1
+p Local2
+continue
+
+target modules dump ast
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/nested-types.lldbinit b/lit/SymbolFile/NativePDB/Inputs/nested-types.lldbinit
new file mode 100644
index 000000000000..466df81fc421
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/nested-types.lldbinit
@@ -0,0 +1,13 @@
+settings set auto-one-line-summaries false
+
+target variable -T GlobalA
+target variable -T GlobalB
+target variable -T GlobalC
+target variable -T GlobalD
+target variable -T GlobalE
+target variable -T GlobalF
+target variable -T GlobalG
+target variable -T GlobalH
+target variable -T GlobalEnum
+
+target modules dump ast
diff --git a/lit/SymbolFile/NativePDB/Inputs/s_constant.lldbinit b/lit/SymbolFile/NativePDB/Inputs/s_constant.lldbinit
new file mode 100644
index 000000000000..1a50d808cdc2
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/s_constant.lldbinit
@@ -0,0 +1,25 @@
+target variable GlobalLUEA
+target variable GlobalLUEB
+target variable GlobalLUEC
+
+target variable GlobalLSEA
+target variable GlobalLSEB
+target variable GlobalLSEC
+
+target variable GlobalUEA
+target variable GlobalUEB
+target variable GlobalUEC
+
+target variable GlobalSEA
+target variable GlobalSEB
+target variable GlobalSEC
+
+target variable GlobalSUEA
+target variable GlobalSUEB
+target variable GlobalSUEC
+
+target variable GlobalSSEA
+target variable GlobalSSEB
+target variable GlobalSSEC
+
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/s_constant.s b/lit/SymbolFile/NativePDB/Inputs/s_constant.s
new file mode 100644
index 000000000000..553a5ce06dbf
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/s_constant.s
@@ -0,0 +1,971 @@
+ .text
+ .def @feat.00;
+ .scl 3;
+ .type 0;
+ .endef
+ .globl @feat.00
+.set @feat.00, 0
+ .intel_syntax noprefix
+ .def main;
+ .scl 2;
+ .type 32;
+ .endef
+ .globl main # -- Begin function main
+ .p2align 4, 0x90
+main: # @main
+.Lfunc_begin0:
+ .cv_func_id 0
+ .cv_file 1 "D:\\src\\llvm-mono\\lldb\\lit\\SymbolFile\\NativePDB\\s_constant.cpp" "7F1DA683A9B72A1360C1FDEDD7550E06" 1
+ .cv_loc 0 1 79 0 # D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp:79:0
+.seh_proc main
+# %bb.0: # %entry
+ sub rsp, 24
+ .seh_stackalloc 24
+ .seh_endprologue
+ xor eax, eax
+ mov dword ptr [rsp + 20], 0
+ mov qword ptr [rsp + 8], rdx
+ mov dword ptr [rsp + 4], ecx
+.Ltmp0:
+ .cv_loc 0 1 80 0 # D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp:80:0
+ add rsp, 24
+ ret
+.Ltmp1:
+.Lfunc_end0:
+ .seh_handlerdata
+ .text
+ .seh_endproc
+ # -- End function
+ .section .rdata,"dr"
+ .p2align 3 # @GlobalLUEA
+GlobalLUEA:
+ .quad 0 # 0x0
+
+ .p2align 3 # @GlobalLUEB
+GlobalLUEB:
+ .quad 1000 # 0x3e8
+
+ .p2align 3 # @GlobalLUEC
+GlobalLUEC:
+ .quad -16 # 0xfffffffffffffff0
+
+ .p2align 3 # @GlobalLSEA
+GlobalLSEA:
+ .quad 0 # 0x0
+
+ .p2align 3 # @GlobalLSEB
+GlobalLSEB:
+ .quad 9223372036854775000 # 0x7ffffffffffffcd8
+
+ .p2align 3 # @GlobalLSEC
+GlobalLSEC:
+ .quad -9223372036854775000 # 0x8000000000000328
+
+ .p2align 2 # @GlobalUEA
+GlobalUEA:
+ .long 0 # 0x0
+
+ .p2align 2 # @GlobalUEB
+GlobalUEB:
+ .long 1000 # 0x3e8
+
+ .p2align 2 # @GlobalUEC
+GlobalUEC:
+ .long 4294000000 # 0xfff13d80
+
+ .p2align 2 # @GlobalSEA
+GlobalSEA:
+ .long 0 # 0x0
+
+ .p2align 2 # @GlobalSEB
+GlobalSEB:
+ .long 2147000000 # 0x7ff89ec0
+
+ .p2align 2 # @GlobalSEC
+GlobalSEC:
+ .long 2147967296 # 0x80076140
+
+GlobalSUEA: # @GlobalSUEA
+ .byte 0 # 0x0
+
+GlobalSUEB: # @GlobalSUEB
+ .byte 100 # 0x64
+
+GlobalSUEC: # @GlobalSUEC
+ .byte 200 # 0xc8
+
+GlobalSSEA: # @GlobalSSEA
+ .byte 0 # 0x0
+
+GlobalSSEB: # @GlobalSSEB
+ .byte 100 # 0x64
+
+GlobalSSEC: # @GlobalSSEC
+ .byte 156 # 0x9c
+
+ .section .drectve,"yn"
+ .ascii " /DEFAULTLIB:libcmt.lib"
+ .ascii " /DEFAULTLIB:oldnames.lib"
+ .section .debug$S,"dr"
+ .p2align 2
+ .long 4 # Debug section magic
+ .long 241
+ .long .Ltmp3-.Ltmp2 # Subsection size
+.Ltmp2:
+ .short .Ltmp5-.Ltmp4 # Record length
+.Ltmp4:
+ .short 4412 # Record kind: S_COMPILE3
+ .long 1 # Flags and language
+ .short 208 # CPUType
+ .short 8 # Frontend version
+ .short 0
+ .short 0
+ .short 0
+ .short 8000 # Backend version
+ .short 0
+ .short 0
+ .short 0
+ .asciz "clang version 8.0.0 " # Null-terminated compiler version string
+.Ltmp5:
+.Ltmp3:
+ .p2align 2
+ .long 241 # Symbol subsection for main
+ .long .Ltmp7-.Ltmp6 # Subsection size
+.Ltmp6:
+ .short .Ltmp9-.Ltmp8 # Record length
+.Ltmp8:
+ .short 4423 # Record kind: S_GPROC32_ID
+ .long 0 # PtrParent
+ .long 0 # PtrEnd
+ .long 0 # PtrNext
+ .long .Lfunc_end0-main # Code size
+ .long 0 # Offset after prologue
+ .long 0 # Offset before epilogue
+ .long 4099 # Function type index
+ .secrel32 main # Function section relative address
+ .secidx main # Function section index
+ .byte 0 # Flags
+ .asciz "main" # Function name
+.Ltmp9:
+ .short .Ltmp11-.Ltmp10 # Record length
+.Ltmp10:
+ .short 4114 # Record kind: S_FRAMEPROC
+ .long 24 # FrameSize
+ .long 0 # Padding
+ .long 0 # Offset of padding
+ .long 0 # Bytes of callee saved registers
+ .long 0 # Exception handler offset
+ .short 0 # Exception handler section
+ .long 81920 # Flags (defines frame register)
+.Ltmp11:
+ .short .Ltmp13-.Ltmp12 # Record length
+.Ltmp12:
+ .short 4414 # Record kind: S_LOCAL
+ .long 116 # TypeIndex
+ .short 1 # Flags
+ .asciz "argc"
+.Ltmp13:
+ .cv_def_range .Ltmp0 .Ltmp1, "B\021\004\000\000\000"
+ .short .Ltmp15-.Ltmp14 # Record length
+.Ltmp14:
+ .short 4414 # Record kind: S_LOCAL
+ .long 4096 # TypeIndex
+ .short 1 # Flags
+ .asciz "argv"
+.Ltmp15:
+ .cv_def_range .Ltmp0 .Ltmp1, "B\021\b\000\000\000"
+ .short 2 # Record length
+ .short 4431 # Record kind: S_PROC_ID_END
+.Ltmp7:
+ .p2align 2
+ .cv_linetable 0, main, .Lfunc_end0
+ .long 241 # Symbol subsection for globals
+ .long .Ltmp17-.Ltmp16 # Subsection size
+.Ltmp16:
+ .short .Ltmp19-.Ltmp18 # Record length
+.Ltmp18:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4104 # Type
+ .short 0 # Value
+ .asciz "GlobalLUEA" # Name
+.Ltmp19:
+ .short .Ltmp21-.Ltmp20 # Record length
+.Ltmp20:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4104 # Type
+ .short 1000 # Value
+ .asciz "GlobalLUEB" # Name
+.Ltmp21:
+ .short .Ltmp23-.Ltmp22 # Record length
+.Ltmp22:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4104 # Type
+ .byte 0x00, 0x80, 0xf0 # Value
+ .asciz "GlobalLUEC" # Name
+.Ltmp23:
+ .short .Ltmp25-.Ltmp24 # Record length
+.Ltmp24:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4108 # Type
+ .byte 0x00, 0x00 # Value
+ .asciz "GlobalLSEA" # Name
+.Ltmp25:
+ .short .Ltmp27-.Ltmp26 # Record length
+.Ltmp26:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4108 # Type
+ .byte 0x0A, 0x80, 0xD8, 0xFC # Value
+ .byte 0xFF, 0xFF, 0xFF, 0xFF
+ .byte 0xFF, 0x7F
+ .asciz "GlobalLSEB" # Name
+.Ltmp27:
+ .short .Ltmp29-.Ltmp28 # Record length
+.Ltmp28:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4108 # Type
+ .byte 0x09, 0x80, 0x28, 0x03 # Value
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x80
+ .asciz "GlobalLSEC" # Name
+.Ltmp29:
+ .short .Ltmp31-.Ltmp30 # Record length
+.Ltmp30:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4112 # Type
+ .byte 0x00, 0x00 # Value
+ .asciz "GlobalUEA" # Name
+.Ltmp31:
+ .short .Ltmp33-.Ltmp32 # Record length
+.Ltmp32:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4112 # Type
+ .byte 0xe8, 0x03 # Value
+ .asciz "GlobalUEB" # Name
+.Ltmp33:
+ .short .Ltmp35-.Ltmp34 # Record length
+.Ltmp34:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4112 # Type
+ .byte 0x04, 0x80, 0x80, 0x3d # Value
+ .byte 0xf1, 0xff
+ .asciz "GlobalUEC" # Name
+.Ltmp35:
+ .short .Ltmp37-.Ltmp36 # Record length
+.Ltmp36:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4116 # Type
+ .byte 0x00, 0x00 # Value
+ .asciz "GlobalSEA" # Name
+.Ltmp37:
+ .short .Ltmp39-.Ltmp38 # Record length
+.Ltmp38:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4116 # Type
+ .byte 0x04, 0x80, 0xc0, 0x9e # Value
+ .byte 0xf8, 0x7f
+ .asciz "GlobalSEB" # Name
+.Ltmp39:
+ .short .Ltmp41-.Ltmp40 # Record length
+.Ltmp40:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4116 # Type
+ .byte 0x03, 0x80, 0x40, 0x61 # Value
+ .byte 0x07, 0x80
+ .asciz "GlobalSEC" # Name
+.Ltmp41:
+ .short .Ltmp43-.Ltmp42 # Record length
+.Ltmp42:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4120 # Type
+ .byte 0x00, 0x00 # Value
+ .asciz "GlobalSUEA" # Name
+.Ltmp43:
+ .short .Ltmp45-.Ltmp44 # Record length
+.Ltmp44:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4120 # Type
+ .byte 0x64, 0x00 # Value
+ .asciz "GlobalSUEB" # Name
+.Ltmp45:
+ .short .Ltmp47-.Ltmp46 # Record length
+.Ltmp46:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4120 # Type
+ .byte 0xc8, 0x00 # Value
+ .asciz "GlobalSUEC" # Name
+.Ltmp47:
+ .short .Ltmp49-.Ltmp48 # Record length
+.Ltmp48:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4124 # Type
+ .byte 0x00, 0x00 # Value
+ .asciz "GlobalSSEA" # Name
+.Ltmp49:
+ .short .Ltmp51-.Ltmp50 # Record length
+.Ltmp50:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4124 # Type
+ .byte 0x64, 0x00 # Value
+ .asciz "GlobalSSEB" # Name
+.Ltmp51:
+ .short .Ltmp53-.Ltmp52 # Record length
+.Ltmp52:
+ .short 4359 # Record kind: S_CONSTANT
+ .long 4124 # Type
+ .byte 0x00, 0x80, 0x9c # Value
+ .asciz "GlobalSSEC" # Name
+.Ltmp53:
+.Ltmp17:
+ .p2align 2
+ .cv_filechecksums # File index to string table offset subsection
+ .cv_stringtable # String table
+ .long 241
+ .long .Ltmp55-.Ltmp54 # Subsection size
+.Ltmp54:
+ .short 6 # Record length
+ .short 4428 # Record kind: S_BUILDINFO
+ .long 4127 # LF_BUILDINFO index
+.Ltmp55:
+ .p2align 2
+ .section .debug$T,"dr"
+ .p2align 2
+ .long 4 # Debug section magic
+ # Pointer (0x1000) {
+ # TypeLeafKind: LF_POINTER (0x1002)
+ # PointeeType: char* (0x670)
+ # PointerAttributes: 0x1000C
+ # PtrType: Near64 (0xC)
+ # PtrMode: Pointer (0x0)
+ # IsFlat: 0
+ # IsConst: 0
+ # IsVolatile: 0
+ # IsUnaligned: 0
+ # IsRestrict: 0
+ # SizeOf: 8
+ # }
+ .byte 0x0a, 0x00, 0x02, 0x10
+ .byte 0x70, 0x06, 0x00, 0x00
+ .byte 0x0c, 0x00, 0x01, 0x00
+ # ArgList (0x1001) {
+ # TypeLeafKind: LF_ARGLIST (0x1201)
+ # NumArgs: 2
+ # Arguments [
+ # ArgType: int (0x74)
+ # ArgType: char** (0x1000)
+ # ]
+ # }
+ .byte 0x0e, 0x00, 0x01, 0x12
+ .byte 0x02, 0x00, 0x00, 0x00
+ .byte 0x74, 0x00, 0x00, 0x00
+ .byte 0x00, 0x10, 0x00, 0x00
+ # Procedure (0x1002) {
+ # TypeLeafKind: LF_PROCEDURE (0x1008)
+ # ReturnType: int (0x74)
+ # CallingConvention: NearC (0x0)
+ # FunctionOptions [ (0x0)
+ # ]
+ # NumParameters: 2
+ # ArgListType: (int, char**) (0x1001)
+ # }
+ .byte 0x0e, 0x00, 0x08, 0x10
+ .byte 0x74, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x02, 0x00
+ .byte 0x01, 0x10, 0x00, 0x00
+ # FuncId (0x1003) {
+ # TypeLeafKind: LF_FUNC_ID (0x1601)
+ # ParentScope: 0x0
+ # FunctionType: int (int, char**) (0x1002)
+ # Name: main
+ # }
+ .byte 0x12, 0x00, 0x01, 0x16
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x02, 0x10, 0x00, 0x00
+ .byte 0x6d, 0x61, 0x69, 0x6e
+ .byte 0x00, 0xf3, 0xf2, 0xf1
+ # FieldList (0x1004) {
+ # TypeLeafKind: LF_FIELDLIST (0x1203)
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 0
+ # Name: LUE_A
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 1000
+ # Name: LUE_B
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 18446744073709551600
+ # Name: LUE_C
+ # }
+ # }
+ .byte 0x2e, 0x00, 0x03, 0x12
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x00, 0x00, 0x4c, 0x55
+ .byte 0x45, 0x5f, 0x41, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0xe8, 0x03, 0x4c, 0x55
+ .byte 0x45, 0x5f, 0x42, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x0a, 0x80, 0xf0, 0xff
+ .byte 0xff, 0xff, 0xff, 0xff
+ .byte 0xff, 0xff, 0x4c, 0x55
+ .byte 0x45, 0x5f, 0x43, 0x00
+ # Enum (0x1005) {
+ # TypeLeafKind: LF_ENUM (0x1507)
+ # NumEnumerators: 3
+ # Properties [ (0x200)
+ # HasUniqueName (0x200)
+ # ]
+ # UnderlyingType: unsigned __int64 (0x23)
+ # FieldListType: <field list> (0x1004)
+ # Name: A::B::C::LargeUnsignedEnum
+ # LinkageName: .?AW4LargeUnsignedEnum@C@B@A@@
+ # }
+ .byte 0x4a, 0x00, 0x07, 0x15
+ .byte 0x03, 0x00, 0x00, 0x02
+ .byte 0x23, 0x00, 0x00, 0x00
+ .byte 0x04, 0x10, 0x00, 0x00
+ .byte 0x41, 0x3a, 0x3a, 0x42
+ .byte 0x3a, 0x3a, 0x43, 0x3a
+ .byte 0x3a, 0x4c, 0x61, 0x72
+ .byte 0x67, 0x65, 0x55, 0x6e
+ .byte 0x73, 0x69, 0x67, 0x6e
+ .byte 0x65, 0x64, 0x45, 0x6e
+ .byte 0x75, 0x6d, 0x00, 0x2e
+ .byte 0x3f, 0x41, 0x57, 0x34
+ .byte 0x4c, 0x61, 0x72, 0x67
+ .byte 0x65, 0x55, 0x6e, 0x73
+ .byte 0x69, 0x67, 0x6e, 0x65
+ .byte 0x64, 0x45, 0x6e, 0x75
+ .byte 0x6d, 0x40, 0x43, 0x40
+ .byte 0x42, 0x40, 0x41, 0x40
+ .byte 0x40, 0x00, 0xf2, 0xf1
+ # StringId (0x1006) {
+ # TypeLeafKind: LF_STRING_ID (0x1605)
+ # Id: 0x0
+ # StringData: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp
+ # }
+ .byte 0x46, 0x00, 0x05, 0x16
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x44, 0x3a, 0x5c, 0x73
+ .byte 0x72, 0x63, 0x5c, 0x6c
+ .byte 0x6c, 0x76, 0x6d, 0x2d
+ .byte 0x6d, 0x6f, 0x6e, 0x6f
+ .byte 0x5c, 0x6c, 0x6c, 0x64
+ .byte 0x62, 0x5c, 0x6c, 0x69
+ .byte 0x74, 0x5c, 0x53, 0x79
+ .byte 0x6d, 0x62, 0x6f, 0x6c
+ .byte 0x46, 0x69, 0x6c, 0x65
+ .byte 0x5c, 0x4e, 0x61, 0x74
+ .byte 0x69, 0x76, 0x65, 0x50
+ .byte 0x44, 0x42, 0x5c, 0x73
+ .byte 0x5f, 0x63, 0x6f, 0x6e
+ .byte 0x73, 0x74, 0x61, 0x6e
+ .byte 0x74, 0x2e, 0x63, 0x70
+ .byte 0x70, 0x00, 0xf2, 0xf1
+ # UdtSourceLine (0x1007) {
+ # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+ # UDT: A::B::C::LargeUnsignedEnum (0x1005)
+ # SourceFile: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp (0x1006)
+ # LineNumber: 14
+ # }
+ .byte 0x0e, 0x00, 0x06, 0x16
+ .byte 0x05, 0x10, 0x00, 0x00
+ .byte 0x06, 0x10, 0x00, 0x00
+ .byte 0x0e, 0x00, 0x00, 0x00
+ # Modifier (0x1008) {
+ # TypeLeafKind: LF_MODIFIER (0x1001)
+ # ModifiedType: A::B::C::LargeUnsignedEnum (0x1005)
+ # Modifiers [ (0x1)
+ # Const (0x1)
+ # ]
+ # }
+ .byte 0x0a, 0x00, 0x01, 0x10
+ .byte 0x05, 0x10, 0x00, 0x00
+ .byte 0x01, 0x00, 0xf2, 0xf1
+ # FieldList (0x1009) {
+ # TypeLeafKind: LF_FIELDLIST (0x1203)
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 0
+ # Name: LSE_A
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 9223372036854775000
+ # Name: LSE_B
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 9223372036854776616
+ # Name: LSE_C
+ # }
+ # }
+ .byte 0x36, 0x00, 0x03, 0x12
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x00, 0x00, 0x4c, 0x53
+ .byte 0x45, 0x5f, 0x41, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x0a, 0x80, 0xd8, 0xfc
+ .byte 0xff, 0xff, 0xff, 0xff
+ .byte 0xff, 0x7f, 0x4c, 0x53
+ .byte 0x45, 0x5f, 0x42, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x0a, 0x80, 0x28, 0x03
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x80, 0x4c, 0x53
+ .byte 0x45, 0x5f, 0x43, 0x00
+ # Enum (0x100A) {
+ # TypeLeafKind: LF_ENUM (0x1507)
+ # NumEnumerators: 3
+ # Properties [ (0x200)
+ # HasUniqueName (0x200)
+ # ]
+ # UnderlyingType: __int64 (0x13)
+ # FieldListType: <field list> (0x1009)
+ # Name: A::B::C::LargeSignedEnum
+ # LinkageName: .?AW4LargeSignedEnum@C@B@A@@
+ # }
+ .byte 0x46, 0x00, 0x07, 0x15
+ .byte 0x03, 0x00, 0x00, 0x02
+ .byte 0x13, 0x00, 0x00, 0x00
+ .byte 0x09, 0x10, 0x00, 0x00
+ .byte 0x41, 0x3a, 0x3a, 0x42
+ .byte 0x3a, 0x3a, 0x43, 0x3a
+ .byte 0x3a, 0x4c, 0x61, 0x72
+ .byte 0x67, 0x65, 0x53, 0x69
+ .byte 0x67, 0x6e, 0x65, 0x64
+ .byte 0x45, 0x6e, 0x75, 0x6d
+ .byte 0x00, 0x2e, 0x3f, 0x41
+ .byte 0x57, 0x34, 0x4c, 0x61
+ .byte 0x72, 0x67, 0x65, 0x53
+ .byte 0x69, 0x67, 0x6e, 0x65
+ .byte 0x64, 0x45, 0x6e, 0x75
+ .byte 0x6d, 0x40, 0x43, 0x40
+ .byte 0x42, 0x40, 0x41, 0x40
+ .byte 0x40, 0x00, 0xf2, 0xf1
+ # UdtSourceLine (0x100B) {
+ # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+ # UDT: A::B::C::LargeSignedEnum (0x100A)
+ # SourceFile: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp (0x1006)
+ # LineNumber: 20
+ # }
+ .byte 0x0e, 0x00, 0x06, 0x16
+ .byte 0x0a, 0x10, 0x00, 0x00
+ .byte 0x06, 0x10, 0x00, 0x00
+ .byte 0x14, 0x00, 0x00, 0x00
+ # Modifier (0x100C) {
+ # TypeLeafKind: LF_MODIFIER (0x1001)
+ # ModifiedType: A::B::C::LargeSignedEnum (0x100A)
+ # Modifiers [ (0x1)
+ # Const (0x1)
+ # ]
+ # }
+ .byte 0x0a, 0x00, 0x01, 0x10
+ .byte 0x0a, 0x10, 0x00, 0x00
+ .byte 0x01, 0x00, 0xf2, 0xf1
+ # FieldList (0x100D) {
+ # TypeLeafKind: LF_FIELDLIST (0x1203)
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 0
+ # Name: UE_A
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 1000
+ # Name: UE_B
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 4294000000
+ # Name: UE_C
+ # }
+ # }
+ .byte 0x2a, 0x00, 0x03, 0x12
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x00, 0x00, 0x55, 0x45
+ .byte 0x5f, 0x41, 0x00, 0xf1
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0xe8, 0x03, 0x55, 0x45
+ .byte 0x5f, 0x42, 0x00, 0xf1
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x04, 0x80, 0x80, 0x3d
+ .byte 0xf1, 0xff, 0x55, 0x45
+ .byte 0x5f, 0x43, 0x00, 0xf1
+ # Enum (0x100E) {
+ # TypeLeafKind: LF_ENUM (0x1507)
+ # NumEnumerators: 3
+ # Properties [ (0x200)
+ # HasUniqueName (0x200)
+ # ]
+ # UnderlyingType: unsigned (0x75)
+ # FieldListType: <field list> (0x100D)
+ # Name: A::B::C::UnsignedEnum
+ # LinkageName: .?AW4UnsignedEnum@C@B@A@@
+ # }
+ .byte 0x3e, 0x00, 0x07, 0x15
+ .byte 0x03, 0x00, 0x00, 0x02
+ .byte 0x75, 0x00, 0x00, 0x00
+ .byte 0x0d, 0x10, 0x00, 0x00
+ .byte 0x41, 0x3a, 0x3a, 0x42
+ .byte 0x3a, 0x3a, 0x43, 0x3a
+ .byte 0x3a, 0x55, 0x6e, 0x73
+ .byte 0x69, 0x67, 0x6e, 0x65
+ .byte 0x64, 0x45, 0x6e, 0x75
+ .byte 0x6d, 0x00, 0x2e, 0x3f
+ .byte 0x41, 0x57, 0x34, 0x55
+ .byte 0x6e, 0x73, 0x69, 0x67
+ .byte 0x6e, 0x65, 0x64, 0x45
+ .byte 0x6e, 0x75, 0x6d, 0x40
+ .byte 0x43, 0x40, 0x42, 0x40
+ .byte 0x41, 0x40, 0x40, 0x00
+ # UdtSourceLine (0x100F) {
+ # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+ # UDT: A::B::C::UnsignedEnum (0x100E)
+ # SourceFile: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp (0x1006)
+ # LineNumber: 26
+ # }
+ .byte 0x0e, 0x00, 0x06, 0x16
+ .byte 0x0e, 0x10, 0x00, 0x00
+ .byte 0x06, 0x10, 0x00, 0x00
+ .byte 0x1a, 0x00, 0x00, 0x00
+ # Modifier (0x1010) {
+ # TypeLeafKind: LF_MODIFIER (0x1001)
+ # ModifiedType: A::B::C::UnsignedEnum (0x100E)
+ # Modifiers [ (0x1)
+ # Const (0x1)
+ # ]
+ # }
+ .byte 0x0a, 0x00, 0x01, 0x10
+ .byte 0x0e, 0x10, 0x00, 0x00
+ .byte 0x01, 0x00, 0xf2, 0xf1
+ # FieldList (0x1011) {
+ # TypeLeafKind: LF_FIELDLIST (0x1203)
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 0
+ # Name: SE_A
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 2147000000
+ # Name: SE_B
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 18446744071562551616
+ # Name: SE_C
+ # }
+ # }
+ .byte 0x32, 0x00, 0x03, 0x12
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x00, 0x00, 0x53, 0x45
+ .byte 0x5f, 0x41, 0x00, 0xf1
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x04, 0x80, 0xc0, 0x9e
+ .byte 0xf8, 0x7f, 0x53, 0x45
+ .byte 0x5f, 0x42, 0x00, 0xf1
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x0a, 0x80, 0x40, 0x61
+ .byte 0x07, 0x80, 0xff, 0xff
+ .byte 0xff, 0xff, 0x53, 0x45
+ .byte 0x5f, 0x43, 0x00, 0xf1
+ # Enum (0x1012) {
+ # TypeLeafKind: LF_ENUM (0x1507)
+ # NumEnumerators: 3
+ # Properties [ (0x200)
+ # HasUniqueName (0x200)
+ # ]
+ # UnderlyingType: int (0x74)
+ # FieldListType: <field list> (0x1011)
+ # Name: A::B::C::SignedEnum
+ # LinkageName: .?AW4SignedEnum@C@B@A@@
+ # }
+ .byte 0x3a, 0x00, 0x07, 0x15
+ .byte 0x03, 0x00, 0x00, 0x02
+ .byte 0x74, 0x00, 0x00, 0x00
+ .byte 0x11, 0x10, 0x00, 0x00
+ .byte 0x41, 0x3a, 0x3a, 0x42
+ .byte 0x3a, 0x3a, 0x43, 0x3a
+ .byte 0x3a, 0x53, 0x69, 0x67
+ .byte 0x6e, 0x65, 0x64, 0x45
+ .byte 0x6e, 0x75, 0x6d, 0x00
+ .byte 0x2e, 0x3f, 0x41, 0x57
+ .byte 0x34, 0x53, 0x69, 0x67
+ .byte 0x6e, 0x65, 0x64, 0x45
+ .byte 0x6e, 0x75, 0x6d, 0x40
+ .byte 0x43, 0x40, 0x42, 0x40
+ .byte 0x41, 0x40, 0x40, 0x00
+ # UdtSourceLine (0x1013) {
+ # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+ # UDT: A::B::C::SignedEnum (0x1012)
+ # SourceFile: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp (0x1006)
+ # LineNumber: 32
+ # }
+ .byte 0x0e, 0x00, 0x06, 0x16
+ .byte 0x12, 0x10, 0x00, 0x00
+ .byte 0x06, 0x10, 0x00, 0x00
+ .byte 0x20, 0x00, 0x00, 0x00
+ # Modifier (0x1014) {
+ # TypeLeafKind: LF_MODIFIER (0x1001)
+ # ModifiedType: A::B::C::SignedEnum (0x1012)
+ # Modifiers [ (0x1)
+ # Const (0x1)
+ # ]
+ # }
+ .byte 0x0a, 0x00, 0x01, 0x10
+ .byte 0x12, 0x10, 0x00, 0x00
+ .byte 0x01, 0x00, 0xf2, 0xf1
+ # FieldList (0x1015) {
+ # TypeLeafKind: LF_FIELDLIST (0x1203)
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 0
+ # Name: SUE_A
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 100
+ # Name: SUE_B
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 200
+ # Name: SUE_C
+ # }
+ # }
+ .byte 0x26, 0x00, 0x03, 0x12
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x00, 0x00, 0x53, 0x55
+ .byte 0x45, 0x5f, 0x41, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x64, 0x00, 0x53, 0x55
+ .byte 0x45, 0x5f, 0x42, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0xc8, 0x00, 0x53, 0x55
+ .byte 0x45, 0x5f, 0x43, 0x00
+ # Enum (0x1016) {
+ # TypeLeafKind: LF_ENUM (0x1507)
+ # NumEnumerators: 3
+ # Properties [ (0x200)
+ # HasUniqueName (0x200)
+ # ]
+ # UnderlyingType: unsigned char (0x20)
+ # FieldListType: <field list> (0x1015)
+ # Name: A::B::C::SmallUnsignedEnum
+ # LinkageName: .?AW4SmallUnsignedEnum@C@B@A@@
+ # }
+ .byte 0x4a, 0x00, 0x07, 0x15
+ .byte 0x03, 0x00, 0x00, 0x02
+ .byte 0x20, 0x00, 0x00, 0x00
+ .byte 0x15, 0x10, 0x00, 0x00
+ .byte 0x41, 0x3a, 0x3a, 0x42
+ .byte 0x3a, 0x3a, 0x43, 0x3a
+ .byte 0x3a, 0x53, 0x6d, 0x61
+ .byte 0x6c, 0x6c, 0x55, 0x6e
+ .byte 0x73, 0x69, 0x67, 0x6e
+ .byte 0x65, 0x64, 0x45, 0x6e
+ .byte 0x75, 0x6d, 0x00, 0x2e
+ .byte 0x3f, 0x41, 0x57, 0x34
+ .byte 0x53, 0x6d, 0x61, 0x6c
+ .byte 0x6c, 0x55, 0x6e, 0x73
+ .byte 0x69, 0x67, 0x6e, 0x65
+ .byte 0x64, 0x45, 0x6e, 0x75
+ .byte 0x6d, 0x40, 0x43, 0x40
+ .byte 0x42, 0x40, 0x41, 0x40
+ .byte 0x40, 0x00, 0xf2, 0xf1
+ # UdtSourceLine (0x1017) {
+ # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+ # UDT: A::B::C::SmallUnsignedEnum (0x1016)
+ # SourceFile: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp (0x1006)
+ # LineNumber: 38
+ # }
+ .byte 0x0e, 0x00, 0x06, 0x16
+ .byte 0x16, 0x10, 0x00, 0x00
+ .byte 0x06, 0x10, 0x00, 0x00
+ .byte 0x26, 0x00, 0x00, 0x00
+ # Modifier (0x1018) {
+ # TypeLeafKind: LF_MODIFIER (0x1001)
+ # ModifiedType: A::B::C::SmallUnsignedEnum (0x1016)
+ # Modifiers [ (0x1)
+ # Const (0x1)
+ # ]
+ # }
+ .byte 0x0a, 0x00, 0x01, 0x10
+ .byte 0x16, 0x10, 0x00, 0x00
+ .byte 0x01, 0x00, 0xf2, 0xf1
+ # FieldList (0x1019) {
+ # TypeLeafKind: LF_FIELDLIST (0x1203)
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 0
+ # Name: SSE_A
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 100
+ # Name: SSE_B
+ # }
+ # Enumerator {
+ # TypeLeafKind: LF_ENUMERATE (0x1502)
+ # AccessSpecifier: Public (0x3)
+ # EnumValue: 18446744073709551516
+ # Name: SSE_C
+ # }
+ # }
+ .byte 0x2e, 0x00, 0x03, 0x12
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x00, 0x00, 0x53, 0x53
+ .byte 0x45, 0x5f, 0x41, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x64, 0x00, 0x53, 0x53
+ .byte 0x45, 0x5f, 0x42, 0x00
+ .byte 0x02, 0x15, 0x03, 0x00
+ .byte 0x0a, 0x80, 0x9c, 0xff
+ .byte 0xff, 0xff, 0xff, 0xff
+ .byte 0xff, 0xff, 0x53, 0x53
+ .byte 0x45, 0x5f, 0x43, 0x00
+ # Enum (0x101A) {
+ # TypeLeafKind: LF_ENUM (0x1507)
+ # NumEnumerators: 3
+ # Properties [ (0x200)
+ # HasUniqueName (0x200)
+ # ]
+ # UnderlyingType: char (0x70)
+ # FieldListType: <field list> (0x1019)
+ # Name: A::B::C::SmallSignedEnum
+ # LinkageName: .?AW4SmallSignedEnum@C@B@A@@
+ # }
+ .byte 0x46, 0x00, 0x07, 0x15
+ .byte 0x03, 0x00, 0x00, 0x02
+ .byte 0x70, 0x00, 0x00, 0x00
+ .byte 0x19, 0x10, 0x00, 0x00
+ .byte 0x41, 0x3a, 0x3a, 0x42
+ .byte 0x3a, 0x3a, 0x43, 0x3a
+ .byte 0x3a, 0x53, 0x6d, 0x61
+ .byte 0x6c, 0x6c, 0x53, 0x69
+ .byte 0x67, 0x6e, 0x65, 0x64
+ .byte 0x45, 0x6e, 0x75, 0x6d
+ .byte 0x00, 0x2e, 0x3f, 0x41
+ .byte 0x57, 0x34, 0x53, 0x6d
+ .byte 0x61, 0x6c, 0x6c, 0x53
+ .byte 0x69, 0x67, 0x6e, 0x65
+ .byte 0x64, 0x45, 0x6e, 0x75
+ .byte 0x6d, 0x40, 0x43, 0x40
+ .byte 0x42, 0x40, 0x41, 0x40
+ .byte 0x40, 0x00, 0xf2, 0xf1
+ # UdtSourceLine (0x101B) {
+ # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
+ # UDT: A::B::C::SmallSignedEnum (0x101A)
+ # SourceFile: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\s_constant.cpp (0x1006)
+ # LineNumber: 44
+ # }
+ .byte 0x0e, 0x00, 0x06, 0x16
+ .byte 0x1a, 0x10, 0x00, 0x00
+ .byte 0x06, 0x10, 0x00, 0x00
+ .byte 0x2c, 0x00, 0x00, 0x00
+ # Modifier (0x101C) {
+ # TypeLeafKind: LF_MODIFIER (0x1001)
+ # ModifiedType: A::B::C::SmallSignedEnum (0x101A)
+ # Modifiers [ (0x1)
+ # Const (0x1)
+ # ]
+ # }
+ .byte 0x0a, 0x00, 0x01, 0x10
+ .byte 0x1a, 0x10, 0x00, 0x00
+ .byte 0x01, 0x00, 0xf2, 0xf1
+ # StringId (0x101D) {
+ # TypeLeafKind: LF_STRING_ID (0x1605)
+ # Id: 0x0
+ # StringData: D:\\src\\llvmbuild\\ninja-x64
+ # }
+ .byte 0x26, 0x00, 0x05, 0x16
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x44, 0x3a, 0x5c, 0x5c
+ .byte 0x73, 0x72, 0x63, 0x5c
+ .byte 0x5c, 0x6c, 0x6c, 0x76
+ .byte 0x6d, 0x62, 0x75, 0x69
+ .byte 0x6c, 0x64, 0x5c, 0x5c
+ .byte 0x6e, 0x69, 0x6e, 0x6a
+ .byte 0x61, 0x2d, 0x78, 0x36
+ .byte 0x34, 0x00, 0xf2, 0xf1
+ # StringId (0x101E) {
+ # TypeLeafKind: LF_STRING_ID (0x1605)
+ # Id: 0x0
+ # StringData: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\variable.cpp
+ # }
+ .byte 0x42, 0x00, 0x05, 0x16
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x44, 0x3a, 0x5c, 0x73
+ .byte 0x72, 0x63, 0x5c, 0x6c
+ .byte 0x6c, 0x76, 0x6d, 0x2d
+ .byte 0x6d, 0x6f, 0x6e, 0x6f
+ .byte 0x5c, 0x6c, 0x6c, 0x64
+ .byte 0x62, 0x5c, 0x6c, 0x69
+ .byte 0x74, 0x5c, 0x53, 0x79
+ .byte 0x6d, 0x62, 0x6f, 0x6c
+ .byte 0x46, 0x69, 0x6c, 0x65
+ .byte 0x5c, 0x4e, 0x61, 0x74
+ .byte 0x69, 0x76, 0x65, 0x50
+ .byte 0x44, 0x42, 0x5c, 0x76
+ .byte 0x61, 0x72, 0x69, 0x61
+ .byte 0x62, 0x6c, 0x65, 0x2e
+ .byte 0x63, 0x70, 0x70, 0x00
+ # BuildInfo (0x101F) {
+ # TypeLeafKind: LF_BUILDINFO (0x1603)
+ # NumArgs: 5
+ # Arguments [
+ # ArgType: D:\\src\\llvmbuild\\ninja-x64 (0x101D)
+ # ArgType: 0x0
+ # ArgType: D:\src\llvm-mono\lldb\lit\SymbolFile\NativePDB\variable.cpp (0x101E)
+ # ArgType: 0x0
+ # ArgType: 0x0
+ # ]
+ # }
+ .byte 0x1a, 0x00, 0x03, 0x16
+ .byte 0x05, 0x00, 0x1d, 0x10
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x1e, 0x10
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0xf2, 0xf1
+
+ .addrsig
+ .addrsig_sym GlobalLUEA
+ .addrsig_sym GlobalLUEB
+ .addrsig_sym GlobalLUEC
+ .addrsig_sym GlobalLSEA
+ .addrsig_sym GlobalLSEB
+ .addrsig_sym GlobalLSEC
+ .addrsig_sym GlobalUEA
+ .addrsig_sym GlobalUEB
+ .addrsig_sym GlobalUEC
+ .addrsig_sym GlobalSEA
+ .addrsig_sym GlobalSEB
+ .addrsig_sym GlobalSEC
+ .addrsig_sym GlobalSUEA
+ .addrsig_sym GlobalSUEB
+ .addrsig_sym GlobalSUEC
+ .addrsig_sym GlobalSSEA
+ .addrsig_sym GlobalSSEB
+ .addrsig_sym GlobalSSEC
diff --git a/lit/SymbolFile/NativePDB/Inputs/source-list.lldbinit b/lit/SymbolFile/NativePDB/Inputs/source-list.lldbinit
new file mode 100644
index 000000000000..624ce5ba156b
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/source-list.lldbinit
@@ -0,0 +1,3 @@
+source list -n main
+source list -n OvlGlobalFn
+quit
diff --git a/lit/SymbolFile/NativePDB/Inputs/tag-types.lldbinit b/lit/SymbolFile/NativePDB/Inputs/tag-types.lldbinit
new file mode 100644
index 000000000000..c50e18101b1b
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/Inputs/tag-types.lldbinit
@@ -0,0 +1,8 @@
+type lookup -- Struct
+type lookup -- Class
+type lookup -- Union
+type lookup -- Derived
+type lookup -- Derived2
+type lookup -- EnumInt
+type lookup -- EnumShort
+type lookup -- InvalidType
diff --git a/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp b/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
new file mode 100644
index 000000000000..b8154168aff3
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/ast-functions-msvc.cpp
@@ -0,0 +1,7 @@
+// clang-format off
+// REQUIRES: msvc
+
+// RUN: %build --compiler=msvc --nodefaultlib -o %t.exe -- %S/ast-functions.cpp
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/ast-functions.lldbinit 2>&1 | FileCheck %S/ast-functions.cpp
diff --git a/lit/SymbolFile/NativePDB/ast-functions.cpp b/lit/SymbolFile/NativePDB/ast-functions.cpp
new file mode 100644
index 000000000000..05c80c7298f7
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/ast-functions.cpp
@@ -0,0 +1,29 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/ast-functions.lldbinit 2>&1 | FileCheck %s
+
+static int static_fn() {
+ return 42;
+}
+
+int varargs_fn(int x, int y, ...) {
+ return x + y;
+}
+
+int main(int argc, char **argv) {
+ return static_fn() + varargs_fn(argc, argc);
+}
+
+// CHECK: TranslationUnitDecl
+// CHECK-NEXT: |-FunctionDecl {{.*}} main 'int (int, char **)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} argc 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} argv 'char **'
+// CHECK-NEXT: |-FunctionDecl {{.*}} static_fn 'int ()' static
+// CHECK-NEXT: |-FunctionDecl {{.*}} varargs_fn 'int (int, int, ...)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} x 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} y 'int'
+// CHECK-NEXT: `-<undeserialized declarations>
diff --git a/lit/SymbolFile/NativePDB/ast-types.cpp b/lit/SymbolFile/NativePDB/ast-types.cpp
new file mode 100644
index 000000000000..224c7c26e846
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/ast-types.cpp
@@ -0,0 +1,131 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test various interesting cases for AST reconstruction.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/ast-types.lldbinit 2>&1 | FileCheck %s
+
+// Test trivial versions of each tag type.
+class TrivialC {};
+struct TrivialS {};
+union TrivialU {};
+enum TrivialE {TE_A};
+
+// Test reconstruction of DeclContext hierarchies.
+namespace A {
+ namespace B {
+ template<typename T>
+ struct C {
+ T ABCMember;
+ };
+
+ // Let's try a template specialization with a different implementation
+ template<>
+ struct C<void> {
+ void *ABCSpecializationMember;
+ };
+ }
+
+ // Let's make sure we can distinguish classes and namespaces. Also let's try
+ // a non-type template parameter.
+ template<int N>
+ struct C {
+ class D {
+ int ACDMember = 0;
+ C<N - 1> *CPtr = nullptr;
+ };
+ };
+
+ struct D {
+ // Let's make a nested class with the same name as another nested class
+ // elsewhere, and confirm that they appear in the right DeclContexts in
+ // the AST.
+ struct E {
+ int ADDMember;
+ };
+ };
+}
+
+
+// Let's try an anonymous namespace.
+namespace {
+ template<typename T>
+ struct Anonymous {
+ int AnonymousMember;
+ // And a nested class within an anonymous namespace
+ struct D {
+ int AnonymousDMember;
+ };
+ };
+}
+
+TrivialC TC;
+TrivialS TS;
+TrivialU TU;
+TrivialE TE;
+
+A::B::C<int> ABCInt;
+A::B::C<float> ABCFloat;
+A::B::C<void> ABCVoid;
+
+A::C<0> AC0;
+A::C<-1> ACNeg1;
+
+A::C<0>::D AC0D;
+A::C<-1>::D ACNeg1D;
+A::D AD;
+A::D::E ADE;
+
+// FIXME: Anonymous namespaces aren't working correctly.
+Anonymous<int> AnonInt;
+Anonymous<A::B::C<void>> AnonABCVoid;
+Anonymous<A::B::C<int>>::D AnonABCVoidD;
+
+// FIXME: Enum size isn't being correctly determined.
+// FIXME: Can't read memory for variable values.
+
+// CHECK: (TrivialC) TC = {}
+// CHECK: (TrivialS) TS = {}
+// CHECK: (TrivialU) TU = {}
+// CHECK: (TrivialE) TE = TE_A
+// CHECK: (A::B::C<int>) ABCInt = (ABCMember = 0)
+// CHECK: (A::B::C<float>) ABCFloat = (ABCMember = 0)
+// CHECK: (A::B::C<void>) ABCVoid = (ABCSpecializationMember = 0x{{0+}})
+// CHECK: (A::C<0>) AC0 = {}
+// CHECK: (A::C<-1>) ACNeg1 = {}
+// CHECK: (A::C<0>::D) AC0D = (ACDMember = 0, CPtr = 0x{{0+}})
+// CHECK: (A::C<-1>::D) ACNeg1D = (ACDMember = 0, CPtr = 0x{{0+}})
+// CHECK: (A::D) AD = {}
+// CHECK: (A::D::E) ADE = (ADDMember = 0)
+// CHECK: Dumping clang ast for 1 modules.
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} class TrivialC definition
+// CHECK: |-CXXRecordDecl {{.*}} struct TrivialS definition
+// CHECK: |-CXXRecordDecl {{.*}} union TrivialU definition
+// CHECK: |-EnumDecl {{.*}} TrivialE
+// CHECK: | `-EnumConstantDecl {{.*}} TE_A 'TrivialE'
+// CHECK: |-NamespaceDecl {{.*}} A
+// CHECK: | |-NamespaceDecl {{.*}} B
+// CHECK: | | |-CXXRecordDecl {{.*}} struct C<int> definition
+// CHECK: | | | `-FieldDecl {{.*}} ABCMember 'int'
+// CHECK: | | |-CXXRecordDecl {{.*}} struct C<float> definition
+// CHECK: | | | `-FieldDecl {{.*}} ABCMember 'float'
+// CHECK: | | `-CXXRecordDecl {{.*}} struct C<void> definition
+// CHECK: | | `-FieldDecl {{.*}} ABCSpecializationMember 'void *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct C<0> definition
+// CHECK: | | `-CXXRecordDecl {{.*}} class D definition
+// CHECK: | | |-FieldDecl {{.*}} ACDMember 'int'
+// CHECK: | | `-FieldDecl {{.*}} CPtr 'A::C<-1> *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct C<-1> definition
+// CHECK: | | `-CXXRecordDecl {{.*}} class D definition
+// CHECK: | | |-FieldDecl {{.*}} ACDMember 'int'
+// CHECK: | | `-FieldDecl {{.*}} CPtr 'A::C<-2> *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct C<-2>
+// CHECK: | `-CXXRecordDecl {{.*}} struct D definition
+// CHECK: | `-CXXRecordDecl {{.*}} struct E definition
+// CHECK: | `-FieldDecl {{.*}} ADDMember 'int'
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/lit/SymbolFile/NativePDB/bitfields.cpp b/lit/SymbolFile/NativePDB/bitfields.cpp
new file mode 100644
index 000000000000..301ae3067d13
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/bitfields.cpp
@@ -0,0 +1,60 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test various interesting cases for AST reconstruction.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/bitfields.lldbinit 2>&1 | FileCheck %s
+
+// Test trivial versions of each tag type.
+struct Struct {
+ int A : 5 = 6;
+ int B : 7 = 8;
+ unsigned C : 3 = 2;
+ unsigned D : 15 = 12345;
+ char E : 1 = 0;
+ char F : 2 = 1;
+ char G : 3 = 2;
+ // H should be at offset 0 of a new byte.
+ char H : 3 = 3;
+};
+
+constexpr Struct TheStruct;
+
+
+int main(int argc, char **argv) {
+ return TheStruct.A;
+}
+
+// CHECK: (lldb) target variable -T TheStruct
+// CHECK: (const Struct) TheStruct = {
+// CHECK: (int:5) A = 6
+// CHECK: (int:7) B = 8
+// CHECK: (unsigned int:3) C = 2
+// CHECK: (unsigned int:15) D = 12345
+// CHECK: (char:1) E = '\0'
+// CHECK: (char:2) F = '\x01'
+// CHECK: (char:3) G = '\x02'
+// CHECK: (char:3) H = '\x03'
+// CHECK: }
+//
+// CHECK: target modules dump ast
+// CHECK: Dumping clang ast for 1 modules.
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} struct Struct definition
+// CHECK: | |-FieldDecl {{.*}} A 'int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 5
+// CHECK: | |-FieldDecl {{.*}} B 'int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 7
+// CHECK: | |-FieldDecl {{.*}} C 'unsigned int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 3
+// CHECK: | |-FieldDecl {{.*}} D 'unsigned int'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 15
+// CHECK: | |-FieldDecl {{.*}} E 'char'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 1
+// CHECK: | |-FieldDecl {{.*}} F 'char'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 2
+// CHECK: | |-FieldDecl {{.*}} G 'char'
+// CHECK: | | `-IntegerLiteral {{.*}} 'int' 3
+// CHECK: | `-FieldDecl {{.*}} H 'char'
+// CHECK: | `-IntegerLiteral {{.*}} 'int' 3
diff --git a/lit/SymbolFile/NativePDB/break-by-function.cpp b/lit/SymbolFile/NativePDB/break-by-function.cpp
new file mode 100644
index 000000000000..c0c26f7617c9
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/break-by-function.cpp
@@ -0,0 +1,57 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can set simple breakpoints using PDB on any platform.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/break-by-function.lldbinit | FileCheck %s
+
+// Use different indentation style for each overload so that the starting
+// line is in a different place.
+
+int OvlGlobalFn(int X) {
+ return X + 42;
+}
+
+int OvlGlobalFn(int X, int Y) { return X + Y + 42; }
+
+int OvlGlobalFn(int X, int Y, int Z)
+{
+ return X + Y + Z + 42;
+}
+
+static int StaticFn(int X) {
+ return X + 42;
+}
+
+int main(int argc, char **argv) {
+ // Make sure they don't get optimized out.
+ // Note the comments here, we want to make sure the line number reported
+ // for the breakpoint is the first actual line of code.
+ int Result = OvlGlobalFn(argc) + OvlGlobalFn(argc, argc)
+ + OvlGlobalFn(argc, argc, argc) + StaticFn(argc);
+ return Result;
+}
+
+
+// CHECK: (lldb) target create "{{.*}}break-by-function.cpp.tmp.exe"
+// CHECK: Current executable set to '{{.*}}break-by-function.cpp.tmp.exe'
+// CHECK: (lldb) break set -n main
+// CHECK: Breakpoint 1: where = break-by-function.cpp.tmp.exe`main + {{[0-9]+}}
+// CHECK: (lldb) break set -n OvlGlobalFn
+// CHECK: Breakpoint 2: 3 locations.
+// CHECK: (lldb) break set -n StaticFn
+// CHECK: Breakpoint 3: where = break-by-function.cpp.tmp.exe`StaticFn + {{[0-9]+}}
+// CHECK: (lldb) break set -n DoesntExist
+// CHECK: Breakpoint 4: no locations (pending).
+// CHECK: (lldb) break list
+// CHECK: Current breakpoints:
+// CHECK: 1: name = 'main', locations = 1
+// CHECK: 1.1: where = break-by-function.cpp.tmp.exe`main + {{[0-9]+}}
+// CHECK: 2: name = 'OvlGlobalFn', locations = 3
+// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}}
+// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`OvlGlobalFn
+// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}}
+// CHECK: 3: name = 'StaticFn', locations = 1
+// CHECK: 3.1: where = break-by-function.cpp.tmp.exe`StaticFn + {{[0-9]+}}
+// CHECK: 4: name = 'DoesntExist', locations = 0 (pending)
diff --git a/lit/SymbolFile/NativePDB/break-by-line.cpp b/lit/SymbolFile/NativePDB/break-by-line.cpp
new file mode 100644
index 000000000000..ae3269f3719f
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/break-by-line.cpp
@@ -0,0 +1,26 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can set simple breakpoints using PDB on any platform.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/break-by-line.lldbinit | FileCheck %s
+
+// This is a separate test from break-by-function.cpp because this test is
+// sensitive to edits in the source file.
+
+namespace NS {
+ int NamespaceFn(int X) {
+ return X + 42;
+ }
+}
+
+int main(int argc, char **argv) {
+ return NS::NamespaceFn(argc);
+}
+
+
+// CHECK: (lldb) target create "{{.*}}break-by-line.cpp.tmp.exe"
+// CHECK: Current executable set to '{{.*}}break-by-line.cpp.tmp.exe'
+// CHECK: (lldb) break set -f break-by-line.cpp -l 14
+// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`NS::NamespaceFn + {{[0-9]+}} at break-by-line.cpp:14
diff --git a/lit/SymbolFile/NativePDB/disassembly.cpp b/lit/SymbolFile/NativePDB/disassembly.cpp
new file mode 100644
index 000000000000..3553f29ce55c
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/disassembly.cpp
@@ -0,0 +1,38 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can show disassembly and source.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/disassembly.lldbinit | FileCheck %s
+
+// Some context lines before
+// the function.
+
+int foo() { return 42; }
+
+int main(int argc, char **argv) {
+ foo();
+ return 0;
+}
+
+
+// CHECK: (lldb) disassemble --flavor=intel -m -n main
+// CHECK: 12 int foo() { return 42; }
+// CHECK-NEXT: 13
+// CHECK-NEXT: ** 14 int main(int argc, char **argv) {
+// CHECK: disassembly.cpp.tmp.exe`main:
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+0>: sub rsp, 0x38
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+4>: mov dword ptr [rsp + 0x34], 0x0
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+12>: mov qword ptr [rsp + 0x28], rdx
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+17>: mov dword ptr [rsp + 0x24], ecx
+// CHECK: ** 15 foo();
+// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; foo at disassembly.cpp:12
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+26>: xor ecx, ecx
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+28>: mov dword ptr [rsp + 0x20], eax
+// CHECK: ** 16 return 0;
+// CHECK-NEXT: 17 }
+// CHECK-NEXT: 18
+// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+32>: mov eax, ecx
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+34>: add rsp, 0x38
+// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+38>: ret
diff --git a/lit/SymbolFile/NativePDB/function-types-builtins.cpp b/lit/SymbolFile/NativePDB/function-types-builtins.cpp
new file mode 100644
index 000000000000..ac76955197a2
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/function-types-builtins.cpp
@@ -0,0 +1,214 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/function-types-builtins.lldbinit | FileCheck %s
+
+// Test that we can display function signatures with simple builtin
+// and pointer types. We do this by using `target variable` in lldb
+// with global variables of type ptr-to-function or reference-to-function.
+// This technique in general allows us to exercise most of LLDB's type
+// system without a running process.
+
+template<typename T>
+struct MakeResult {
+ static T result() {
+ return T{};
+ }
+};
+
+template<typename T>
+struct MakeResult<T&> {
+ static T& result() {
+ static T t;
+ return t;
+ }
+};
+
+template<typename T>
+struct MakeResult<T&&> {
+ static T&& result() {
+ static T t;
+ return static_cast<T&&>(t);
+ }
+};
+
+
+void nullary() {}
+
+template<typename Arg>
+void unary(Arg) { }
+
+template<typename Ret, int N>
+Ret unaryret() { return MakeResult<Ret>::result(); }
+
+template<typename A1, typename A2>
+void binary(A1, A2) { }
+
+int varargs(int, int, ...) { return 0; }
+
+// Make sure to test every builtin type at least once for completeness. We
+// test these in the globals-fundamentals.cpp when they are the types of
+// variables but it's possible to imagine a situation where things behave
+// differently as function arguments or return values than they do with
+// global variables.
+
+// some interesting cases with argument types.
+auto aa = &unary<bool>;
+// CHECK: (void (*)(bool)) aa = {{.*}}
+auto ab = &unary<char>;
+// CHECK: (void (*)(char)) ab = {{.*}}
+auto ac = &unary<signed char>;
+// CHECK: (void (*)(signed char)) ac = {{.*}}
+auto ad = &unary<unsigned char>;
+// CHECK: (void (*)(unsigned char)) ad = {{.*}}
+auto ae = &unary<char16_t>;
+// CHECK: (void (*)(char16_t)) ae = {{.*}}
+auto af = &unary<char32_t>;
+// CHECK: (void (*)(char32_t)) af = {{.*}}
+auto ag = &unary<wchar_t>;
+// CHECK: (void (*)(wchar_t)) ag = {{.*}}
+auto ah = &unary<short>;
+// CHECK: (void (*)(short)) ah = {{.*}}
+auto ai = &unary<unsigned short>;
+// CHECK: (void (*)(unsigned short)) ai = {{.*}}
+auto aj = &unary<int>;
+// CHECK: (void (*)(int)) aj = {{.*}}
+auto ak = &unary<unsigned int>;
+// CHECK: (void (*)(unsigned int)) ak = {{.*}}
+auto al = &unary<long>;
+// CHECK: (void (*)(long)) al = {{.*}}
+auto am = &unary<unsigned long>;
+// CHECK: (void (*)(unsigned long)) am = {{.*}}
+auto an = &unary<long long>;
+// CHECK: (void (*)(long long)) an = {{.*}}
+auto ao = &unary<unsigned long long>;
+// CHECK: (void (*)(unsigned long long)) ao = {{.*}}
+auto aq = &unary<float>;
+// CHECK: (void (*)(float)) aq = {{.*}}
+auto ar = &unary<double>;
+// CHECK: (void (*)(double)) ar = {{.*}}
+
+auto as = &unary<int*>;
+// CHECK: (void (*)(int *)) as = {{.*}}
+auto at = &unary<int**>;
+// CHECK: (void (*)(int **)) at = {{.*}}
+auto au = &unary<int&>;
+// CHECK: (void (*)(int &)) au = {{.*}}
+auto av = &unary<int&&>;
+// CHECK: (void (*)(int &&)) av = {{.*}}
+auto aw = &unary<const int*>;
+// CHECK: (void (*)(const int *)) aw = {{.*}}
+auto ax = &unary<volatile int*>;
+// CHECK: (void (*)(volatile int *)) ax = {{.*}}
+auto ay = &unary<const volatile int*>;
+// CHECK: (void (*)(const volatile int *)) ay = {{.*}}
+auto az = &unary<void*&>;
+// CHECK: (void (*)(void *&)) az = {{.*}}
+auto aaa = &unary<int(&)[5]>;
+// CHECK: (void (*)(int (&)[5])) aaa = {{.*}}
+auto aab = &unary<int(*)[5]>;
+// CHECK: (void (*)(int (*)[5])) aab = {{.*}}
+auto aac = &unary<int(&&)[5]>;
+// CHECK: (void (*)(int (&&)[5])) aac = {{.*}}
+auto aad = &unary<int(*const)[5]>;
+// CHECK: (void (*)(int (*)[5])) aad = {{.*}}
+
+
+// same test cases with return values, note we can't overload on return type
+// so we need to use a different instantiation each time.
+auto ra = &unaryret<bool, 0>;
+// CHECK: (bool (*)()) ra = {{.*}}
+auto rb = &unaryret<char, 1>;
+// CHECK: (char (*)()) rb = {{.*}}
+auto rc = &unaryret<signed char, 2>;
+// CHECK: (signed char (*)()) rc = {{.*}}
+auto rd = &unaryret<unsigned char, 3>;
+// CHECK: (unsigned char (*)()) rd = {{.*}}
+auto re = &unaryret<char16_t, 4>;
+// CHECK: (char16_t (*)()) re = {{.*}}
+auto rf = &unaryret<char32_t, 5>;
+// CHECK: (char32_t (*)()) rf = {{.*}}
+auto rg = &unaryret<wchar_t, 6>;
+// CHECK: (wchar_t (*)()) rg = {{.*}}
+auto rh = &unaryret<short, 7>;
+// CHECK: (short (*)()) rh = {{.*}}
+auto ri = &unaryret<unsigned short, 8>;
+// CHECK: (unsigned short (*)()) ri = {{.*}}
+auto rj = &unaryret<int, 9>;
+// CHECK: (int (*)()) rj = {{.*}}
+auto rk = &unaryret<unsigned int, 10>;
+// CHECK: (unsigned int (*)()) rk = {{.*}}
+auto rl = &unaryret<long, 11>;
+// CHECK: (long (*)()) rl = {{.*}}
+auto rm = &unaryret<unsigned long, 12>;
+// CHECK: (unsigned long (*)()) rm = {{.*}}
+auto rn = &unaryret<long long, 13>;
+// CHECK: (long long (*)()) rn = {{.*}}
+auto ro = &unaryret<unsigned long long, 14>;
+// CHECK: (unsigned long long (*)()) ro = {{.*}}
+auto rq = &unaryret<float, 15>;
+// CHECK: (float (*)()) rq = {{.*}}
+auto rr = &unaryret<double, 16>;
+// CHECK: (double (*)()) rr = {{.*}}
+
+auto rs = &unaryret<int*, 17>;
+// CHECK: (int *(*)()) rs = {{.*}}
+auto rt = &unaryret<int**, 18>;
+// CHECK: (int **(*)()) rt = {{.*}}
+auto ru = &unaryret<int&, 19>;
+// CHECK: (int &(*)()) ru = {{.*}}
+auto rv = &unaryret<int&&, 20>;
+// CHECK: (int &&(*)()) rv = {{.*}}
+auto rw = &unaryret<const int*, 21>;
+// CHECK: (const int *(*)()) rw = {{.*}}
+auto rx = &unaryret<volatile int*, 22>;
+// CHECK: (volatile int *(*)()) rx = {{.*}}
+auto ry = &unaryret<const volatile int*, 23>;
+// CHECK: (const volatile int *(*)()) ry = {{.*}}
+auto rz = &unaryret<void*&, 24>;
+// CHECK: (void *&(*)()) rz = {{.*}}
+
+// FIXME: This output doesn't really look correct. It should probably be
+// formatting this as `int(&)[5] (*)()`.
+auto raa = &unaryret<int(&)[5], 25>;
+// CHECK: (int (&(*)())[5]) raa = {{.*}}
+auto rab = &unaryret<int(*)[5], 26>;
+// CHECK: (int (*(*)())[5]) rab = {{.*}}
+auto rac = &unaryret<int(&&)[5], 27>;
+// CHECK: (int (&&(*)())[5]) rac = {{.*}}
+auto rad = &unaryret<int(*const)[5], 28>;
+// CHECK: (int (*const (*)())[5]) rad = {{.*}}
+
+
+
+// Function references, we only need a couple of these since most of the
+// interesting cases are already tested.
+auto &ref = unary<bool>;
+// CHECK: (void (&)(bool)) ref = {{.*}} (&::ref = <Unable to determine byte size.>)
+auto &ref2 = unary<volatile int*>;
+// CHECK: (void (&)(volatile int *)) ref2 = {{.*}} (&::ref2 = <Unable to determine byte size.>)
+auto &ref3 = varargs;
+// CHECK: (int (&)(int, int, ...)) ref3 = {{.*}} (&::ref3 = <Unable to determine byte size.>)
+
+// Multiple arguments, as before, just something to make sure it works.
+auto binp = &binary<int*, const int*>;
+// CHECK: (void (*)(int *, const int *)) binp = {{.*}}
+auto &binr = binary<int*, const int*>;
+// CHECK: (void (&)(int *, const int *)) binr = {{.*}} (&::binr = <Unable to determine byte size.>)
+
+// And finally, a function with no arguments.
+auto null = &nullary;
+// CHECK: (void (*)()) null = {{.*}}
+
+// FIXME: These currently don't work because clang-cl emits incorrect debug info
+// for std::nullptr_t. We should fix these in clang-cl.
+auto rae = &unaryret<decltype(nullptr), 29>;
+// CHECK: (nullptr_t (*)()) rae = {{.*}}
+auto aae = &unary<decltype(nullptr)>;
+// CHECK: (void (*)(nullptr_t)) aae = {{.*}}
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp b/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp
new file mode 100644
index 000000000000..cd13159d508c
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/function-types-calling-conv.cpp
@@ -0,0 +1,32 @@
+// clang-format off
+// REQUIRES: lld
+
+// RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/function-types-calling-conv.lldbinit | FileCheck %s
+
+
+void __stdcall StdcallFn() {}
+void __fastcall FastcallFn() {}
+void __thiscall ThiscallFn() {}
+void __cdecl CdeclFn() {}
+void __vectorcall VectorcallFn() {}
+
+auto sfn = &StdcallFn;
+// CHECK: (void (*)() __attribute__((stdcall))) sfn = {{.*}}
+
+auto ffn = &FastcallFn;
+// CHECK: (void (*)() __attribute__((fastcall))) ffn = {{.*}}
+
+auto tfn = &ThiscallFn;
+// CHECK: (void (*)() __attribute__((thiscall))) tfn = {{.*}}
+
+auto cfn = &CdeclFn;
+// CHECK: (void (*)()) cfn = {{.*}}
+
+auto vfn = &VectorcallFn;
+// CHECK: (void (*)() __attribute__((vectorcall))) vfn = {{.*}}
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/lit/SymbolFile/NativePDB/function-types-classes.cpp b/lit/SymbolFile/NativePDB/function-types-classes.cpp
new file mode 100644
index 000000000000..5670f9bd1e17
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/function-types-classes.cpp
@@ -0,0 +1,141 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display function signatures with class types.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/function-types-classes.lldbinit | FileCheck %s
+
+// This is just some unimportant helpers needed so that we can get reference and
+// rvalue-reference types into return values.
+template<typename T>
+struct MakeResult {
+ static T result() {
+ return T{};
+ }
+};
+
+template<typename T>
+struct MakeResult<T&> {
+ static T& result() {
+ static T t;
+ return t;
+ }
+};
+
+template<typename T>
+struct MakeResult<T&&> {
+ static T&& result() {
+ static T t;
+ return static_cast<T&&>(t);
+ }
+};
+
+
+template<typename R>
+R nullary() { return MakeResult<R>::result(); }
+
+template<typename R, typename A, typename B>
+R three(A a, B b) { return MakeResult<R>::result(); }
+
+template<typename R, typename A, typename B, typename C>
+R four(A a, B b, C c) { return MakeResult<R>::result(); }
+
+struct S {};
+class C {};
+union U {};
+enum E {};
+
+namespace A {
+ namespace B {
+ // NS::NS
+ struct S { };
+ }
+
+ struct C {
+ // NS::Struct
+ struct S {};
+ };
+}
+
+struct B {
+ struct A {
+ // Struct::Struct
+ struct S {};
+ };
+};
+
+// clang (incorrectly) doesn't emit debug information for outer classes
+// unless they are instantiated. They should also be emitted if there
+// is an inner class which is instantiated.
+A::C ForceInstantiateAC;
+B ForceInstantiateB;
+B::A ForceInstantiateBA;
+
+template<typename T>
+struct TC {};
+
+// const and volatile modifiers
+auto a = &four<S, C*, U&, E&&>;
+// CHECK: (S (*)(C *, U &, E &&)) a = {{.*}}
+auto b = &four<E, const S*, const C&, const U&&>;
+// CHECK: (E (*)(const S *, const C &, const U &&)) b = {{.*}}
+auto c = &four<U, volatile E*, volatile S&, volatile C&&>;
+// CHECK: (U (*)(volatile E *, volatile S &, volatile C &&)) c = {{.*}}
+auto d = &four<C, const volatile U*, const volatile E&, const volatile S&&>;
+// CHECK: (C (*)(const volatile U *, const volatile E &, const volatile S &&)) d = {{.*}}
+
+// classes nested in namespaces and inner classes
+
+auto e = &three<A::B::S*, B::A::S*, A::C::S&>;
+// CHECK: (A::B::S *(*)(B::A::S *, A::C::S &)) e = {{.*}}
+auto f = &three<A::C::S&, A::B::S*, B::A::S*>;
+// CHECK: (A::C::S &(*)(A::B::S *, B::A::S *)) f = {{.*}}
+auto g = &three<B::A::S*, A::C::S&, A::B::S*>;
+// CHECK: (B::A::S *(*)(A::C::S &, A::B::S *)) g = {{.*}}
+
+// parameter types that are themselves template instantiations.
+auto h = &four<TC<void>, TC<int>, TC<TC<int>>, TC<A::B::S>>;
+// CHECK: (TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)) h = {{.*}}
+
+auto i = &nullary<A::B::S>;
+// CHECK: (A::B::S (*)()) i = {{.*}}
+
+
+// Make sure we can handle types that don't have complete debug info.
+struct Incomplete;
+auto incomplete = &three<Incomplete*, Incomplete**, const Incomplete*>;
+// CHECK: (Incomplete *(*)(Incomplete **, const Incomplete *)) incomplete = {{.*}}
+
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} class C
+// CHECK: |-CXXRecordDecl {{.*}} union U
+// CHECK: |-EnumDecl {{.*}} E
+// CHECK: |-CXXRecordDecl {{.*}} struct S
+// CHECK: |-VarDecl {{.*}} a 'S (*)(C *, U &, E &&)'
+// CHECK: |-VarDecl {{.*}} b 'E (*)(const S *, const C &, const U &&)'
+// CHECK: |-VarDecl {{.*}} c 'U (*)(volatile E *, volatile S &, volatile C &&)'
+// CHECK: |-VarDecl {{.*}} d 'C (*)(const volatile U *, const volatile E &, const volatile S &&)'
+// CHECK: |-CXXRecordDecl {{.*}} struct B
+// CHECK: | |-CXXRecordDecl {{.*}} struct A
+// CHECK: | | |-CXXRecordDecl {{.*}} struct S
+// CHECK: |-NamespaceDecl {{.*}} A
+// CHECK: | |-CXXRecordDecl {{.*}} struct C
+// CHECK: | | |-CXXRecordDecl {{.*}} struct S
+// CHECK: | `-NamespaceDecl {{.*}} B
+// CHECK: | `-CXXRecordDecl {{.*}} struct S
+// CHECK: |-VarDecl {{.*}} e 'A::B::S *(*)(B::A::S *, A::C::S &)'
+// CHECK: |-VarDecl {{.*}} f 'A::C::S &(*)(A::B::S *, B::A::S *)'
+// CHECK: |-VarDecl {{.*}} g 'B::A::S *(*)(A::C::S &, A::B::S *)'
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<int>
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<TC<int>>
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<A::B::S>
+// CHECK: |-CXXRecordDecl {{.*}} struct TC<void>
+// CHECK: |-VarDecl {{.*}} h 'TC<void> (*)(TC<int>, TC<TC<int>>, TC<A::B::S>)'
+// CHECK: |-VarDecl {{.*}} i 'A::B::S (*)()'
+// CHECK: |-CXXRecordDecl {{.*}} struct Incomplete
+// CHECK: |-VarDecl {{.*}} incomplete 'Incomplete *(*)(Incomplete **, const Incomplete *)'
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/lit/SymbolFile/NativePDB/global-classes.cpp b/lit/SymbolFile/NativePDB/global-classes.cpp
new file mode 100644
index 000000000000..ea7cc745d74d
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/global-classes.cpp
@@ -0,0 +1,370 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display tag types.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/globals-classes.lldbinit | FileCheck %s
+
+enum class EnumType : unsigned {
+ A = 1,
+ B = 2
+};
+
+class ClassNoPadding {
+ /* [ 0] */ unsigned char a = 86;
+ /* [ 1] */ char b = 'a';
+ /* [ 2] */ bool c = false;
+ /* [ 3] */ bool d = true;
+ /* [ 4] */ short e = -1234;
+ /* [ 6] */ unsigned short f = 8123;
+ /* [ 8] */ unsigned int g = 123908;
+ /* [12] */ int h = -890234;
+ /* [16] */ unsigned long i = 2908234;
+ /* [20] */ long j = 7234890;
+ /* [24] */ float k = 908234.12392;
+ /* [28] */ EnumType l = EnumType::A;
+ /* [32] */ double m = 23890.897423;
+ /* [40] */ unsigned long long n = 23490782;
+ /* [48] */ long long o = -923409823;
+ /* [56] */ int p[5] = { 2, 3, 5, 8, 13 };
+};
+
+class ClassWithPadding {
+ /* [ 0] */ char a = '0';
+ // char padding[1];
+ /* [ 2] */ short b = 50;
+ /* [ 4] */ char c[2] = { '0', '1' };
+ // char padding[2];
+ /* [ 8] */ int d = 100;
+ /* [12] */ char e = '0';
+ // char padding[3];
+ /* [16] */ int f = 200;
+ // char padding[4];
+ /* [24] */ long long g = 300;
+ /* [32] */ char h[3] = { '0', '1', '2' };
+ // char padding[5];
+ /* [40] */ long long i = 400;
+ /* [48] */ char j[2] = { '0', '1' };
+ // char padding[6];
+ /* [56] */ long long k = 500;
+ /* [64] */ char l = '0';
+ // char padding[7];
+ /* [72] */ long long m = 600;
+} ;
+
+struct EmptyBase {};
+
+template<typename T>
+struct BaseClass {
+ constexpr BaseClass(int N)
+ : BaseMember(N) {}
+
+ int BaseMember;
+};
+
+struct DerivedClass : public BaseClass<int> {
+ constexpr DerivedClass(int Base, int Derived)
+ : BaseClass(Base), DerivedMember(Derived) {}
+
+ int DerivedMember;
+};
+
+struct EBO : public EmptyBase {
+ constexpr EBO(int N) : Member(N) {}
+ int Member;
+};
+
+struct PaddedBases : public BaseClass<char>, public BaseClass<short>, BaseClass<int> {
+ constexpr PaddedBases(char CH, short S, int N, long long D)
+ : BaseClass<char>(CH), BaseClass<short>(S), BaseClass<int>(N), DerivedMember(D) {}
+ long long DerivedMember;
+};
+
+struct Statics {
+ static char a;
+ static bool b;
+ static short c;
+ static unsigned short d;
+ static unsigned int e;
+ static int f;
+ static unsigned long g;
+ static long h;
+ static float i;
+ static EnumType j;
+ static double k;
+ static unsigned long long l;
+ static long long m;
+};
+
+char Statics::a = 'a';
+bool Statics::b = true;
+short Statics::c = 1234;
+unsigned short Statics::d = 2345;
+unsigned int Statics::e = 3456;
+int Statics::f = 4567;
+unsigned long Statics::g = 5678;
+long Statics::h = 6789;
+float Statics::i = 7890.1234;
+EnumType Statics::j = EnumType::A;
+double Statics::k = 8901.2345;
+unsigned long long Statics::l = 9012345;
+long long Statics::m = 1234567;
+
+
+struct Pointers {
+ void *a = nullptr;
+ char *b = &Statics::a;
+ bool *c = &Statics::b;
+ short *e = &Statics::c;
+ unsigned short *f = &Statics::d;
+ unsigned int *g = &Statics::e;
+ int *h = &Statics::f;
+ unsigned long *i = &Statics::g;
+ long *j = &Statics::h;
+ float *k = &Statics::i;
+ EnumType *l = &Statics::j;
+ double *m = &Statics::k;
+ unsigned long long *n = &Statics::l;
+ long long *o = &Statics::m;
+};
+
+struct References {
+ char &a = Statics::a;
+ bool &b = Statics::b;
+ short &c = Statics::c;
+ unsigned short &d = Statics::d;
+ unsigned int &e = Statics::e;
+ int &f = Statics::f;
+ unsigned long &g = Statics::g;
+ long &h = Statics::h;
+ float &i = Statics::i;
+ EnumType &j = Statics::j;
+ double &k = Statics::k;
+ unsigned long long &l = Statics::l;
+ long long &m = Statics::m;
+};
+
+
+constexpr ClassWithPadding ClassWithPaddingInstance;
+// CHECK: (lldb) target variable -T ClassWithPaddingInstance
+// CHECK-NEXT: (const ClassWithPadding) ClassWithPaddingInstance = {
+// CHECK-NEXT: (char) a = '0'
+// CHECK-NEXT: (short) b = 50
+// CHECK-NEXT: (char [2]) c = "01"
+// CHECK-NEXT: (int) d = 100
+// CHECK-NEXT: (char) e = '0'
+// CHECK-NEXT: (int) f = 200
+// CHECK-NEXT: (long long) g = 300
+// CHECK-NEXT: (char [3]) h = "012"
+// CHECK-NEXT: (long long) i = 400
+// CHECK-NEXT: (char [2]) j = "01"
+// CHECK-NEXT: (long long) k = 500
+// CHECK-NEXT: (char) l = '0'
+// CHECK-NEXT: (long long) m = 600
+// CHECK-NEXT: }
+
+constexpr ClassNoPadding ClassNoPaddingInstance;
+// CHECK: (lldb) target variable -T ClassNoPaddingInstance
+// CHECK-NEXT: (const ClassNoPadding) ClassNoPaddingInstance = {
+// CHECK-NEXT: (unsigned char) a = 'V'
+// CHECK-NEXT: (char) b = 'a'
+// CHECK-NEXT: (bool) c = false
+// CHECK-NEXT: (bool) d = true
+// CHECK-NEXT: (short) e = -1234
+// CHECK-NEXT: (unsigned short) f = 8123
+// CHECK-NEXT: (unsigned int) g = 123908
+// CHECK-NEXT: (int) h = -890234
+// CHECK-NEXT: (unsigned long) i = 2908234
+// CHECK-NEXT: (long) j = 7234890
+// CHECK-NEXT: (float) k = 908234.125
+// CHECK-NEXT: (EnumType) l = A
+// CHECK-NEXT: (double) m = 23890.897422999999
+// CHECK-NEXT: (unsigned long long) n = 23490782
+// CHECK-NEXT: (long long) o = -923409823
+// CHECK-NEXT: (int [5]) p = {
+// CHECK-NEXT: (int) [0] = 2
+// CHECK-NEXT: (int) [1] = 3
+// CHECK-NEXT: (int) [2] = 5
+// CHECK-NEXT: (int) [3] = 8
+// CHECK-NEXT: (int) [4] = 13
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+
+constexpr DerivedClass DC(10, 20);
+// CHECK: (lldb) target variable -T DC
+// CHECK-NEXT: (const DerivedClass) DC = {
+// CHECK-NEXT: (BaseClass<int>) BaseClass<int> = {
+// CHECK-NEXT: (int) BaseMember = 10
+// CHECK-NEXT: }
+// CHECK-NEXT: (int) DerivedMember = 20
+// CHECK-NEXT: }
+
+constexpr EBO EBOC(20);
+// CHECK: (lldb) target variable -T EBOC
+// CHECK-NEXT: (const EBO) EBOC = {
+// CHECK-NEXT: (int) Member = 20
+// CHECK-NEXT: }
+
+constexpr PaddedBases PBC('a', 12, 120, 1200);
+// CHECK: (lldb) target variable -T PBC
+// CHECK-NEXT: (const PaddedBases) PBC = {
+// CHECK-NEXT: (BaseClass<char>) BaseClass<char> = {
+// CHECK-NEXT: (int) BaseMember = 97
+// CHECK-NEXT: }
+// CHECK-NEXT: (BaseClass<short>) BaseClass<short> = {
+// CHECK-NEXT: (int) BaseMember = 12
+// CHECK-NEXT: }
+// CHECK-NEXT: (BaseClass<int>) BaseClass<int> = {
+// CHECK-NEXT: (int) BaseMember = 120
+// CHECK-NEXT: }
+// CHECK-NEXT: (long long) DerivedMember = 1200
+// CHECK-NEXT: }
+
+constexpr struct {
+ int x = 12;
+ EBO EBOC{ 42 };
+} UnnamedClassInstance;
+// CHECK: (lldb) target variable -T UnnamedClassInstance
+// CHECK-NEXT: (const <unnamed-type-UnnamedClassInstance>) UnnamedClassInstance = {
+// CHECK-NEXT: (int) x = 12
+// CHECK-NEXT: (EBO) EBOC = {
+// CHECK-NEXT: (int) Member = 42
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+
+constexpr Pointers PointersInstance;
+// CHECK: (lldb) target variable -T PointersInstance
+// CHECK-NEXT: (const Pointers) PointersInstance = {
+// CHECK-NEXT: (void *) a = {{.*}}
+// CHECK-NEXT: (char *) b = {{.*}}
+// CHECK-NEXT: (bool *) c = {{.*}}
+// CHECK-NEXT: (short *) e = {{.*}}
+// CHECK-NEXT: (unsigned short *) f = {{.*}}
+// CHECK-NEXT: (unsigned int *) g = {{.*}}
+// CHECK-NEXT: (int *) h = {{.*}}
+// CHECK-NEXT: (unsigned long *) i = {{.*}}
+// CHECK-NEXT: (long *) j = {{.*}}
+// CHECK-NEXT: (float *) k = {{.*}}
+// CHECK-NEXT: (EnumType *) l = {{.*}}
+// CHECK-NEXT: (double *) m = {{.*}}
+// CHECK-NEXT: (unsigned long long *) n = {{.*}}
+// CHECK-NEXT: (long long *) o = {{.*}}
+// CHECK-NEXT: }
+constexpr References ReferencesInstance;
+// CHECK: (lldb) target variable -T ReferencesInstance
+// CHECK-NEXT: (const References) ReferencesInstance = {
+// CHECK-NEXT: (char &) a = {{.*}}
+// CHECK-NEXT: (bool &) b = {{.*}}
+// CHECK-NEXT: (short &) c = {{.*}}
+// CHECK-NEXT: (unsigned short &) d = {{.*}}
+// CHECK-NEXT: (unsigned int &) e = {{.*}}
+// CHECK-NEXT: (int &) f = {{.*}}
+// CHECK-NEXT: (unsigned long &) g = {{.*}}
+// CHECK-NEXT: (long &) h = {{.*}}
+// CHECK-NEXT: (float &) i = {{.*}}
+// CHECK-NEXT: (EnumType &) j = {{.*}}
+// CHECK-NEXT: (double &) k = {{.*}}
+// CHECK-NEXT: (unsigned long long &) l = {{.*}}
+// CHECK-NEXT: (long long &) m = {{.*}}
+// CHECK-NEXT: }
+
+// CHECK: Dumping clang ast for 1 modules.
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} class ClassWithPadding definition
+// CHECK: | |-FieldDecl {{.*}} a 'char'
+// CHECK: | |-FieldDecl {{.*}} b 'short'
+// CHECK: | |-FieldDecl {{.*}} c 'char [2]'
+// CHECK: | |-FieldDecl {{.*}} d 'int'
+// CHECK: | |-FieldDecl {{.*}} e 'char'
+// CHECK: | |-FieldDecl {{.*}} f 'int'
+// CHECK: | |-FieldDecl {{.*}} g 'long long'
+// CHECK: | |-FieldDecl {{.*}} h 'char [3]'
+// CHECK: | |-FieldDecl {{.*}} i 'long long'
+// CHECK: | |-FieldDecl {{.*}} j 'char [2]'
+// CHECK: | |-FieldDecl {{.*}} k 'long long'
+// CHECK: | |-FieldDecl {{.*}} l 'char'
+// CHECK: | `-FieldDecl {{.*}} m 'long long'
+// CHECK: |-VarDecl {{.*}} ClassWithPaddingInstance 'const ClassWithPadding'
+// CHECK: |-CXXRecordDecl {{.*}} class ClassNoPadding definition
+// CHECK: | |-FieldDecl {{.*}} a 'unsigned char'
+// CHECK: | |-FieldDecl {{.*}} b 'char'
+// CHECK: | |-FieldDecl {{.*}} c 'bool'
+// CHECK: | |-FieldDecl {{.*}} d 'bool'
+// CHECK: | |-FieldDecl {{.*}} e 'short'
+// CHECK: | |-FieldDecl {{.*}} f 'unsigned short'
+// CHECK: | |-FieldDecl {{.*}} g 'unsigned int'
+// CHECK: | |-FieldDecl {{.*}} h 'int'
+// CHECK: | |-FieldDecl {{.*}} i 'unsigned long'
+// CHECK: | |-FieldDecl {{.*}} j 'long'
+// CHECK: | |-FieldDecl {{.*}} k 'float'
+// CHECK: | |-FieldDecl {{.*}} l 'EnumType'
+// CHECK: | |-FieldDecl {{.*}} m 'double'
+// CHECK: | |-FieldDecl {{.*}} n 'unsigned long long'
+// CHECK: | |-FieldDecl {{.*}} o 'long long'
+// CHECK: | `-FieldDecl {{.*}} p 'int [5]'
+// CHECK: |-VarDecl {{.*}} ClassNoPaddingInstance 'const ClassNoPadding'
+// CHECK: |-EnumDecl {{.*}} EnumType
+// CHECK: | |-EnumConstantDecl {{.*}} A 'EnumType'
+// CHECK: | `-EnumConstantDecl {{.*}} B 'EnumType'
+// CHECK: |-CXXRecordDecl {{.*}} struct DerivedClass definition
+// CHECK: | |-public 'BaseClass<int>'
+// CHECK: | `-FieldDecl {{.*}} DerivedMember 'int'
+// CHECK: |-VarDecl {{.*}} DC 'const DerivedClass'
+// CHECK: |-CXXRecordDecl {{.*}} struct BaseClass<int> definition
+// CHECK: | `-FieldDecl {{.*}} BaseMember 'int'
+// CHECK: |-CXXRecordDecl {{.*}} struct EBO definition
+// CHECK: | |-public 'EmptyBase'
+// CHECK: | `-FieldDecl {{.*}} Member 'int'
+// CHECK: |-VarDecl {{.*}} EBOC 'const EBO'
+// CHECK: |-CXXRecordDecl {{.*}} struct EmptyBase definition
+// CHECK: |-CXXRecordDecl {{.*}} struct PaddedBases definition
+// CHECK: | |-public 'BaseClass<char>'
+// CHECK: | |-public 'BaseClass<short>'
+// CHECK: | |-public 'BaseClass<int>'
+// CHECK: | `-FieldDecl {{.*}} DerivedMember 'long long'
+// CHECK: |-VarDecl {{.*}} PBC 'const PaddedBases'
+// CHECK: |-CXXRecordDecl {{.*}} struct BaseClass<char> definition
+// CHECK: | `-FieldDecl {{.*}} BaseMember 'int'
+// CHECK: |-CXXRecordDecl {{.*}} struct BaseClass<short> definition
+// CHECK: | `-FieldDecl {{.*}} BaseMember 'int'
+// CHECK: |-CXXRecordDecl {{.*}} struct <unnamed-type-UnnamedClassInstance> definition
+// CHECK: | |-FieldDecl {{.*}} x 'int'
+// CHECK: | `-FieldDecl {{.*}} EBOC 'EBO'
+// CHECK: |-VarDecl {{.*}} UnnamedClassInstance 'const <unnamed-type-UnnamedClassInstance>'
+// CHECK: |-CXXRecordDecl {{.*}} struct Pointers definition
+// CHECK: | |-FieldDecl {{.*}} a 'void *'
+// CHECK: | |-FieldDecl {{.*}} b 'char *'
+// CHECK: | |-FieldDecl {{.*}} c 'bool *'
+// CHECK: | |-FieldDecl {{.*}} e 'short *'
+// CHECK: | |-FieldDecl {{.*}} f 'unsigned short *'
+// CHECK: | |-FieldDecl {{.*}} g 'unsigned int *'
+// CHECK: | |-FieldDecl {{.*}} h 'int *'
+// CHECK: | |-FieldDecl {{.*}} i 'unsigned long *'
+// CHECK: | |-FieldDecl {{.*}} j 'long *'
+// CHECK: | |-FieldDecl {{.*}} k 'float *'
+// CHECK: | |-FieldDecl {{.*}} l 'EnumType *'
+// CHECK: | |-FieldDecl {{.*}} m 'double *'
+// CHECK: | |-FieldDecl {{.*}} n 'unsigned long long *'
+// CHECK: | `-FieldDecl {{.*}} o 'long long *'
+// CHECK: |-VarDecl {{.*}} PointersInstance 'const Pointers'
+// CHECK: |-CXXRecordDecl {{.*}} struct References definition
+// CHECK: | |-FieldDecl {{.*}} a 'char &'
+// CHECK: | |-FieldDecl {{.*}} b 'bool &'
+// CHECK: | |-FieldDecl {{.*}} c 'short &'
+// CHECK: | |-FieldDecl {{.*}} d 'unsigned short &'
+// CHECK: | |-FieldDecl {{.*}} e 'unsigned int &'
+// CHECK: | |-FieldDecl {{.*}} f 'int &'
+// CHECK: | |-FieldDecl {{.*}} g 'unsigned long &'
+// CHECK: | |-FieldDecl {{.*}} h 'long &'
+// CHECK: | |-FieldDecl {{.*}} i 'float &'
+// CHECK: | |-FieldDecl {{.*}} j 'EnumType &'
+// CHECK: | |-FieldDecl {{.*}} k 'double &'
+// CHECK: | |-FieldDecl {{.*}} l 'unsigned long long &'
+// CHECK: | `-FieldDecl {{.*}} m 'long long &'
+// CHECK: |-VarDecl {{.*}} ReferencesInstance 'const References'
+// CHECK: `-<undeserialized declarations>
+
+int main(int argc, char **argv) {
+ return 0;
+}
diff --git a/lit/SymbolFile/NativePDB/globals-bss.cpp b/lit/SymbolFile/NativePDB/globals-bss.cpp
new file mode 100644
index 000000000000..c10c3c196286
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/globals-bss.cpp
@@ -0,0 +1,34 @@
+// clang-format off
+// REQUIRES: lld
+
+// Make sure we can read variables from BSS
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: llvm-readobj -s %t.exe | FileCheck --check-prefix=BSS %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/globals-bss.lldbinit 2>&1 | FileCheck %s
+
+int GlobalVariable = 0;
+
+int main(int argc, char **argv) {
+ return 0;
+}
+
+// BSS: Section {
+// BSS: Number: 3
+// BSS: Name: .data
+// BSS-NEXT: VirtualSize: 0x4
+// BSS-NEXT: VirtualAddress:
+// BSS-NEXT: RawDataSize: 0
+// BSS-NEXT: PointerToRawData: 0x0
+// BSS-NEXT: PointerToRelocations: 0x0
+// BSS-NEXT: PointerToLineNumbers: 0x0
+// BSS-NEXT: RelocationCount: 0
+// BSS-NEXT: LineNumberCount: 0
+// BSS-NEXT: Characteristics [ (0xC0000040)
+// BSS-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
+// BSS-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+// BSS-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
+// BSS-NEXT: ]
+// BSS-NEXT: }
+
+// CHECK: (int) GlobalVariable = 0
diff --git a/lit/SymbolFile/NativePDB/globals-fundamental.cpp b/lit/SymbolFile/NativePDB/globals-fundamental.cpp
new file mode 100644
index 000000000000..8891eddf6689
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/globals-fundamental.cpp
@@ -0,0 +1,880 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display tag types.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/globals-fundamental.lldbinit | FileCheck %s
+
+
+// Fundamental data types
+bool BFalse = false;
+// CHECK: (lldb) target variable BFalse
+// CHECK-NEXT: (bool) BFalse = false
+bool BTrue = true;
+// CHECK-NEXT: (lldb) target variable BTrue
+// CHECK-NEXT: (bool) BTrue = true
+char CA = 'A';
+// CHECK-NEXT: (lldb) target variable CA
+// CHECK-NEXT: (char) CA = 'A'
+char CZ = 'Z';
+// CHECK-NEXT: (lldb) target variable CZ
+// CHECK-NEXT: (char) CZ = 'Z'
+signed char SCa = 'a';
+// CHECK-NEXT: (lldb) target variable SCa
+// CHECK-NEXT: (signed char) SCa = 'a'
+signed char SCz = 'z';
+// CHECK-NEXT: (lldb) target variable SCz
+// CHECK-NEXT: (signed char) SCz = 'z'
+unsigned char UC24 = 24;
+// CHECK-NEXT: (lldb) target variable UC24
+// CHECK-NEXT: (unsigned char) UC24 = '\x18'
+unsigned char UC42 = 42;
+// CHECK-NEXT: (lldb) target variable UC42
+// CHECK-NEXT: (unsigned char) UC42 = '*'
+char16_t C16_24 = u'\24';
+// CHECK-NEXT: (lldb) target variable C16_24
+// CHECK-NEXT: (char16_t) C16_24 = U+0014
+char32_t C32_42 = U'\42';
+// CHECK-NEXT: (lldb) target variable C32_42
+// CHECK-NEXT: (char32_t) C32_42 = U+0x00000022
+wchar_t WC1 = L'1';
+// CHECK-NEXT: (lldb) target variable WC1
+// CHECK-NEXT: (wchar_t) WC1 = L'1'
+wchar_t WCP = L'P';
+// CHECK-NEXT: (lldb) target variable WCP
+// CHECK-NEXT: (wchar_t) WCP = L'P'
+short SMax = 32767;
+// CHECK-NEXT: (lldb) target variable SMax
+// CHECK-NEXT: (short) SMax = 32767
+short SMin = -32768;
+// CHECK-NEXT: (lldb) target variable SMin
+// CHECK-NEXT: (short) SMin = -32768
+unsigned short USMax = 65535;
+// CHECK-NEXT: (lldb) target variable USMax
+// CHECK-NEXT: (unsigned short) USMax = 65535
+unsigned short USMin = 0;
+// CHECK-NEXT: (lldb) target variable USMin
+// CHECK-NEXT: (unsigned short) USMin = 0
+int IMax = 2147483647;
+// CHECK-NEXT: (lldb) target variable IMax
+// CHECK-NEXT: (int) IMax = 2147483647
+int IMin = -2147483648;
+// CHECK-NEXT: (lldb) target variable IMin
+// CHECK-NEXT: (int) IMin = -2147483648
+unsigned int UIMax = 4294967295;
+// CHECK-NEXT: (lldb) target variable UIMax
+// CHECK-NEXT: (unsigned int) UIMax = 4294967295
+unsigned int UIMin = 0;
+// CHECK-NEXT: (lldb) target variable UIMin
+// CHECK-NEXT: (unsigned int) UIMin = 0
+long LMax = 2147483647;
+// CHECK-NEXT: (lldb) target variable LMax
+// CHECK-NEXT: (long) LMax = 2147483647
+long LMin = -2147483648;
+// CHECK-NEXT: (lldb) target variable LMin
+// CHECK-NEXT: (long) LMin = -2147483648
+unsigned long ULMax = 4294967295;
+// CHECK-NEXT: (lldb) target variable ULMax
+// CHECK-NEXT: (unsigned long) ULMax = 4294967295
+unsigned long ULMin = 0;
+// CHECK-NEXT: (lldb) target variable ULMin
+// CHECK-NEXT: (unsigned long) ULMin = 0
+long long LLMax = 9223372036854775807LL;
+// CHECK-NEXT: (lldb) target variable LLMax
+// CHECK-NEXT: (long long) LLMax = 9223372036854775807
+long long LLMin = -9223372036854775807i64 - 1;
+// CHECK-NEXT: (lldb) target variable LLMin
+// CHECK-NEXT: (long long) LLMin = -9223372036854775808
+unsigned long long ULLMax = 18446744073709551615ULL;
+// CHECK-NEXT: (lldb) target variable ULLMax
+// CHECK-NEXT: (unsigned long long) ULLMax = 18446744073709551615
+unsigned long long ULLMin = 0;
+// CHECK-NEXT: (lldb) target variable ULLMin
+// CHECK-NEXT: (unsigned long long) ULLMin = 0
+float F = 3.1415f;
+// CHECK-NEXT: (lldb) target variable F
+// CHECK-NEXT: (float) F = 3.1415
+double D = 3.1415;
+// CHECK-NEXT: (lldb) target variable D
+// CHECK-NEXT: (double) D = 3.1415
+
+const bool CBFalse = false;
+// CHECK-NEXT: (lldb) target variable CBFalse
+// CHECK-NEXT: (const bool) CBFalse = false
+const bool CBTrue = true;
+// CHECK-NEXT: (lldb) target variable CBTrue
+// CHECK-NEXT: (const bool) CBTrue = true
+const char CCA = 'A';
+// CHECK-NEXT: (lldb) target variable CCA
+// CHECK-NEXT: (const char) CCA = 'A'
+const char CCZ = 'Z';
+// CHECK-NEXT: (lldb) target variable CCZ
+// CHECK-NEXT: (const char) CCZ = 'Z'
+const signed char CSCa = 'a';
+// CHECK-NEXT: (lldb) target variable CSCa
+// CHECK-NEXT: (const signed char) CSCa = 'a'
+const signed char CSCz = 'z';
+// CHECK-NEXT: (lldb) target variable CSCz
+// CHECK-NEXT: (const signed char) CSCz = 'z'
+const unsigned char CUC24 = 24;
+// CHECK-NEXT: (lldb) target variable CUC24
+// CHECK-NEXT: (const unsigned char) CUC24 = '\x18'
+const unsigned char CUC42 = 42;
+// CHECK-NEXT: (lldb) target variable CUC42
+// CHECK-NEXT: (const unsigned char) CUC42 = '*'
+const char16_t CC16_24 = u'\24';
+// CHECK-NEXT: (lldb) target variable CC16_24
+// CHECK-NEXT: (const char16_t) CC16_24 = U+0014
+const char32_t CC32_42 = U'\42';
+// CHECK-NEXT: (lldb) target variable CC32_42
+// CHECK-NEXT: (const char32_t) CC32_42 = U+0x00000022
+const wchar_t CWC1 = L'1';
+// CHECK-NEXT: (lldb) target variable CWC1
+// CHECK-NEXT: (const wchar_t) CWC1 = L'1'
+const wchar_t CWCP = L'P';
+// CHECK-NEXT: (lldb) target variable CWCP
+// CHECK-NEXT: (const wchar_t) CWCP = L'P'
+const short CSMax = 32767;
+// CHECK-NEXT: (lldb) target variable CSMax
+// CHECK-NEXT: (const short) CSMax = 32767
+const short CSMin = -32768;
+// CHECK-NEXT: (lldb) target variable CSMin
+// CHECK-NEXT: (const short) CSMin = -32768
+const unsigned short CUSMax = 65535;
+// CHECK-NEXT: (lldb) target variable CUSMax
+// CHECK-NEXT: (const unsigned short) CUSMax = 65535
+const unsigned short CUSMin = 0;
+// CHECK-NEXT: (lldb) target variable CUSMin
+// CHECK-NEXT: (const unsigned short) CUSMin = 0
+const int CIMax = 2147483647;
+// CHECK-NEXT: (lldb) target variable CIMax
+// CHECK-NEXT: (const int) CIMax = 2147483647
+const int CIMin = -2147483648;
+// CHECK-NEXT: (lldb) target variable CIMin
+// CHECK-NEXT: (const int) CIMin = -2147483648
+const unsigned int CUIMax = 4294967295;
+// CHECK-NEXT: (lldb) target variable CUIMax
+// CHECK-NEXT: (const unsigned int) CUIMax = 4294967295
+const unsigned int CUIMin = 0;
+// CHECK-NEXT: (lldb) target variable CUIMin
+// CHECK-NEXT: (const unsigned int) CUIMin = 0
+const long CLMax = 2147483647;
+// CHECK-NEXT: (lldb) target variable CLMax
+// CHECK-NEXT: (const long) CLMax = 2147483647
+const long CLMin = -2147483648;
+// CHECK-NEXT: (lldb) target variable CLMin
+// CHECK-NEXT: (const long) CLMin = -2147483648
+const unsigned long CULMax = 4294967295;
+// CHECK-NEXT: (lldb) target variable CULMax
+// CHECK-NEXT: (const unsigned long) CULMax = 4294967295
+const unsigned long CULMin = 0;
+// CHECK-NEXT: (lldb) target variable CULMin
+// CHECK-NEXT: (const unsigned long) CULMin = 0
+const long long CLLMax = 9223372036854775807i64;
+// CHECK-NEXT: (lldb) target variable CLLMax
+// CHECK-NEXT: (const long long) CLLMax = 9223372036854775807
+const long long CLLMin = -9223372036854775807i64 - 1;
+// CHECK-NEXT: (lldb) target variable CLLMin
+// CHECK-NEXT: (const long long) CLLMin = -9223372036854775808
+const unsigned long long CULLMax = 18446744073709551615ULL;
+// CHECK-NEXT: (lldb) target variable CULLMax
+// CHECK-NEXT: (const unsigned long long) CULLMax = 18446744073709551615
+const unsigned long long CULLMin = 0;
+// CHECK-NEXT: (lldb) target variable CULLMin
+// CHECK-NEXT: (const unsigned long long) CULLMin = 0
+const float CF = 3.1415f;
+// CHECK-NEXT: (lldb) target variable CF
+// CHECK-NEXT: (const float) CF = 3.1415
+const double CD = 3.1415;
+// CHECK-NEXT: (lldb) target variable CD
+// CHECK-NEXT: (const double) CD = 3.1415
+
+// constexpr fundamental data types.
+constexpr bool ConstexprBFalse = false;
+// CHECK-NEXT: (lldb) target variable ConstexprBFalse
+// CHECK-NEXT: (const bool) ConstexprBFalse = false
+constexpr bool ConstexprBTrue = true;
+// CHECK-NEXT: (lldb) target variable ConstexprBTrue
+// CHECK-NEXT: (const bool) ConstexprBTrue = true
+constexpr char ConstexprCA = 'A';
+// CHECK-NEXT: (lldb) target variable ConstexprCA
+// CHECK-NEXT: (const char) ConstexprCA = 'A'
+constexpr char ConstexprCZ = 'Z';
+// CHECK-NEXT: (lldb) target variable ConstexprCZ
+// CHECK-NEXT: (const char) ConstexprCZ = 'Z'
+constexpr signed char ConstexprSCa = 'a';
+// CHECK-NEXT: (lldb) target variable ConstexprSCa
+// CHECK-NEXT: (const signed char) ConstexprSCa = 'a'
+constexpr signed char ConstexprSCz = 'z';
+// CHECK-NEXT: (lldb) target variable ConstexprSCz
+// CHECK-NEXT: (const signed char) ConstexprSCz = 'z'
+constexpr unsigned char ConstexprUC24 = 24;
+// CHECK-NEXT: (lldb) target variable ConstexprUC24
+// CHECK-NEXT: (const unsigned char) ConstexprUC24 = '\x18'
+constexpr unsigned char ConstexprUC42 = 42;
+// CHECK-NEXT: (lldb) target variable ConstexprUC42
+// CHECK-NEXT: (const unsigned char) ConstexprUC42 = '*'
+constexpr char16_t ConstexprC16_24 = u'\24';
+// CHECK-NEXT: (lldb) target variable ConstexprC16_24
+// CHECK-NEXT: (const char16_t) ConstexprC16_24 = U+0014
+constexpr char32_t ConstexprC32_42 = U'\42';
+// CHECK-NEXT: (lldb) target variable ConstexprC32_42
+// CHECK-NEXT: (const char32_t) ConstexprC32_42 = U+0x00000022
+constexpr wchar_t ConstexprWC1 = L'1';
+// CHECK-NEXT: (lldb) target variable ConstexprWC1
+// CHECK-NEXT: (const wchar_t) ConstexprWC1 = L'1'
+constexpr wchar_t ConstexprWCP = L'P';
+// CHECK-NEXT: (lldb) target variable ConstexprWCP
+// CHECK-NEXT: (const wchar_t) ConstexprWCP = L'P'
+constexpr short ConstexprSMax = 32767;
+// CHECK-NEXT: (lldb) target variable ConstexprSMax
+// CHECK-NEXT: (const short) ConstexprSMax = 32767
+constexpr short ConstexprSMin = -32768;
+// CHECK-NEXT: (lldb) target variable ConstexprSMin
+// CHECK-NEXT: (const short) ConstexprSMin = -32768
+constexpr unsigned short ConstexprUSMax = 65535;
+// CHECK-NEXT: (lldb) target variable ConstexprUSMax
+// CHECK-NEXT: (const unsigned short) ConstexprUSMax = 65535
+constexpr unsigned short ConstexprUSMin = 0;
+// CHECK-NEXT: (lldb) target variable ConstexprUSMin
+// CHECK-NEXT: (const unsigned short) ConstexprUSMin = 0
+constexpr int ConstexprIMax = 2147483647;
+// CHECK-NEXT: (lldb) target variable ConstexprIMax
+// CHECK-NEXT: (const int) ConstexprIMax = 2147483647
+constexpr int ConstexprIMin = -2147483648;
+// CHECK-NEXT: (lldb) target variable ConstexprIMin
+// CHECK-NEXT: (const int) ConstexprIMin = -2147483648
+constexpr unsigned int ConstexprUIMax = 4294967295;
+// CHECK-NEXT: (lldb) target variable ConstexprUIMax
+// CHECK-NEXT: (const unsigned int) ConstexprUIMax = 4294967295
+constexpr unsigned int ConstexprUIMin = 0;
+// CHECK-NEXT: (lldb) target variable ConstexprUIMin
+// CHECK-NEXT: (const unsigned int) ConstexprUIMin = 0
+constexpr long ConstexprLMax = 2147483647;
+// CHECK-NEXT: (lldb) target variable ConstexprLMax
+// CHECK-NEXT: (const long) ConstexprLMax = 2147483647
+constexpr long ConstexprLMin = -2147483648;
+// CHECK-NEXT: (lldb) target variable ConstexprLMin
+// CHECK-NEXT: (const long) ConstexprLMin = -2147483648
+constexpr unsigned long ConstexprULMax = 4294967295;
+// CHECK-NEXT: (lldb) target variable ConstexprULMax
+// CHECK-NEXT: (const unsigned long) ConstexprULMax = 4294967295
+constexpr unsigned long ConstexprULMin = 0;
+// CHECK-NEXT: (lldb) target variable ConstexprULMin
+// CHECK-NEXT: (const unsigned long) ConstexprULMin = 0
+constexpr long long ConstexprLLMax = 9223372036854775807i64;
+// CHECK-NEXT: (lldb) target variable ConstexprLLMax
+// CHECK-NEXT: (const long long) ConstexprLLMax = 9223372036854775807
+constexpr long long ConstexprLLMin = -9223372036854775807i64 - 1;
+// CHECK-NEXT: (lldb) target variable ConstexprLLMin
+// CHECK-NEXT: (const long long) ConstexprLLMin = -9223372036854775808
+constexpr unsigned long long ConstexprULLMax = 18446744073709551615ULL;
+// CHECK-NEXT: (lldb) target variable ConstexprULLMax
+// CHECK-NEXT: (const unsigned long long) ConstexprULLMax = 18446744073709551615
+constexpr unsigned long long ConstexprULLMin = 0;
+// CHECK-NEXT: (lldb) target variable ConstexprULLMin
+// CHECK-NEXT: (const unsigned long long) ConstexprULLMin = 0
+constexpr float ConstexprF = 3.1415f;
+// CHECK-NEXT: (lldb) target variable ConstexprF
+// CHECK-NEXT: (const float) ConstexprF = 3.1415
+constexpr double ConstexprD = 3.1415;
+// CHECK-NEXT: (lldb) target variable ConstexprD
+// CHECK-NEXT: (const double) ConstexprD = 3.1415
+
+
+// FIXME: LLDB currently doesn't resolve pointers within the target without a
+// running process (I haven't checked whether or not it can with a running
+// process). So currently it will just print an address, which is unstable and
+// should not be relied upon for testing. So for now we're just checking that
+// the variable name and type is correct. We should fix this in LLDB and then
+// update the tests.
+bool *PBFalse = &BFalse;
+// CHECK-NEXT: (lldb) target variable PBFalse
+// CHECK-NEXT: (bool *) PBFalse = {{.*}}
+bool *PBTrue = &BTrue;
+// CHECK-NEXT: (lldb) target variable PBTrue
+// CHECK-NEXT: (bool *) PBTrue = {{.*}}
+char *PCA = &CA;
+// CHECK-NEXT: (lldb) target variable PCA
+// CHECK-NEXT: (char *) PCA = {{.*}}
+char *PCZ = &CZ;
+// CHECK-NEXT: (lldb) target variable PCZ
+// CHECK-NEXT: (char *) PCZ = {{.*}}
+signed char *PSCa = &SCa;
+// CHECK-NEXT: (lldb) target variable PSCa
+// CHECK-NEXT: (signed char *) PSCa = {{.*}}
+signed char *PSCz = &SCz;
+// CHECK-NEXT: (lldb) target variable PSCz
+// CHECK-NEXT: (signed char *) PSCz = {{.*}}
+unsigned char *PUC24 = &UC24;
+// CHECK-NEXT: (lldb) target variable PUC24
+// CHECK-NEXT: (unsigned char *) PUC24 = {{.*}}
+unsigned char *PUC42 = &UC42;
+// CHECK-NEXT: (lldb) target variable PUC42
+// CHECK-NEXT: (unsigned char *) PUC42 = {{.*}}
+char16_t *PC16_24 = &C16_24;
+// CHECK-NEXT: (lldb) target variable PC16_24
+// CHECK-NEXT: (char16_t *) PC16_24 = {{.*}}
+char32_t *PC32_42 = &C32_42;
+// CHECK-NEXT: (lldb) target variable PC32_42
+// CHECK-NEXT: (char32_t *) PC32_42 = {{.*}}
+wchar_t *PWC1 = &WC1;
+// CHECK-NEXT: (lldb) target variable PWC1
+// CHECK-NEXT: (wchar_t *) PWC1 = {{.*}}
+wchar_t *PWCP = &WCP;
+// CHECK-NEXT: (lldb) target variable PWCP
+// CHECK-NEXT: (wchar_t *) PWCP = {{.*}}
+short *PSMax = &SMax;
+// CHECK-NEXT: (lldb) target variable PSMax
+// CHECK-NEXT: (short *) PSMax = {{.*}}
+short *PSMin = &SMin;
+// CHECK-NEXT: (lldb) target variable PSMin
+// CHECK-NEXT: (short *) PSMin = {{.*}}
+unsigned short *PUSMax = &USMax;
+// CHECK-NEXT: (lldb) target variable PUSMax
+// CHECK-NEXT: (unsigned short *) PUSMax = {{.*}}
+unsigned short *PUSMin = &USMin;
+// CHECK-NEXT: (lldb) target variable PUSMin
+// CHECK-NEXT: (unsigned short *) PUSMin = {{.*}}
+int *PIMax = &IMax;
+// CHECK-NEXT: (lldb) target variable PIMax
+// CHECK-NEXT: (int *) PIMax = {{.*}}
+int *PIMin = &IMin;
+// CHECK-NEXT: (lldb) target variable PIMin
+// CHECK-NEXT: (int *) PIMin = {{.*}}
+unsigned int *PUIMax = &UIMax;
+// CHECK-NEXT: (lldb) target variable PUIMax
+// CHECK-NEXT: (unsigned int *) PUIMax = {{.*}}
+unsigned int *PUIMin = &UIMin;
+// CHECK-NEXT: (lldb) target variable PUIMin
+// CHECK-NEXT: (unsigned int *) PUIMin = {{.*}}
+long *PLMax = &LMax;
+// CHECK-NEXT: (lldb) target variable PLMax
+// CHECK-NEXT: (long *) PLMax = {{.*}}
+long *PLMin = &LMin;
+// CHECK-NEXT: (lldb) target variable PLMin
+// CHECK-NEXT: (long *) PLMin = {{.*}}
+unsigned long *PULMax = &ULMax;
+// CHECK-NEXT: (lldb) target variable PULMax
+// CHECK-NEXT: (unsigned long *) PULMax = {{.*}}
+unsigned long *PULMin = &ULMin;
+// CHECK-NEXT: (lldb) target variable PULMin
+// CHECK-NEXT: (unsigned long *) PULMin = {{.*}}
+long long *PLLMax = &LLMax;
+// CHECK-NEXT: (lldb) target variable PLLMax
+// CHECK-NEXT: (long long *) PLLMax = {{.*}}
+long long *PLLMin = &LLMin;
+// CHECK-NEXT: (lldb) target variable PLLMin
+// CHECK-NEXT: (long long *) PLLMin = {{.*}}
+unsigned long long *PULLMax = &ULLMax;
+// CHECK-NEXT: (lldb) target variable PULLMax
+// CHECK-NEXT: (unsigned long long *) PULLMax = {{.*}}
+unsigned long long *PULLMin = &ULLMin;
+// CHECK-NEXT: (lldb) target variable PULLMin
+// CHECK-NEXT: (unsigned long long *) PULLMin = {{.*}}
+float *PF = &F;
+// CHECK-NEXT: (lldb) target variable PF
+// CHECK-NEXT: (float *) PF = {{.*}}
+double *PD = &D;
+// CHECK-NEXT: (lldb) target variable PD
+// CHECK-NEXT: (double *) PD = {{.*}}
+
+// Const pointers to fundamental data types
+const bool *CPBFalse = &BFalse;
+// CHECK-NEXT: (lldb) target variable CPBFalse
+// CHECK-NEXT: (const bool *) CPBFalse = {{.*}}
+const bool *CPBTrue = &BTrue;
+// CHECK-NEXT: (lldb) target variable CPBTrue
+// CHECK-NEXT: (const bool *) CPBTrue = {{.*}}
+const char *CPCA = &CA;
+// CHECK-NEXT: (lldb) target variable CPCA
+// CHECK-NEXT: (const char *) CPCA = {{.*}}
+const char *CPCZ = &CZ;
+// CHECK-NEXT: (lldb) target variable CPCZ
+// CHECK-NEXT: (const char *) CPCZ = {{.*}}
+const signed char *CPSCa = &SCa;
+// CHECK-NEXT: (lldb) target variable CPSCa
+// CHECK-NEXT: (const signed char *) CPSCa = {{.*}}
+const signed char *CPSCz = &SCz;
+// CHECK-NEXT: (lldb) target variable CPSCz
+// CHECK-NEXT: (const signed char *) CPSCz = {{.*}}
+const unsigned char *CPUC24 = &UC24;
+// CHECK-NEXT: (lldb) target variable CPUC24
+// CHECK-NEXT: (const unsigned char *) CPUC24 = {{.*}}
+const unsigned char *CPUC42 = &UC42;
+// CHECK-NEXT: (lldb) target variable CPUC42
+// CHECK-NEXT: (const unsigned char *) CPUC42 = {{.*}}
+const char16_t *CPC16_24 = &C16_24;
+// CHECK-NEXT: (lldb) target variable CPC16_24
+// CHECK-NEXT: (const char16_t *) CPC16_24 = {{.*}}
+const char32_t *CPC32_42 = &C32_42;
+// CHECK-NEXT: (lldb) target variable CPC32_42
+// CHECK-NEXT: (const char32_t *) CPC32_42 = {{.*}}
+const wchar_t *CPWC1 = &WC1;
+// CHECK-NEXT: (lldb) target variable CPWC1
+// CHECK-NEXT: (const wchar_t *) CPWC1 = {{.*}}
+const wchar_t *CPWCP = &WCP;
+// CHECK-NEXT: (lldb) target variable CPWCP
+// CHECK-NEXT: (const wchar_t *) CPWCP = {{.*}}
+const short *CPSMax = &SMax;
+// CHECK-NEXT: (lldb) target variable CPSMax
+// CHECK-NEXT: (const short *) CPSMax = {{.*}}
+const short *CPSMin = &SMin;
+// CHECK-NEXT: (lldb) target variable CPSMin
+// CHECK-NEXT: (const short *) CPSMin = {{.*}}
+const unsigned short *CPUSMax = &USMax;
+// CHECK-NEXT: (lldb) target variable CPUSMax
+// CHECK-NEXT: (const unsigned short *) CPUSMax = {{.*}}
+const unsigned short *CPUSMin = &USMin;
+// CHECK-NEXT: (lldb) target variable CPUSMin
+// CHECK-NEXT: (const unsigned short *) CPUSMin = {{.*}}
+const int *CPIMax = &IMax;
+// CHECK-NEXT: (lldb) target variable CPIMax
+// CHECK-NEXT: (const int *) CPIMax = {{.*}}
+const int *CPIMin = &IMin;
+// CHECK-NEXT: (lldb) target variable CPIMin
+// CHECK-NEXT: (const int *) CPIMin = {{.*}}
+const unsigned int *CPUIMax = &UIMax;
+// CHECK-NEXT: (lldb) target variable CPUIMax
+// CHECK-NEXT: (const unsigned int *) CPUIMax = {{.*}}
+const unsigned int *CPUIMin = &UIMin;
+// CHECK-NEXT: (lldb) target variable CPUIMin
+// CHECK-NEXT: (const unsigned int *) CPUIMin = {{.*}}
+const long *CPLMax = &LMax;
+// CHECK-NEXT: (lldb) target variable CPLMax
+// CHECK-NEXT: (const long *) CPLMax = {{.*}}
+const long *CPLMin = &LMin;
+// CHECK-NEXT: (lldb) target variable CPLMin
+// CHECK-NEXT: (const long *) CPLMin = {{.*}}
+const unsigned long *CPULMax = &ULMax;
+// CHECK-NEXT: (lldb) target variable CPULMax
+// CHECK-NEXT: (const unsigned long *) CPULMax = {{.*}}
+const unsigned long *CPULMin = &ULMin;
+// CHECK-NEXT: (lldb) target variable CPULMin
+// CHECK-NEXT: (const unsigned long *) CPULMin = {{.*}}
+const long long *CPLLMax = &LLMax;
+// CHECK-NEXT: (lldb) target variable CPLLMax
+// CHECK-NEXT: (const long long *) CPLLMax = {{.*}}
+const long long *CPLLMin = &LLMin;
+// CHECK-NEXT: (lldb) target variable CPLLMin
+// CHECK-NEXT: (const long long *) CPLLMin = {{.*}}
+const unsigned long long *CPULLMax = &ULLMax;
+// CHECK-NEXT: (lldb) target variable CPULLMax
+// CHECK-NEXT: (const unsigned long long *) CPULLMax = {{.*}}
+const unsigned long long *CPULLMin = &ULLMin;
+// CHECK-NEXT: (lldb) target variable CPULLMin
+// CHECK-NEXT: (const unsigned long long *) CPULLMin = {{.*}}
+const float *CPF = &F;
+// CHECK-NEXT: (lldb) target variable CPF
+// CHECK-NEXT: (const float *) CPF = {{.*}}
+const double *CPD = &D;
+// CHECK-NEXT: (lldb) target variable CPD
+// CHECK-NEXT: (const double *) CPD = {{.*}}
+
+
+// References to fundamental data types
+
+bool &RBFalse = BFalse;
+// CHECK-NEXT: (lldb) target variable RBFalse
+// CHECK-NEXT: (bool &) RBFalse = {{.*}} (&::RBFalse = false)
+bool &RBTrue = BTrue;
+// CHECK-NEXT: (lldb) target variable RBTrue
+// CHECK-NEXT: (bool &) RBTrue = {{.*}} (&::RBTrue = true)
+char &RCA = CA;
+// CHECK-NEXT: (lldb) target variable RCA
+// CHECK-NEXT: (char &) RCA = {{.*}} (&::RCA = 'A')
+char &RCZ = CZ;
+// CHECK-NEXT: (lldb) target variable RCZ
+// CHECK-NEXT: (char &) RCZ = {{.*}} (&::RCZ = 'Z')
+signed char &RSCa = SCa;
+// CHECK-NEXT: (lldb) target variable RSCa
+// CHECK-NEXT: (signed char &) RSCa = {{.*}} (&::RSCa = 'a')
+signed char &RSCz = SCz;
+// CHECK-NEXT: (lldb) target variable RSCz
+// CHECK-NEXT: (signed char &) RSCz = {{.*}} (&::RSCz = 'z')
+unsigned char &RUC24 = UC24;
+// CHECK-NEXT: (lldb) target variable RUC24
+// CHECK-NEXT: (unsigned char &) RUC24 = {{.*}} (&::RUC24 = '\x18')
+unsigned char &RUC42 = UC42;
+// CHECK-NEXT: (lldb) target variable RUC42
+// CHECK-NEXT: (unsigned char &) RUC42 = {{.*}} (&::RUC42 = '*')
+short &RSMax = SMax;
+// CHECK-NEXT: (lldb) target variable RSMax
+// CHECK-NEXT: (short &) RSMax = {{.*}} (&::RSMax = 32767)
+short &RSMin = SMin;
+// CHECK-NEXT: (lldb) target variable RSMin
+// CHECK-NEXT: (short &) RSMin = {{.*}} (&::RSMin = -32768)
+unsigned short &RUSMax = USMax;
+// CHECK-NEXT: (lldb) target variable RUSMax
+// CHECK-NEXT: (unsigned short &) RUSMax = {{.*}} (&::RUSMax = 65535)
+unsigned short &RUSMin = USMin;
+// CHECK-NEXT: (lldb) target variable RUSMin
+// CHECK-NEXT: (unsigned short &) RUSMin = {{.*}} (&::RUSMin = 0)
+int &RIMax = IMax;
+// CHECK-NEXT: (lldb) target variable RIMax
+// CHECK-NEXT: (int &) RIMax = {{.*}} (&::RIMax = 2147483647)
+int &RIMin = IMin;
+// CHECK-NEXT: (lldb) target variable RIMin
+// CHECK-NEXT: (int &) RIMin = {{.*}} (&::RIMin = -2147483648)
+unsigned int &RUIMax = UIMax;
+// CHECK-NEXT: (lldb) target variable RUIMax
+// CHECK-NEXT: (unsigned int &) RUIMax = {{.*}} (&::RUIMax = 4294967295)
+unsigned int &RUIMin = UIMin;
+// CHECK-NEXT: (lldb) target variable RUIMin
+// CHECK-NEXT: (unsigned int &) RUIMin = {{.*}} (&::RUIMin = 0)
+long &RLMax = LMax;
+// CHECK-NEXT: (lldb) target variable RLMax
+// CHECK-NEXT: (long &) RLMax = {{.*}} (&::RLMax = 2147483647)
+long &RLMin = LMin;
+// CHECK-NEXT: (lldb) target variable RLMin
+// CHECK-NEXT: (long &) RLMin = {{.*}} (&::RLMin = -2147483648)
+unsigned long &RULMax = ULMax;
+// CHECK-NEXT: (lldb) target variable RULMax
+// CHECK-NEXT: (unsigned long &) RULMax = {{.*}} (&::RULMax = 4294967295)
+unsigned long &RULMin = ULMin;
+// CHECK-NEXT: (lldb) target variable RULMin
+// CHECK-NEXT: (unsigned long &) RULMin = {{.*}} (&::RULMin = 0)
+long long &RLLMax = LLMax;
+// CHECK-NEXT: (lldb) target variable RLLMax
+// CHECK-NEXT: (long long &) RLLMax = {{.*}} (&::RLLMax = 9223372036854775807)
+long long &RLLMin = LLMin;
+// CHECK-NEXT: (lldb) target variable RLLMin
+// CHECK-NEXT: (long long &) RLLMin = {{.*}} (&::RLLMin = -9223372036854775808)
+unsigned long long &RULLMax = ULLMax;
+// CHECK-NEXT: (lldb) target variable RULLMax
+// CHECK-NEXT: (unsigned long long &) RULLMax = {{.*}} (&::RULLMax = 18446744073709551615)
+unsigned long long &RULLMin = ULLMin;
+// CHECK-NEXT: (lldb) target variable RULLMin
+// CHECK-NEXT: (unsigned long long &) RULLMin = {{.*}} (&::RULLMin = 0)
+float &RF = F;
+// CHECK-NEXT: (lldb) target variable RF
+// CHECK-NEXT: (float &) RF = {{.*}} (&::RF = 3.1415)
+double &RD = D;
+// CHECK-NEXT: (lldb) target variable RD
+// CHECK-NEXT: (double &) RD = {{.*}} (&::RD = 3.1415000000000002)
+
+// const references to fundamental data types
+const bool &CRBFalse = BFalse;
+// CHECK-NEXT: (lldb) target variable CRBFalse
+// CHECK-NEXT: (const bool &) CRBFalse = {{.*}} (&::CRBFalse = false)
+const bool &CRBTrue = BTrue;
+// CHECK-NEXT: (lldb) target variable CRBTrue
+// CHECK-NEXT: (const bool &) CRBTrue = {{.*}} (&::CRBTrue = true)
+const char &CRCA = CA;
+// CHECK-NEXT: (lldb) target variable CRCA
+// CHECK-NEXT: (const char &) CRCA = {{.*}} (&::CRCA = 'A')
+const char &CRCZ = CZ;
+// CHECK-NEXT: (lldb) target variable CRCZ
+// CHECK-NEXT: (const char &) CRCZ = {{.*}} (&::CRCZ = 'Z')
+const signed char &CRSCa = SCa;
+// CHECK-NEXT: (lldb) target variable CRSCa
+// CHECK-NEXT: (const signed char &) CRSCa = {{.*}} (&::CRSCa = 'a')
+const signed char &CRSCz = SCz;
+// CHECK-NEXT: (lldb) target variable CRSCz
+// CHECK-NEXT: (const signed char &) CRSCz = {{.*}} (&::CRSCz = 'z')
+const unsigned char &CRUC24 = UC24;
+// CHECK-NEXT: (lldb) target variable CRUC24
+// CHECK-NEXT: (const unsigned char &) CRUC24 = {{.*}} (&::CRUC24 = '\x18')
+const unsigned char &CRUC42 = UC42;
+// CHECK-NEXT: (lldb) target variable CRUC42
+// CHECK-NEXT: (const unsigned char &) CRUC42 = {{.*}} (&::CRUC42 = '*')
+const short &CRSMax = SMax;
+// CHECK-NEXT: (lldb) target variable CRSMax
+// CHECK-NEXT: (const short &) CRSMax = {{.*}} (&::CRSMax = 32767)
+const short &CRSMin = SMin;
+// CHECK-NEXT: (lldb) target variable CRSMin
+// CHECK-NEXT: (const short &) CRSMin = {{.*}} (&::CRSMin = -32768)
+const unsigned short &CRUSMax = USMax;
+// CHECK-NEXT: (lldb) target variable CRUSMax
+// CHECK-NEXT: (const unsigned short &) CRUSMax = {{.*}} (&::CRUSMax = 65535)
+const unsigned short &CRUSMin = USMin;
+// CHECK-NEXT: (lldb) target variable CRUSMin
+// CHECK-NEXT: (const unsigned short &) CRUSMin = {{.*}} (&::CRUSMin = 0)
+const int &CRIMax = IMax;
+// CHECK-NEXT: (lldb) target variable CRIMax
+// CHECK-NEXT: (const int &) CRIMax = {{.*}} (&::CRIMax = 2147483647)
+const int &CRIMin = IMin;
+// CHECK-NEXT: (lldb) target variable CRIMin
+// CHECK-NEXT: (const int &) CRIMin = {{.*}} (&::CRIMin = -2147483648)
+const unsigned int &CRUIMax = UIMax;
+// CHECK-NEXT: (lldb) target variable CRUIMax
+// CHECK-NEXT: (const unsigned int &) CRUIMax = {{.*}} (&::CRUIMax = 4294967295)
+const unsigned int &CRUIMin = UIMin;
+// CHECK-NEXT: (lldb) target variable CRUIMin
+// CHECK-NEXT: (const unsigned int &) CRUIMin = {{.*}} (&::CRUIMin = 0)
+const long &CRLMax = LMax;
+// CHECK-NEXT: (lldb) target variable CRLMax
+// CHECK-NEXT: (const long &) CRLMax = {{.*}} (&::CRLMax = 2147483647)
+const long &CRLMin = LMin;
+// CHECK-NEXT: (lldb) target variable CRLMin
+// CHECK-NEXT: (const long &) CRLMin = {{.*}} (&::CRLMin = -2147483648)
+const unsigned long &CRULMax = ULMax;
+// CHECK-NEXT: (lldb) target variable CRULMax
+// CHECK-NEXT: (const unsigned long &) CRULMax = {{.*}} (&::CRULMax = 4294967295)
+const unsigned long &CRULMin = ULMin;
+// CHECK-NEXT: (lldb) target variable CRULMin
+// CHECK-NEXT: (const unsigned long &) CRULMin = {{.*}} (&::CRULMin = 0)
+const long long &CRLLMax = LLMax;
+// CHECK-NEXT: (lldb) target variable CRLLMax
+// CHECK-NEXT: (const long long &) CRLLMax = {{.*}} (&::CRLLMax = 9223372036854775807)
+const long long &CRLLMin = LLMin;
+// CHECK-NEXT: (lldb) target variable CRLLMin
+// CHECK-NEXT: (const long long &) CRLLMin = {{.*}} (&::CRLLMin = -9223372036854775808)
+const unsigned long long &CRULLMax = ULLMax;
+// CHECK-NEXT: (lldb) target variable CRULLMax
+// CHECK-NEXT: (const unsigned long long &) CRULLMax = {{.*}} (&::CRULLMax = 18446744073709551615)
+const unsigned long long &CRULLMin = ULLMin;
+// CHECK-NEXT: (lldb) target variable CRULLMin
+// CHECK-NEXT: (const unsigned long long &) CRULLMin = {{.*}} (&::CRULLMin = 0)
+const float &CRF = F;
+// CHECK-NEXT: (lldb) target variable CRF
+// CHECK-NEXT: (const float &) CRF = {{.*}} (&::CRF = 3.1415)
+const double &CRD = D;
+// CHECK-NEXT: (lldb) target variable CRD
+// CHECK-NEXT: (const double &) CRD = {{.*}} (&::CRD = 3.1415000000000002)
+
+char16_t &RC16_24 = C16_24;
+// CHECK: (lldb) target variable RC16_24
+// FIXME: (char16_t &) RC16_24 = {{.*}} (&::RC16_24 = U+0014)
+char32_t &RC32_42 = C32_42;
+// CHECK: (lldb) target variable RC32_42
+// FIXME: (char32_t &) RC32_42 = {{.*}} (&::RC32_42 = U+0x00000022)
+wchar_t &RWC1 = WC1;
+// CHECK: (lldb) target variable RWC1
+// FIXME: (wchar_t &) RWC1 = {{.*}} (&::RWC1 = L'1')
+wchar_t &RWCP = WCP;
+// CHECK: (lldb) target variable RWCP
+// FIXME: (wchar_t &) RWCP = {{.*}} (&::RWCP = L'P')
+const char16_t &CRC16_24 = C16_24;
+// CHECK: (lldb) target variable CRC16_24
+// FIXME: (const char16_t &) CRC16_24 = {{.*}} (&::CRC16_24 = U+0014)
+const char32_t &CRC32_42 = C32_42;
+// CHECK: (lldb) target variable CRC32_42
+// FIXME: (const char32_t &) CRC32_42 = {{.*}} (&::CRC32_42 = U+0x00000022)
+const wchar_t &CRWC1 = WC1;
+// CHECK: (lldb) target variable CRWC1
+// FIXME: (const wchar_t &) CRWC1 = {{.*}} (&::CRWC1 = L'1')
+const wchar_t &CRWCP = WCP;
+// CHECK: (lldb) target variable CRWCP
+// FIXME: (const wchar_t &) CRWCP = {{.*}} (&::CRWCP = L'P')
+
+
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK-NEXT: |-VarDecl {{.*}} BFalse 'bool'
+// CHECK-NEXT: |-VarDecl {{.*}} BTrue 'bool'
+// CHECK-NEXT: |-VarDecl {{.*}} CA 'char'
+// CHECK-NEXT: |-VarDecl {{.*}} CZ 'char'
+// CHECK-NEXT: |-VarDecl {{.*}} SCa 'signed char'
+// CHECK-NEXT: |-VarDecl {{.*}} SCz 'signed char'
+// CHECK-NEXT: |-VarDecl {{.*}} UC24 'unsigned char'
+// CHECK-NEXT: |-VarDecl {{.*}} UC42 'unsigned char'
+// CHECK-NEXT: |-VarDecl {{.*}} C16_24 'char16_t'
+// CHECK-NEXT: |-VarDecl {{.*}} C32_42 'char32_t'
+// CHECK-NEXT: |-VarDecl {{.*}} WC1 'wchar_t'
+// CHECK-NEXT: |-VarDecl {{.*}} WCP 'wchar_t'
+// CHECK-NEXT: |-VarDecl {{.*}} SMax 'short'
+// CHECK-NEXT: |-VarDecl {{.*}} SMin 'short'
+// CHECK-NEXT: |-VarDecl {{.*}} USMax 'unsigned short'
+// CHECK-NEXT: |-VarDecl {{.*}} USMin 'unsigned short'
+// CHECK-NEXT: |-VarDecl {{.*}} IMax 'int'
+// CHECK-NEXT: |-VarDecl {{.*}} IMin 'int'
+// CHECK-NEXT: |-VarDecl {{.*}} UIMax 'unsigned int'
+// CHECK-NEXT: |-VarDecl {{.*}} UIMin 'unsigned int'
+// CHECK-NEXT: |-VarDecl {{.*}} LMax 'long'
+// CHECK-NEXT: |-VarDecl {{.*}} LMin 'long'
+// CHECK-NEXT: |-VarDecl {{.*}} ULMax 'unsigned long'
+// CHECK-NEXT: |-VarDecl {{.*}} ULMin 'unsigned long'
+// CHECK-NEXT: |-VarDecl {{.*}} LLMax 'long long'
+// CHECK-NEXT: |-VarDecl {{.*}} LLMin 'long long'
+// CHECK-NEXT: |-VarDecl {{.*}} ULLMax 'unsigned long long'
+// CHECK-NEXT: |-VarDecl {{.*}} ULLMin 'unsigned long long'
+// CHECK-NEXT: |-VarDecl {{.*}} F 'float'
+// CHECK-NEXT: |-VarDecl {{.*}} D 'double'
+// CHECK-NEXT: |-VarDecl {{.*}} CBFalse 'const bool'
+// CHECK-NEXT: |-VarDecl {{.*}} CBTrue 'const bool'
+// CHECK-NEXT: |-VarDecl {{.*}} CCA 'const char'
+// CHECK-NEXT: |-VarDecl {{.*}} CCZ 'const char'
+// CHECK-NEXT: |-VarDecl {{.*}} CSCa 'const signed char'
+// CHECK-NEXT: |-VarDecl {{.*}} CSCz 'const signed char'
+// CHECK-NEXT: |-VarDecl {{.*}} CUC24 'const unsigned char'
+// CHECK-NEXT: |-VarDecl {{.*}} CUC42 'const unsigned char'
+// CHECK-NEXT: |-VarDecl {{.*}} CC16_24 'const char16_t'
+// CHECK-NEXT: |-VarDecl {{.*}} CC32_42 'const char32_t'
+// CHECK-NEXT: |-VarDecl {{.*}} CWC1 'const wchar_t'
+// CHECK-NEXT: |-VarDecl {{.*}} CWCP 'const wchar_t'
+// CHECK-NEXT: |-VarDecl {{.*}} CSMax 'const short'
+// CHECK-NEXT: |-VarDecl {{.*}} CSMin 'const short'
+// CHECK-NEXT: |-VarDecl {{.*}} CUSMax 'const unsigned short'
+// CHECK-NEXT: |-VarDecl {{.*}} CUSMin 'const unsigned short'
+// CHECK-NEXT: |-VarDecl {{.*}} CIMax 'const int'
+// CHECK-NEXT: |-VarDecl {{.*}} CIMin 'const int'
+// CHECK-NEXT: |-VarDecl {{.*}} CUIMax 'const unsigned int'
+// CHECK-NEXT: |-VarDecl {{.*}} CUIMin 'const unsigned int'
+// CHECK-NEXT: |-VarDecl {{.*}} CLMax 'const long'
+// CHECK-NEXT: |-VarDecl {{.*}} CLMin 'const long'
+// CHECK-NEXT: |-VarDecl {{.*}} CULMax 'const unsigned long'
+// CHECK-NEXT: |-VarDecl {{.*}} CULMin 'const unsigned long'
+// CHECK-NEXT: |-VarDecl {{.*}} CLLMax 'const long long'
+// CHECK-NEXT: |-VarDecl {{.*}} CLLMin 'const long long'
+// CHECK-NEXT: |-VarDecl {{.*}} CULLMax 'const unsigned long long'
+// CHECK-NEXT: |-VarDecl {{.*}} CULLMin 'const unsigned long long'
+// CHECK-NEXT: |-VarDecl {{.*}} CF 'const float'
+// CHECK-NEXT: |-VarDecl {{.*}} CD 'const double'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprBFalse 'const bool'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprBTrue 'const bool'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprCA 'const char'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprCZ 'const char'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprSCa 'const signed char'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprSCz 'const signed char'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUC24 'const unsigned char'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUC42 'const unsigned char'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprC16_24 'const char16_t'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprC32_42 'const char32_t'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprWC1 'const wchar_t'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprWCP 'const wchar_t'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprSMax 'const short'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprSMin 'const short'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUSMax 'const unsigned short'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUSMin 'const unsigned short'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprIMax 'const int'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprIMin 'const int'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUIMax 'const unsigned int'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprUIMin 'const unsigned int'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprLMax 'const long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprLMin 'const long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprULMax 'const unsigned long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprULMin 'const unsigned long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprLLMax 'const long long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprLLMin 'const long long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprULLMax 'const unsigned long long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprULLMin 'const unsigned long long'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprF 'const float'
+// CHECK-NEXT: |-VarDecl {{.*}} ConstexprD 'const double'
+// CHECK-NEXT: |-VarDecl {{.*}} PBFalse 'bool *'
+// CHECK-NEXT: |-VarDecl {{.*}} PBTrue 'bool *'
+// CHECK-NEXT: |-VarDecl {{.*}} PCA 'char *'
+// CHECK-NEXT: |-VarDecl {{.*}} PCZ 'char *'
+// CHECK-NEXT: |-VarDecl {{.*}} PSCa 'signed char *'
+// CHECK-NEXT: |-VarDecl {{.*}} PSCz 'signed char *'
+// CHECK-NEXT: |-VarDecl {{.*}} PUC24 'unsigned char *'
+// CHECK-NEXT: |-VarDecl {{.*}} PUC42 'unsigned char *'
+// CHECK-NEXT: |-VarDecl {{.*}} PC16_24 'char16_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} PC32_42 'char32_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} PWC1 'wchar_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} PWCP 'wchar_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} PSMax 'short *'
+// CHECK-NEXT: |-VarDecl {{.*}} PSMin 'short *'
+// CHECK-NEXT: |-VarDecl {{.*}} PUSMax 'unsigned short *'
+// CHECK-NEXT: |-VarDecl {{.*}} PUSMin 'unsigned short *'
+// CHECK-NEXT: |-VarDecl {{.*}} PIMax 'int *'
+// CHECK-NEXT: |-VarDecl {{.*}} PIMin 'int *'
+// CHECK-NEXT: |-VarDecl {{.*}} PUIMax 'unsigned int *'
+// CHECK-NEXT: |-VarDecl {{.*}} PUIMin 'unsigned int *'
+// CHECK-NEXT: |-VarDecl {{.*}} PLMax 'long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PLMin 'long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PULMax 'unsigned long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PULMin 'unsigned long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PLLMax 'long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PLLMin 'long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PULLMax 'unsigned long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PULLMin 'unsigned long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} PF 'float *'
+// CHECK-NEXT: |-VarDecl {{.*}} PD 'double *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPBFalse 'const bool *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPBTrue 'const bool *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPCA 'const char *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPCZ 'const char *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPSCa 'const signed char *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPSCz 'const signed char *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPUC24 'const unsigned char *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPUC42 'const unsigned char *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPC16_24 'const char16_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPC32_42 'const char32_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPWC1 'const wchar_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPWCP 'const wchar_t *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPSMax 'const short *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPSMin 'const short *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPUSMax 'const unsigned short *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPUSMin 'const unsigned short *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPIMax 'const int *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPIMin 'const int *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPUIMax 'const unsigned int *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPUIMin 'const unsigned int *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPLMax 'const long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPLMin 'const long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPULMax 'const unsigned long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPULMin 'const unsigned long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPLLMax 'const long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPLLMin 'const long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPULLMax 'const unsigned long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPULLMin 'const unsigned long long *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPF 'const float *'
+// CHECK-NEXT: |-VarDecl {{.*}} CPD 'const double *'
+// CHECK-NEXT: |-VarDecl {{.*}} RBFalse 'bool &'
+// CHECK-NEXT: |-VarDecl {{.*}} RBTrue 'bool &'
+// CHECK-NEXT: |-VarDecl {{.*}} RCA 'char &'
+// CHECK-NEXT: |-VarDecl {{.*}} RCZ 'char &'
+// CHECK-NEXT: |-VarDecl {{.*}} RSCa 'signed char &'
+// CHECK-NEXT: |-VarDecl {{.*}} RSCz 'signed char &'
+// CHECK-NEXT: |-VarDecl {{.*}} RUC24 'unsigned char &'
+// CHECK-NEXT: |-VarDecl {{.*}} RUC42 'unsigned char &'
+// CHECK-NEXT: |-VarDecl {{.*}} RSMax 'short &'
+// CHECK-NEXT: |-VarDecl {{.*}} RSMin 'short &'
+// CHECK-NEXT: |-VarDecl {{.*}} RUSMax 'unsigned short &'
+// CHECK-NEXT: |-VarDecl {{.*}} RUSMin 'unsigned short &'
+// CHECK-NEXT: |-VarDecl {{.*}} RIMax 'int &'
+// CHECK-NEXT: |-VarDecl {{.*}} RIMin 'int &'
+// CHECK-NEXT: |-VarDecl {{.*}} RUIMax 'unsigned int &'
+// CHECK-NEXT: |-VarDecl {{.*}} RUIMin 'unsigned int &'
+// CHECK-NEXT: |-VarDecl {{.*}} RLMax 'long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RLMin 'long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RULMax 'unsigned long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RULMin 'unsigned long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RLLMax 'long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RLLMin 'long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RULLMax 'unsigned long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RULLMin 'unsigned long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} RF 'float &'
+// CHECK-NEXT: |-VarDecl {{.*}} RD 'double &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRBFalse 'const bool &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRBTrue 'const bool &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRCA 'const char &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRCZ 'const char &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRSCa 'const signed char &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRSCz 'const signed char &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRUC24 'const unsigned char &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRUC42 'const unsigned char &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRSMax 'const short &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRSMin 'const short &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRUSMax 'const unsigned short &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRUSMin 'const unsigned short &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRIMax 'const int &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRIMin 'const int &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRUIMax 'const unsigned int &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRUIMin 'const unsigned int &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRLMax 'const long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRLMin 'const long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRULMax 'const unsigned long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRULMin 'const unsigned long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRLLMax 'const long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRLLMin 'const long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRULLMax 'const unsigned long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRULLMin 'const unsigned long long &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRF 'const float &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRD 'const double &'
+// CHECK-NEXT: |-VarDecl {{.*}} RC16_24 'char16_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} RC32_42 'char32_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} RWC1 'wchar_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} RWCP 'wchar_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRC16_24 'const char16_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRC32_42 'const char32_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRWC1 'const wchar_t &'
+// CHECK-NEXT: |-VarDecl {{.*}} CRWCP 'const wchar_t &'
+// CHECK-NEXT: `-<undeserialized declarations>
+
+// CHECK: (lldb) quit
+
+int main(int argc, char **argv) {
+ return CIMax;
+}
diff --git a/lit/SymbolFile/NativePDB/local-variables.cpp b/lit/SymbolFile/NativePDB/local-variables.cpp
new file mode 100644
index 000000000000..5886153a27d0
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/local-variables.cpp
@@ -0,0 +1,161 @@
+// clang-format off
+
+// REQUIRES: system-windows
+// RUN: %build -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/local-variables.lldbinit 2>&1 | FileCheck %s
+
+int Function(int Param1, char Param2) {
+ unsigned Local1 = Param1 + 1;
+ char Local2 = Param2 + 1;
+ ++Local1;
+ ++Local2;
+ return Local1;
+}
+
+int main(int argc, char **argv) {
+ int SomeLocal = argc * 2;
+ return Function(SomeLocal, 'a');
+}
+
+// CHECK: (lldb) target create "{{.*}}local-variables.cpp.tmp.exe"
+// CHECK-NEXT: Current executable set to '{{.*}}local-variables.cpp.tmp.exe'
+// CHECK-NEXT: (lldb) command source -s 0 '{{.*}}local-variables.lldbinit'
+// CHECK-NEXT: Executing commands in '{{.*}}local-variables.lldbinit'.
+// CHECK-NEXT: (lldb) break set -n main
+// CHECK-NEXT: Breakpoint 1: where = local-variables.cpp.tmp.exe`main + {{.*}} at local-variables.cpp:{{.*}}, address = {{.*}}
+// CHECK-NEXT: (lldb) run a b c d e f g
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`main(argc=8, argv={{.*}}) at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 14 }
+// CHECK-NEXT: 15
+// CHECK-NEXT: 16 int main(int argc, char **argv) {
+// CHECK-NEXT: -> 17 int SomeLocal = argc * 2;
+// CHECK-NEXT: 18 return Function(SomeLocal, 'a');
+// CHECK-NEXT: 19 }
+// CHECK-NEXT: 20
+
+// CHECK: Process {{.*}} launched: '{{.*}}local-variables.cpp.tmp.exe'
+// CHECK-NEXT: (lldb) p argc
+// CHECK-NEXT: (int) $0 = 8
+// CHECK-NEXT: (lldb) step
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = step in
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`main(argc=8, argv={{.*}}) at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 15
+// CHECK-NEXT: 16 int main(int argc, char **argv) {
+// CHECK-NEXT: 17 int SomeLocal = argc * 2;
+// CHECK-NEXT: -> 18 return Function(SomeLocal, 'a');
+// CHECK-NEXT: 19 }
+// CHECK-NEXT: 20
+
+// CHECK: (lldb) p SomeLocal
+// CHECK-NEXT: (int) $1 = 16
+// CHECK-NEXT: (lldb) step
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = step in
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 6
+// CHECK-NEXT: 7
+// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
+// CHECK-NEXT: -> 9 unsigned Local1 = Param1 + 1;
+// CHECK-NEXT: 10 char Local2 = Param2 + 1;
+// CHECK-NEXT: 11 ++Local1;
+// CHECK-NEXT: 12 ++Local2;
+
+// CHECK: (lldb) p Param1
+// CHECK-NEXT: (int) $2 = 16
+// CHECK-NEXT: (lldb) p Param2
+// CHECK-NEXT: (char) $3 = 'a'
+// CHECK-NEXT: (lldb) step
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = step in
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 7
+// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
+// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
+// CHECK-NEXT: -> 10 char Local2 = Param2 + 1;
+// CHECK-NEXT: 11 ++Local1;
+// CHECK-NEXT: 12 ++Local2;
+// CHECK-NEXT: 13 return Local1;
+
+// CHECK: (lldb) p Param1
+// CHECK-NEXT: (int) $4 = 16
+// CHECK-NEXT: (lldb) p Param2
+// CHECK-NEXT: (char) $5 = 'a'
+// CHECK-NEXT: (lldb) p Local1
+// CHECK-NEXT: (unsigned int) $6 = 17
+// CHECK-NEXT: (lldb) step
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = step in
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
+// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
+// CHECK-NEXT: 10 char Local2 = Param2 + 1;
+// CHECK-NEXT: -> 11 ++Local1;
+// CHECK-NEXT: 12 ++Local2;
+// CHECK-NEXT: 13 return Local1;
+// CHECK-NEXT: 14 }
+
+// CHECK: (lldb) p Param1
+// CHECK-NEXT: (int) $7 = 16
+// CHECK-NEXT: (lldb) p Param2
+// CHECK-NEXT: (char) $8 = 'a'
+// CHECK-NEXT: (lldb) p Local1
+// CHECK-NEXT: (unsigned int) $9 = 17
+// CHECK-NEXT: (lldb) p Local2
+// CHECK-NEXT: (char) $10 = 'b'
+// CHECK-NEXT: (lldb) step
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = step in
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
+// CHECK-NEXT: 10 char Local2 = Param2 + 1;
+// CHECK-NEXT: 11 ++Local1;
+// CHECK-NEXT: -> 12 ++Local2;
+// CHECK-NEXT: 13 return Local1;
+// CHECK-NEXT: 14 }
+// CHECK-NEXT: 15
+
+// CHECK: (lldb) p Param1
+// CHECK-NEXT: (int) $11 = 16
+// CHECK-NEXT: (lldb) p Param2
+// CHECK-NEXT: (char) $12 = 'a'
+// CHECK-NEXT: (lldb) p Local1
+// CHECK-NEXT: (unsigned int) $13 = 18
+// CHECK-NEXT: (lldb) p Local2
+// CHECK-NEXT: (char) $14 = 'b'
+// CHECK-NEXT: (lldb) step
+// CHECK-NEXT: Process {{.*}} stopped
+// CHECK-NEXT: * thread #1, stop reason = step in
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: 10 char Local2 = Param2 + 1;
+// CHECK-NEXT: 11 ++Local1;
+// CHECK-NEXT: 12 ++Local2;
+// CHECK-NEXT: -> 13 return Local1;
+// CHECK-NEXT: 14 }
+// CHECK-NEXT: 15
+// CHECK-NEXT: 16 int main(int argc, char **argv) {
+
+// CHECK: (lldb) p Param1
+// CHECK-NEXT: (int) $15 = 16
+// CHECK-NEXT: (lldb) p Param2
+// CHECK-NEXT: (char) $16 = 'a'
+// CHECK-NEXT: (lldb) p Local1
+// CHECK-NEXT: (unsigned int) $17 = 18
+// CHECK-NEXT: (lldb) p Local2
+// CHECK-NEXT: (char) $18 = 'c'
+// CHECK-NEXT: (lldb) continue
+// CHECK-NEXT: Process {{.*}} resuming
+// CHECK-NEXT: Process {{.*}} exited with status = 18 (0x00000012)
+
+// CHECK: (lldb) target modules dump ast
+// CHECK-NEXT: Dumping clang ast for {{.*}} modules.
+// CHECK-NEXT: TranslationUnitDecl
+// CHECK-NEXT: |-FunctionDecl {{.*}} main 'int (int, char **)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} argc 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} argv 'char **'
+// CHECK-NEXT: |-FunctionDecl {{.*}} Function 'int (int, char)'
+// CHECK-NEXT: | |-ParmVarDecl {{.*}} Param1 'int'
+// CHECK-NEXT: | `-ParmVarDecl {{.*}} Param2 'char'
diff --git a/lit/SymbolFile/NativePDB/nested-types.cpp b/lit/SymbolFile/NativePDB/nested-types.cpp
new file mode 100644
index 000000000000..e9bee690d301
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/nested-types.cpp
@@ -0,0 +1,153 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test various interesting cases for AST reconstruction.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/nested-types.lldbinit 2>&1 | FileCheck %s
+
+struct S {
+ struct NestedStruct {
+ int A = 0;
+ int B = 1;
+ };
+
+ enum class NestedEnum {
+ EnumValue1 = 0,
+ EnumValue2 = 1,
+ };
+ int C = 2;
+ int D = 3;
+ using VoidPtrT = void *;
+ VoidPtrT DD = nullptr;
+};
+struct T {
+ using NestedTypedef = int;
+ using NestedTypedef2 = S;
+
+ struct NestedStruct {
+ int E = 4;
+ int F = 5;
+ };
+
+ using NestedStructAlias = NestedStruct;
+ using NST = S::NestedStruct;
+
+ NestedTypedef NT = 4;
+
+ using U = struct {
+ int G = 6;
+ int H = 7;
+ };
+};
+
+template<typename Param>
+class U {
+public:
+ // See llvm.org/pr39607. clang-cl currently doesn't emit an important debug
+ // info record for nested template instantiations, so we can't reconstruct
+ // a proper DeclContext hierarchy for these. As such, U<X>::V<Y> will show up
+ // in the global namespace.
+ template<typename Param>
+ struct V {
+ Param I = 8;
+ Param J = 9;
+
+ using W = T::NestedTypedef;
+ using X = U<int>;
+ };
+
+ struct W {
+ Param M = 12;
+ Param N = 13;
+ };
+ Param K = 10;
+ Param L = 11;
+ using Y = V<int>;
+ using Z = V<T>;
+};
+
+constexpr S GlobalA;
+constexpr S::NestedStruct GlobalB;
+constexpr T GlobalC;
+constexpr T::NestedStruct GlobalD;
+constexpr T::U GlobalE;
+constexpr U<int> GlobalF;
+constexpr U<int>::V<int> GlobalG;
+constexpr U<int>::W GlobalH;
+constexpr S::NestedEnum GlobalEnum = S::NestedEnum::EnumValue1;
+
+
+int main(int argc, char **argv) {
+ return 0;
+}
+
+
+
+// CHECK: (lldb) target variable -T GlobalA
+// CHECK: (const S) GlobalA = {
+// CHECK: (int) C = 2
+// CHECK: (int) D = 3
+// CHECK: (void *) DD = 0x00000000
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalB
+// CHECK: (const S::NestedStruct) GlobalB = {
+// CHECK: (int) A = 0
+// CHECK: (int) B = 1
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalC
+// CHECK: (const T) GlobalC = {
+// CHECK: (int) NT = 4
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalD
+// CHECK: (const T::NestedStruct) GlobalD = {
+// CHECK: (int) E = 4
+// CHECK: (int) F = 5
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalE
+// CHECK: (const T::U) GlobalE = {
+// CHECK: (int) G = 6
+// CHECK: (int) H = 7
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalF
+// CHECK: (const U<int>) GlobalF = {
+// CHECK: (int) K = 10
+// CHECK: (int) L = 11
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalG
+// CHECK: (const U<int>::V<int>) GlobalG = {
+// CHECK: (int) I = 8
+// CHECK: (int) J = 9
+// CHECK: }
+// CHECK: (lldb) target variable -T GlobalEnum
+// CHECK: (const S::NestedEnum) GlobalEnum = EnumValue1
+// CHECK: (lldb) target modules dump ast
+// CHECK: Dumping clang ast for 1 modules.
+// CHECK: TranslationUnitDecl {{.*}}
+// CHECK: |-CXXRecordDecl {{.*}} struct S definition
+// CHECK: | |-FieldDecl {{.*}} C 'int'
+// CHECK: | |-FieldDecl {{.*}} D 'int'
+// CHECK: | |-FieldDecl {{.*}} DD 'void *'
+// CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition
+// CHECK: | | |-FieldDecl {{.*}} A 'int'
+// CHECK: | | `-FieldDecl {{.*}} B 'int'
+// CHECK: | `-EnumDecl {{.*}} NestedEnum
+// CHECK: | |-EnumConstantDecl {{.*}} EnumValue1 'S::NestedEnum'
+// CHECK: | `-EnumConstantDecl {{.*}} EnumValue2 'S::NestedEnum'
+// CHECK: |-CXXRecordDecl {{.*}} struct T definition
+// CHECK: | |-FieldDecl {{.*}} NT 'int'
+// CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition
+// CHECK: | | |-FieldDecl {{.*}} E 'int'
+// CHECK: | | `-FieldDecl {{.*}} F 'int'
+// CHECK: | `-CXXRecordDecl {{.*}} struct U definition
+// CHECK: | |-FieldDecl {{.*}} G 'int'
+// CHECK: | `-FieldDecl {{.*}} H 'int'
+// CHECK: |-CXXRecordDecl {{.*}} class U<int> definition
+// CHECK: | |-FieldDecl {{.*}} K 'int'
+// CHECK: | |-FieldDecl {{.*}} L 'int'
+// CHECK: | `-CXXRecordDecl {{.*}} struct W definition
+// CHECK: | |-FieldDecl {{.*}} M 'int'
+// CHECK: | `-FieldDecl {{.*}} N 'int'
+// CHECK: |-CXXRecordDecl {{.*}} struct U<int>::V<int> definition
+// CHECK: | |-FieldDecl {{.*}} I 'int'
+// CHECK: | `-FieldDecl {{.*}} J 'int'
diff --git a/lit/SymbolFile/NativePDB/s_constant.cpp b/lit/SymbolFile/NativePDB/s_constant.cpp
new file mode 100644
index 000000000000..7603a4daba40
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/s_constant.cpp
@@ -0,0 +1,115 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display S_CONSTANT records.
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-win32 %p/Inputs/s_constant.s > %t.obj
+// RUN: %build --compiler=clang-cl --nodefaultlib --mode=link -o %t.exe -- %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/s_constant.lldbinit | FileCheck %s
+
+// clang-cl cannot generate S_CONSTANT records, but we need to test that we can
+// handle them for compatibility with MSVC, which does emit them. This test
+// case was generated by compiling this file with MSVC and copying the bytes
+// that they emit for S_CONSTANT records. Then we compile the same code with
+// clang to get a .s file, and replace all S_LDATA32 records with the bytes from
+// the S_CONSTANT records. This way we end up with a .s file that contains
+// symbol records that clang-cl won't generate.
+
+namespace A {
+namespace B {
+namespace C {
+ enum LargeUnsignedEnum : unsigned long long {
+ LUE_A = 0ULL,
+ LUE_B = 1000ULL,
+ LUE_C = 18446744073709551600ULL,
+ };
+
+ enum LargeSignedEnum : long long {
+ LSE_A = 0LL,
+ LSE_B = 9223372036854775000LL,
+ LSE_C = -9223372036854775000LL,
+ };
+
+ enum UnsignedEnum : unsigned int {
+ UE_A = 0,
+ UE_B = 1000,
+ UE_C = 4294000000,
+ };
+
+ enum SignedEnum : int {
+ SE_A = 0,
+ SE_B = 2147000000,
+ SE_C = -2147000000,
+ };
+
+ enum SmallUnsignedEnum : unsigned char {
+ SUE_A = 0,
+ SUE_B = 100,
+ SUE_C = 200,
+ };
+
+ enum SmallSignedEnum : char {
+ SSE_A = 0,
+ SSE_B = 100,
+ SSE_C = -100,
+ };
+}
+}
+}
+
+using namespace A::B::C;
+
+constexpr LargeUnsignedEnum GlobalLUEA = LUE_A;
+constexpr LargeUnsignedEnum GlobalLUEB = LUE_B;
+constexpr LargeUnsignedEnum GlobalLUEC = LUE_C;
+
+constexpr LargeSignedEnum GlobalLSEA = LSE_A;
+constexpr LargeSignedEnum GlobalLSEB = LSE_B;
+constexpr LargeSignedEnum GlobalLSEC = LSE_C;
+
+constexpr UnsignedEnum GlobalUEA = UE_A;
+constexpr UnsignedEnum GlobalUEB = UE_B;
+constexpr UnsignedEnum GlobalUEC = UE_C;
+
+constexpr SignedEnum GlobalSEA = SE_A;
+constexpr SignedEnum GlobalSEB = SE_B;
+constexpr SignedEnum GlobalSEC = SE_C;
+
+constexpr SmallUnsignedEnum GlobalSUEA = SUE_A;
+constexpr SmallUnsignedEnum GlobalSUEB = SUE_B;
+constexpr SmallUnsignedEnum GlobalSUEC = SUE_C;
+
+constexpr SmallSignedEnum GlobalSSEA = SSE_A;
+constexpr SmallSignedEnum GlobalSSEB = SSE_B;
+constexpr SmallSignedEnum GlobalSSEC = SSE_C;
+
+int main(int argc, char **argv) {
+ return 0;
+}
+
+// CHECK: (const A::B::C::LargeUnsignedEnum) GlobalLUEA = LUE_A
+// CHECK: (const A::B::C::LargeUnsignedEnum) GlobalLUEB = LUE_B
+
+// X-FAIL: Something is outputting bad debug info here, maybe cl.
+// CHECK: (const A::B::C::LargeUnsignedEnum) GlobalLUEC = {{.*}}
+
+// CHECK: (const A::B::C::LargeSignedEnum) GlobalLSEA = LSE_A
+// CHECK: (const A::B::C::LargeSignedEnum) GlobalLSEB = LSE_B
+// CHECK: (const A::B::C::LargeSignedEnum) GlobalLSEC = LSE_C
+
+// CHECK: (const A::B::C::UnsignedEnum) GlobalUEA = UE_A
+// CHECK: (const A::B::C::UnsignedEnum) GlobalUEB = UE_B
+// CHECK: (const A::B::C::UnsignedEnum) GlobalUEC = UE_C
+
+// CHECK: (const A::B::C::SignedEnum) GlobalSEA = SE_A
+// CHECK: (const A::B::C::SignedEnum) GlobalSEB = SE_B
+// CHECK: (const A::B::C::SignedEnum) GlobalSEC = SE_C
+
+// CHECK: (const A::B::C::SmallUnsignedEnum) GlobalSUEA = SUE_A
+// CHECK: (const A::B::C::SmallUnsignedEnum) GlobalSUEB = SUE_B
+// CHECK: (const A::B::C::SmallUnsignedEnum) GlobalSUEC = SUE_C
+
+// CHECK: (const A::B::C::SmallSignedEnum) GlobalSSEA = SSE_A
+// CHECK: (const A::B::C::SmallSignedEnum) GlobalSSEB = SSE_B
+// CHECK: (const A::B::C::SmallSignedEnum) GlobalSSEC = SSE_C
diff --git a/lit/SymbolFile/NativePDB/source-list.cpp b/lit/SymbolFile/NativePDB/source-list.cpp
new file mode 100644
index 000000000000..6b749b082e3d
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/source-list.cpp
@@ -0,0 +1,42 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can set display source of functions.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/source-list.lldbinit | FileCheck %s
+
+
+
+// Some context lines before
+// the function.
+
+
+int main(int argc, char **argv) {
+ // Here are some comments.
+ // That we should print when listing source.
+ return 0;
+}
+
+// Some context lines after
+// the function.
+
+// check lines go at the end so that line numbers stay stable when
+// changing this file.
+
+// CHECK: (lldb) source list -n main
+// CHECK: File: {{.*}}source-list.cpp
+// CHECK: 10
+// CHECK: 11 // Some context lines before
+// CHECK: 12 // the function.
+// CHECK: 13
+// CHECK: 14
+// CHECK: 15 int main(int argc, char **argv) {
+// CHECK: 16 // Here are some comments.
+// CHECK: 17 // That we should print when listing source.
+// CHECK: 18 return 0;
+// CHECK: 19 }
+// CHECK: 20
+// CHECK: 21 // Some context lines after
+// CHECK: 22 // the function.
+// CHECK: 23
diff --git a/lit/SymbolFile/NativePDB/tag-types.cpp b/lit/SymbolFile/NativePDB/tag-types.cpp
new file mode 100644
index 000000000000..947fe20d17d7
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/tag-types.cpp
@@ -0,0 +1,235 @@
+// clang-format off
+// REQUIRES: lld
+
+// Test that we can display tag types.
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
+// RUN: %p/Inputs/tag-types.lldbinit | FileCheck %s
+
+// Test struct
+struct Struct {
+ // Test builtin types, which are represented by special CodeView type indices.
+ bool B;
+ char C;
+ signed char SC;
+ unsigned char UC;
+ char16_t C16;
+ char32_t C32;
+ wchar_t WC;
+ short S;
+ unsigned short US;
+ int I;
+ unsigned int UI;
+ long L;
+ unsigned long UL;
+ long long LL;
+ unsigned long long ULL;
+ float F;
+ double D;
+ long double LD;
+};
+
+// Test class
+class Class {
+public:
+ // Test pointers to builtin types, which are represented by different special
+ // CodeView type indices.
+ bool *PB;
+ char *PC;
+ signed char *PSC;
+ unsigned char *PUC;
+ char16_t *PC16;
+ char32_t *PC32;
+ wchar_t *PWC;
+ short *PS;
+ unsigned short *PUS;
+ int *PI;
+ unsigned int *PUI;
+ long *PL;
+ unsigned long *PUL;
+ long long *PLL;
+ unsigned long long *PULL;
+ float *PF;
+ double *PD;
+ long double *PLD;
+};
+
+// Test union
+union Union {
+ // Test modified types.
+ const bool *PB;
+ const char *PC;
+ const signed char *PSC;
+ const unsigned char *PUC;
+ const char16_t *PC16;
+ const char32_t *PC32;
+ const wchar_t *PWC;
+ const short *PS;
+ const unsigned short *PUS;
+ const int *PI;
+ const unsigned int *PUI;
+ const long *PL;
+ const unsigned long *PUL;
+ const long long *PLL;
+ const unsigned long long *PULL;
+ const float *PF;
+ const double *PD;
+ const long double *PLD;
+};
+
+struct OneMember {
+ int N = 0;
+};
+
+
+// Test single inheritance.
+class Derived : public Class {
+public:
+ explicit Derived()
+ : Reference(*this), RefMember(Member), RValueRefMember((OneMember&&)Member) {}
+
+ // Test reference to self, to make sure we don't end up in an
+ // infinite cycle.
+ Derived &Reference;
+
+ // Test aggregate class member.
+ OneMember Member;
+
+ // And modified aggregate class member.
+ const OneMember ConstMember;
+ volatile OneMember VolatileMember;
+ const volatile OneMember CVMember;
+
+ // And all types of pointers to class members
+ OneMember *PtrMember;
+ OneMember &RefMember;
+ OneMember &&RValueRefMember;
+};
+
+// Test multiple inheritance, as well as protected and private inheritance.
+class Derived2 : protected Class, private Struct {
+public:
+ // Test static data members
+ static unsigned StaticDataMember;
+};
+
+unsigned Derived2::StaticDataMember = 0;
+
+// Test scoped enums and unscoped enums.
+enum class EnumInt {
+ A = 1,
+ B = 2
+};
+
+// Test explicit underlying types
+enum EnumShort : short {
+ ES_A = 2,
+ ES_B = 3
+};
+
+int main(int argc, char **argv) {
+ Struct S;
+ Class C;
+ Union U;
+ Derived D;
+ Derived2 D2;
+ EnumInt EI;
+ EnumShort ES;
+
+ return 0;
+}
+
+// CHECK: (lldb) target create "{{.*}}tag-types.cpp.tmp.exe"
+// CHECK-NEXT: Current executable set to '{{.*}}tag-types.cpp.tmp.exe'
+// CHECK-NEXT: (lldb) command source -s 0 '{{.*}}tag-types.lldbinit'
+// CHECK-NEXT: Executing commands in '{{.*}}tag-types.lldbinit'.
+// CHECK-NEXT: (lldb) type lookup -- Struct
+// CHECK-NEXT: struct Struct {
+// CHECK-NEXT: bool B;
+// CHECK-NEXT: char C;
+// CHECK-NEXT: signed char SC;
+// CHECK-NEXT: unsigned char UC;
+// CHECK-NEXT: char16_t C16;
+// CHECK-NEXT: char32_t C32;
+// CHECK-NEXT: wchar_t WC;
+// CHECK-NEXT: short S;
+// CHECK-NEXT: unsigned short US;
+// CHECK-NEXT: int I;
+// CHECK-NEXT: unsigned int UI;
+// CHECK-NEXT: long L;
+// CHECK-NEXT: unsigned long UL;
+// CHECK-NEXT: long long LL;
+// CHECK-NEXT: unsigned long long ULL;
+// CHECK-NEXT: float F;
+// CHECK-NEXT: double D;
+// CHECK-NEXT: double LD;
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- Class
+// CHECK-NEXT: class Class {
+// CHECK-NEXT: bool *PB;
+// CHECK-NEXT: char *PC;
+// CHECK-NEXT: signed char *PSC;
+// CHECK-NEXT: unsigned char *PUC;
+// CHECK-NEXT: char16_t *PC16;
+// CHECK-NEXT: char32_t *PC32;
+// CHECK-NEXT: wchar_t *PWC;
+// CHECK-NEXT: short *PS;
+// CHECK-NEXT: unsigned short *PUS;
+// CHECK-NEXT: int *PI;
+// CHECK-NEXT: unsigned int *PUI;
+// CHECK-NEXT: long *PL;
+// CHECK-NEXT: unsigned long *PUL;
+// CHECK-NEXT: long long *PLL;
+// CHECK-NEXT: unsigned long long *PULL;
+// CHECK-NEXT: float *PF;
+// CHECK-NEXT: double *PD;
+// CHECK-NEXT: double *PLD;
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- Union
+// CHECK-NEXT: union Union {
+// CHECK-NEXT: const bool *PB;
+// CHECK-NEXT: const char *PC;
+// CHECK-NEXT: const signed char *PSC;
+// CHECK-NEXT: const unsigned char *PUC;
+// CHECK-NEXT: const char16_t *PC16;
+// CHECK-NEXT: const char32_t *PC32;
+// CHECK-NEXT: const wchar_t *PWC;
+// CHECK-NEXT: const short *PS;
+// CHECK-NEXT: const unsigned short *PUS;
+// CHECK-NEXT: const int *PI;
+// CHECK-NEXT: const unsigned int *PUI;
+// CHECK-NEXT: const long *PL;
+// CHECK-NEXT: const unsigned long *PUL;
+// CHECK-NEXT: const long long *PLL;
+// CHECK-NEXT: const unsigned long long *PULL;
+// CHECK-NEXT: const float *PF;
+// CHECK-NEXT: const double *PD;
+// CHECK-NEXT: const double *PLD;
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- Derived
+// CHECK-NEXT: class Derived : public Class {
+// CHECK-NEXT: Derived &Reference;
+// CHECK-NEXT: OneMember Member;
+// CHECK-NEXT: const OneMember ConstMember;
+// CHECK-NEXT: volatile OneMember VolatileMember;
+// CHECK-NEXT: const volatile OneMember CVMember;
+// CHECK-NEXT: OneMember *PtrMember;
+// CHECK-NEXT: OneMember &RefMember;
+// CHECK-NEXT: OneMember &&RValueRefMember;
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- Derived2
+// CHECK-NEXT: class Derived2 : protected Class, private Struct {
+// CHECK-NEXT: static unsigned int StaticDataMember;
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- EnumInt
+// CHECK-NEXT: enum EnumInt {
+// CHECK-NEXT: A,
+// CHECK-NEXT: B
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- EnumShort
+// CHECK-NEXT: enum EnumShort {
+// CHECK-NEXT: ES_A,
+// CHECK-NEXT: ES_B
+// CHECK-NEXT: }
+// CHECK-NEXT: (lldb) type lookup -- InvalidType
+// CHECK-NEXT: no type was found matching 'InvalidType'
diff --git a/lit/SymbolFile/NativePDB/typedefs.cpp b/lit/SymbolFile/NativePDB/typedefs.cpp
new file mode 100644
index 000000000000..738fbe615d90
--- /dev/null
+++ b/lit/SymbolFile/NativePDB/typedefs.cpp
@@ -0,0 +1,71 @@
+// clang-format off
+
+// REQUIRES: system-windows
+// RUN: %build --compiler=clang-cl --nodefaultlib -o %t.exe -- %s
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols -dump-ast %t.exe | FileCheck %s
+
+namespace A {
+ namespace B {
+ using NamespaceTypedef = double;
+ }
+ template<typename T>
+ class C {
+ public:
+ using ClassTypedef = T;
+ };
+ using ClassTypedef = C<char>::ClassTypedef;
+ using ClassTypedef2 = C<wchar_t>::ClassTypedef;
+
+ template<typename T>
+ using AliasTemplate = typename C<T>::ClassTypedef;
+}
+
+namespace {
+ using AnonNamespaceTypedef = bool;
+}
+
+using IntTypedef = int;
+
+using ULongArrayTypedef = unsigned long[10];
+
+using RefTypedef = long double*&;
+
+using FuncPtrTypedef = long long(*)(int&, unsigned char**, short[], const double, volatile bool);
+
+using VarArgsFuncTypedef = char(*)(void*, long, unsigned short, unsigned int, ...);
+
+using VarArgsFuncTypedefA = float(*)(...);
+
+int main(int argc, char **argv) {
+ long double *Ptr;
+
+ A::B::NamespaceTypedef *X0;
+ A::C<char>::ClassTypedef *X1;
+ A::C<wchar_t>::ClassTypedef *X2;
+ AnonNamespaceTypedef *X3;
+ IntTypedef *X4;
+ ULongArrayTypedef *X5;
+ RefTypedef X6 = Ptr;
+ FuncPtrTypedef X7;
+ VarArgsFuncTypedef X8;
+ VarArgsFuncTypedefA X9;
+ A::AliasTemplate<float> X10;
+ return 0;
+}
+
+
+// CHECK: namespace `anonymous namespace' {
+// CHECK-NEXT: typedef bool AnonNamespaceTypedef;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef unsigned long ULongArrayTypedef[10];
+// CHECK-NEXT: typedef double *&RefTypedef;
+// CHECK-NEXT: namespace A {
+// CHECK-NEXT: namespace B {
+// CHECK-NEXT: typedef double NamespaceTypedef;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef float AliasTemplate<float>;
+// CHECK-NEXT: }
+// CHECK-NEXT: typedef long long (*FuncPtrTypedef)(int &, unsigned char **, short *, const double, volatile bool);
+// CHECK-NEXT: typedef char (*VarArgsFuncTypedef)(void *, long, unsigned short, unsigned int, ...);
+// CHECK-NEXT: typedef float (*VarArgsFuncTypedefA)(...);
+// CHECK-NEXT: typedef int IntTypedef;
diff --git a/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp b/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
new file mode 100644
index 000000000000..8c9e26744d5f
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/AstRestoreTest.cpp
@@ -0,0 +1,55 @@
+namespace N0 {
+namespace N1 {
+
+namespace {
+enum Enum { Enum_0 = 1, Enum_1 = 2, Enum_2 = 4, Enum_3 = 8 };
+}
+
+Enum Global = Enum_3;
+
+struct Base {
+ Enum m_e = Enum_1;
+};
+
+class Class : public Base {
+public:
+ Class(Enum e) : m_ce(e) {}
+
+ static int StaticFunc(const Class &c) {
+ return c.PrivateFunc(c.m_inner) + Global + ClassStatic;
+ }
+
+ const Enum m_ce;
+
+ static int ClassStatic;
+
+private:
+ struct Inner {
+ char x;
+ short y;
+ int z;
+ };
+
+ int PrivateFunc(const Inner &i) const { return i.z; }
+
+ Inner m_inner{};
+};
+int Class::ClassStatic = 7;
+
+template<typename T>
+struct Template {
+ template<Enum E>
+ void TemplateFunc() {
+ T::StaticFunc(T(E));
+ }
+};
+
+void foo() { Template<Class>().TemplateFunc<Enum_0>(); }
+
+} // namespace N1
+} // namespace N0
+
+int main() {
+ N0::N1::foo();
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/CallingConventionsTest.cpp b/lit/SymbolFile/PDB/Inputs/CallingConventionsTest.cpp
new file mode 100644
index 000000000000..60854c04c60a
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/CallingConventionsTest.cpp
@@ -0,0 +1,20 @@
+int FuncCCall() { return 0; }
+auto FuncCCallPtr = &FuncCCall;
+
+int __stdcall FuncStdCall() { return 0; }
+auto FuncStdCallPtr = &FuncStdCall;
+
+int __fastcall FuncFastCall() { return 0; }
+auto FuncFastCallPtr = &FuncFastCall;
+
+int __vectorcall FuncVectorCall() { return 0; }
+auto FuncVectorCallPtr = &FuncVectorCall;
+
+struct S {
+ int FuncThisCall() { return 0; }
+};
+auto FuncThisCallPtr = &S::FuncThisCall;
+
+int main() {
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/ClassLayoutTest.cpp b/lit/SymbolFile/PDB/Inputs/ClassLayoutTest.cpp
new file mode 100644
index 000000000000..3c4b005cdf1b
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/ClassLayoutTest.cpp
@@ -0,0 +1,111 @@
+// To avoid linking MSVC specific libs, we don't test virtual/override methods
+// that needs vftable support in this file.
+
+// Enum.
+enum Enum { RED, GREEN, BLUE };
+Enum EnumVar;
+
+// Union.
+union Union {
+ short Row;
+ unsigned short Col;
+ int Line : 16; // Test named bitfield.
+ short : 8; // Unnamed bitfield symbol won't be generated in PDB.
+ long Table;
+};
+Union UnionVar;
+
+// Struct.
+struct Struct;
+typedef Struct StructTypedef;
+
+struct Struct {
+ bool A;
+ unsigned char UCharVar;
+ unsigned int UIntVar;
+ long long LongLongVar;
+ Enum EnumVar; // Test struct has UDT member.
+ int array[10];
+};
+struct Struct StructVar;
+
+struct _List; // Forward declaration.
+struct Complex {
+ struct _List *array[90];
+ struct { // Test unnamed struct. MSVC treats it as `int x`
+ int x;
+ };
+ union { // Test unnamed union. MSVC treats it as `int a; float b;`
+ int a;
+ float b;
+ };
+};
+struct Complex c;
+
+struct _List { // Test doubly linked list.
+ struct _List *current;
+ struct _List *previous;
+ struct _List *next;
+};
+struct _List ListVar;
+
+typedef struct {
+ int a;
+} UnnamedStruct; // Test unnamed typedef-ed struct.
+UnnamedStruct UnnanmedVar;
+
+// Class.
+namespace MemberTest {
+class Base {
+public:
+ Base() {}
+ ~Base() {}
+
+public:
+ int Get() { return 0; }
+
+protected:
+ int a;
+};
+class Friend {
+public:
+ int f() { return 3; }
+};
+class Class : public Base { // Test base class.
+ friend Friend;
+ static int m_static; // Test static member variable.
+public:
+ Class() : m_public(), m_private(), m_protected() {}
+ explicit Class(int a) { m_public = a; } // Test first reference of m_public.
+ ~Class() {}
+
+ static int StaticMemberFunc(int a, ...) {
+ return 1;
+ } // Test static member function.
+ int Get() { return 1; }
+ int f(Friend c) { return c.f(); }
+ inline bool operator==(const Class &rhs) const // Test operator.
+ {
+ return (m_public == rhs.m_public);
+ }
+
+public:
+ int m_public;
+ struct Struct m_struct;
+
+private:
+ Union m_union;
+ int m_private;
+
+protected:
+ friend class Friend;
+ int m_protected;
+};
+} // namespace MemberTest
+
+int main() {
+ MemberTest::Base B1;
+ B1.Get();
+ MemberTest::Class::StaticMemberFunc(1, 10, 2);
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp b/lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp
new file mode 100644
index 000000000000..3785cd3c64c7
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/ExpressionsTest.cpp
@@ -0,0 +1,20 @@
+namespace N0 {
+namespace N1 {
+
+char *buf0 = nullptr;
+char buf1[] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+char sum(char *buf, int size) {
+ char result = 0;
+ for (int i = 0; i < size; i++)
+ result += buf[i];
+ return result;
+}
+
+} // namespace N1
+} // namespace N0
+
+int main() {
+ char result = N0::N1::sum(N0::N1::buf1, sizeof(N0::N1::buf1));
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script b/lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script
new file mode 100644
index 000000000000..d31a2abb68a2
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/ExpressionsTest0.script
@@ -0,0 +1,7 @@
+breakpoint set --file ExpressionsTest.cpp --line 19
+run
+print result
+print N0::N1::sum(N0::N1::buf1, sizeof(N0::N1::buf1))
+print N1::sum(N1::buf1, sizeof(N1::buf1))
+print sum(buf1, sizeof(buf1))
+print sum(buf1, 1000000000)
diff --git a/lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script b/lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script
new file mode 100644
index 000000000000..dac887faa5bb
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/ExpressionsTest1.script
@@ -0,0 +1 @@
+print sum(buf0, 1)
diff --git a/lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script b/lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script
new file mode 100644
index 000000000000..b19240baf99d
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/ExpressionsTest2.script
@@ -0,0 +1,2 @@
+print sum(buf0, result - 28)
+print sum(buf1 + 3, 3)
diff --git a/lit/SymbolFile/PDB/Inputs/PointerTypeTest.cpp b/lit/SymbolFile/PDB/Inputs/PointerTypeTest.cpp
new file mode 100644
index 000000000000..6612c30f00df
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/PointerTypeTest.cpp
@@ -0,0 +1,23 @@
+int main() {
+ // Test pointer to array.
+ int array[2][4];
+ int(*array_pointer)[2][4] = &array;
+
+ struct ST {
+ int a;
+ int f(int x) { return 1; }
+ };
+
+ ST s = {10};
+
+ // Test pointer to a local.
+ int *p_int = &s.a;
+
+ // Test pointer to data member.
+ int ST::*p_member_field = &ST::a;
+
+ // Test pointer to member function.
+ int (ST::*p_member_method)(int) = &ST::f;
+
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/SimpleTypesTest.cpp b/lit/SymbolFile/PDB/Inputs/SimpleTypesTest.cpp
index 8e516201644c..de13a5b430c1 100644
--- a/lit/SymbolFile/PDB/Inputs/SimpleTypesTest.cpp
+++ b/lit/SymbolFile/PDB/Inputs/SimpleTypesTest.cpp
@@ -35,6 +35,9 @@ EnumClass EnumClassVar;
enum struct EnumStruct { red, blue, black };
EnumStruct EnumStructVar;
+typedef signed char SCharTypedef;
+SCharTypedef SCVar;
+
typedef char16_t WChar16Typedef;
WChar16Typedef WC16Var;
diff --git a/lit/SymbolFile/PDB/Inputs/UdtLayoutTest.cpp b/lit/SymbolFile/PDB/Inputs/UdtLayoutTest.cpp
new file mode 100644
index 000000000000..59a4fc585d77
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/UdtLayoutTest.cpp
@@ -0,0 +1,61 @@
+struct A {
+ explicit A(int u) { _u._u3 = u; }
+ A(const A &) = default;
+ virtual ~A() = default;
+
+private:
+ union U {
+ char _u1;
+ short _u2;
+ int _u3;
+ };
+
+ A::U _u;
+};
+
+#pragma pack(push, 1)
+template <int I> struct B : public virtual A {
+ B(char a, unsigned short b, int c) : A(a + b + c), _a(a), _b(b), _c(c) {}
+
+private:
+ char _a;
+ unsigned short : 3;
+ unsigned short _b : 6;
+ unsigned short : 4;
+ int _c;
+};
+#pragma pack(pop)
+
+#pragma pack(push, 16)
+class C : private virtual B<0>, public virtual B<1>, private B<2>, public B<3> {
+public:
+ C(char x, char y, char z)
+ : A(x - y + z), B<0>(x, y, z), B<1>(x * 2, y * 2, z * 2),
+ B<2>(x * 3, y * 3, z * 3), B<3>(x * 4, y * 4, z * 4), _x(x * 5),
+ _y(y * 5), _z(z * 5) {}
+
+ static int abc;
+
+private:
+ int _x;
+ short _y;
+ char _z;
+};
+int C::abc = 123;
+#pragma pack(pop)
+
+class List {
+public:
+ List() = default;
+ List(List *p, List *n, C v) : Prev(p), Next(n), Value(v) {}
+
+private:
+ List *Prev = nullptr;
+ List *Next = nullptr;
+ C Value{1, 2, 3};
+};
+
+int main() {
+ List ls[16];
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/UdtLayoutTest.script b/lit/SymbolFile/PDB/Inputs/UdtLayoutTest.script
new file mode 100644
index 000000000000..91de55f4ade4
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/UdtLayoutTest.script
@@ -0,0 +1,4 @@
+breakpoint set --file UdtLayoutTest.cpp --line 60
+run
+target variable
+frame variable
diff --git a/lit/SymbolFile/PDB/Inputs/VBases.cpp b/lit/SymbolFile/PDB/Inputs/VBases.cpp
new file mode 100644
index 000000000000..a5e84bd36571
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/VBases.cpp
@@ -0,0 +1,16 @@
+struct A {
+ char a = 1;
+};
+
+struct B {
+ int b = 2;
+};
+
+struct C : virtual A, virtual B {
+ short c = 3;
+};
+
+int main() {
+ C c{};
+ return 0;
+}
diff --git a/lit/SymbolFile/PDB/Inputs/VBases.script b/lit/SymbolFile/PDB/Inputs/VBases.script
new file mode 100644
index 000000000000..8675890b76e1
--- /dev/null
+++ b/lit/SymbolFile/PDB/Inputs/VBases.script
@@ -0,0 +1,7 @@
+breakpoint set --file VBases.cpp --line 15
+
+run
+
+print c
+
+frame variable c \ No newline at end of file
diff --git a/lit/SymbolFile/PDB/ast-restore.test b/lit/SymbolFile/PDB/ast-restore.test
new file mode 100644
index 000000000000..2158fc1b3d44
--- /dev/null
+++ b/lit/SymbolFile/PDB/ast-restore.test
@@ -0,0 +1,82 @@
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=msvc --nodefaultlib --output=%t.exe %S/Inputs/AstRestoreTest.cpp
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=ENUM %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=GLOBAL %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=BASE %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=CLASS %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=INNER %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=TEMPLATE %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=FOO %s
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck --check-prefix=MAIN %s
+
+ENUM: Module: {{.*}}
+ENUM: namespace N0 {
+ENUM: namespace N1 {
+ENUM: namespace {
+ENUM: enum Enum {
+ENUM: Enum_0,
+ENUM: Enum_1,
+ENUM: Enum_2,
+ENUM: Enum_3
+ENUM: };
+ENUM: }
+ENUM: }
+ENUM: }
+
+GLOBAL: Module: {{.*}}
+GLOBAL: namespace N0 {
+GLOBAL: namespace N1 {
+GLOBAL: N0::N1::(anonymous namespace)::Enum Global;
+GLOBAL: }
+GLOBAL: }
+
+BASE: Module: {{.*}}
+BASE: namespace N0 {
+BASE: namespace N1 {
+BASE: struct Base {
+BASE: N0::N1::(anonymous namespace)::Enum m_e;
+BASE: };
+BASE: }
+BASE: }
+
+CLASS: Module: {{.*}}
+CLASS: namespace N0 {
+CLASS: namespace N1 {
+CLASS: class Class : public N0::N1::Base {
+CLASS-DAG: const N0::N1::(anonymous namespace)::Enum m_ce;
+CLASS-DAG: static int ClassStatic;
+CLASS-DAG: N0::N1::Class::Inner m_inner;
+CLASS-DAG: {{(inline )?}}Class(N0::N1::(anonymous namespace)::Enum);
+CLASS-DAG: static {{(inline )?}}int StaticFunc(const N0::N1::Class &);
+CLASS-DAG: {{(inline )?}}int PrivateFunc(const N0::N1::Class::Inner &);
+CLASS: };
+CLASS: }
+CLASS: }
+
+INNER: Module: {{.*}}
+INNER: namespace N0 {
+INNER: namespace N1 {
+INNER: class Class : public N0::N1::Base {
+INNER: struct Inner {
+INNER: char x;
+INNER: short y;
+INNER: int z;
+INNER: };
+INNER: };
+INNER: }
+INNER: }
+
+TEMPLATE: Module: {{.*}}
+TEMPLATE: struct Template<N0::N1::Class> {
+TEMPLATE: inline void TemplateFunc<1>();
+TEMPLATE: };
+
+FOO: Module: {{.*}}
+FOO: namespace N0 {
+FOO: namespace N1 {
+FOO: void foo();
+FOO: }
+FOO: }
+
+MAIN: Module: {{.*}}
+MAIN: int main();
diff --git a/lit/SymbolFile/PDB/calling-conventions.test b/lit/SymbolFile/PDB/calling-conventions.test
new file mode 100644
index 000000000000..a85dc65ff04d
--- /dev/null
+++ b/lit/SymbolFile/PDB/calling-conventions.test
@@ -0,0 +1,10 @@
+REQUIRES: system-windows, lld
+RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%t.exe %S/Inputs/CallingConventionsTest.cpp
+RUN: lldb-test symbols -dump-ast %t.exe | FileCheck %s
+
+CHECK: Module: {{.*}}
+CHECK-DAG: int (*FuncCCallPtr)();
+CHECK-DAG: int (*FuncStdCallPtr)() __attribute__((stdcall));
+CHECK-DAG: int (*FuncFastCallPtr)() __attribute__((fastcall));
+CHECK-DAG: int (*FuncVectorCallPtr)() __attribute__((vectorcall));
+CHECK-DAG: int (S::*FuncThisCallPtr)() __attribute__((thiscall));
diff --git a/lit/SymbolFile/PDB/class-layout.test b/lit/SymbolFile/PDB/class-layout.test
new file mode 100644
index 000000000000..5c0194485d76
--- /dev/null
+++ b/lit/SymbolFile/PDB/class-layout.test
@@ -0,0 +1,92 @@
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/ClassLayoutTest.cpp.obj %S/Inputs/ClassLayoutTest.cpp
+RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/ClassLayoutTest.cpp.exe %T/ClassLayoutTest.cpp.obj
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=ENUM %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNION %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=STRUCT %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=COMPLEX %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=LIST %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNNAMED-STRUCT %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=BASE %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=FRIEND %s
+RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=CLASS %s
+
+CHECK: Module [[MOD:.*]]
+CHECK: {{^[0-9A-F]+}}: SymbolVendor pdb ([[MOD]])
+CHECK: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\ClassLayoutTest.cpp'
+
+ENUM: name = "Enum", size = 4, decl = ClassLayoutTest.cpp:5
+ENUM-SAME: enum Enum {
+ENUM: RED,
+ENUM: GREEN,
+ENUM: BLUE
+ENUM:}
+
+UNION: name = "Union", size = 4, decl = ClassLayoutTest.cpp:9
+UNION-SAME: union Union {
+UNION: short Row;
+UNION: unsigned short Col;
+UNION: int Line : 16;
+UNION: long Table;
+UNION:}
+
+STRUCT: name = "Struct", size = 64, decl = ClassLayoutTest.cpp:22
+STRUCT-SAME: struct Struct {
+STRUCT: bool A;
+STRUCT: unsigned char UCharVar;
+STRUCT: unsigned int UIntVar;
+STRUCT: long long LongLongVar;
+STRUCT: Enum EnumVar;
+STRUCT: int array[10];
+STRUCT:}
+
+COMPLEX: name = "Complex", size = 368, decl = ClassLayoutTest.cpp:33
+COMPLEX-SAME: struct Complex {
+COMPLEX: _List *array[90];
+COMPLEX: int x;
+COMPLEX: int a;
+COMPLEX: float b;
+COMPLEX:}
+
+LIST: name = "_List", size = 12, decl = ClassLayoutTest.cpp:45
+LIST-SAME: struct _List {
+LIST: _List *current;
+LIST: _List *previous;
+LIST: _List *next;
+LIST:}
+
+UNNAMED-STRUCT: name = "UnnamedStruct", size = 4, decl = ClassLayoutTest.cpp:52
+UNNAMED-STRUCT-SAME: struct UnnamedStruct {
+UNNAMED-STRUCT: int a;
+UNNAMED-STRUCT:}
+
+BASE: name = "Base", size = 4, decl = ClassLayoutTest.cpp:59
+BASE-SAME: class Base {
+BASE: int a;
+BASE: Base();
+BASE: ~Base();
+BASE: int Get();
+BASE:}
+
+FRIEND: name = "Friend", size = 1, decl = ClassLayoutTest.cpp:70
+FRIEND-SAME: class Friend {
+FRIEND: int f();
+FRIEND: }
+
+CLASS: name = "Class", size = 88, decl = ClassLayoutTest.cpp:74
+CLASS-SAME: class Class : public MemberTest::Base {
+CLASS: static int m_static;
+CLASS: int m_public;
+CLASS: Struct m_struct;
+CLASS: Union m_union;
+CLASS: int m_private;
+CLASS: int m_protected;
+CLASS: Class();
+CLASS: Class(int);
+CLASS: ~Class();
+CLASS: static int {{.*}}StaticMemberFunc(int, ...);
+CLASS: int Get();
+CLASS: int f(MemberTest::Friend);
+CLASS: bool operator==(const MemberTest::Class &)
+CLASS:}
diff --git a/lit/SymbolFile/PDB/compilands.test b/lit/SymbolFile/PDB/compilands.test
index 2e7b014fe966..d719ab7669d8 100644
--- a/lit/SymbolFile/PDB/compilands.test
+++ b/lit/SymbolFile/PDB/compilands.test
@@ -1,9 +1,11 @@
-REQUIRES: windows
-RUN: clang-cl /Z7 %S/Inputs/CompilandsTest.cpp /o %T/CompilandsTest.cpp.exe
-RUN: lldb-test symbols %T/CompilandsTest.cpp.exe | FileCheck %s
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/CompilandsTest.cpp.obj %S/Inputs/CompilandsTest.cpp
+RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/CompilandsTest.cpp.exe %T/CompilandsTest.cpp.obj
+RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %T/CompilandsTest.cpp.exe | FileCheck %s
+RUN: env LLDB_USE_NATIVE_PDB_READER=0 lldb-test symbols %T/CompilandsTest.cpp.exe | FileCheck %s
; Link default libraries
CHECK: Module [[CU:.*]]
-CHECK: {{^[0-9A-F]+}}: SymbolVendor ([[CU]])
+CHECK: {{^[0-9A-F]+}}: SymbolVendor pdb ([[CU]])
CHECK: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\CompilandsTest.cpp'
diff --git a/lit/SymbolFile/PDB/enums-layout.test b/lit/SymbolFile/PDB/enums-layout.test
index ce0b23f453be..79efb259663d 100644
--- a/lit/SymbolFile/PDB/enums-layout.test
+++ b/lit/SymbolFile/PDB/enums-layout.test
@@ -1,45 +1,45 @@
-REQUIRES: windows
-RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/SimpleTypesTest.cpp /o %T/SimpleTypesTest.cpp.enums.obj
-RUN: link %T/SimpleTypesTest.cpp.enums.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/SimpleTypesTest.cpp.enums.exe
-RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck %s
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%T/SimpleTypesTest.cpp.enums.exe %S/Inputs/SimpleTypesTest.cpp
+RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM %s
+RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM_CONST %s
+RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM_EMPTY %s
+RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM_UCHAR %s
+RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM_CLASS %s
+RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM_STRUCT %s
; FIXME: PDB does not have information about scoped enumeration (Enum class) so the
; compiler type used is the same as the one for unscoped enumeration.
-CHECK: Module [[CU:.*]]
-CHECK-DAG: {{^[0-9A-F]+}}: SymbolVendor ([[CU]])
-CHECK: Type{{.*}} , name = "Enum", size = 4, decl = SimpleTypesTest.cpp:19, compiler_type = {{.*}} enum Enum {
-CHECK-NEXT: RED,
-CHECK-NEXT: GREEN,
-CHECK-NEXT: BLUE
-CHECK-NEXT:}
+ENUM: Type{{.*}} , name = "Enum", size = 4, decl = simpletypestest.cpp:19, compiler_type = {{.*}} enum Enum {
+ENUM_NEXT: RED,
+ENUM_NEXT: GREEN,
+ENUM_NEXT: BLUE
+ENUM_NEXT:}
-CHECK: Type{{.*}} , name = "EnumConst", size = 4, decl = SimpleTypesTest.cpp:22, compiler_type = {{.*}} enum EnumConst {
-CHECK-NEXT: LOW,
-CHECK-NEXT: NORMAL,
-CHECK-NEXT: HIGH
-CHECK-NEXT:}
+ENUM_CONST: Type{{.*}} , name = "EnumConst", size = 4, decl = simpletypestest.cpp:22, compiler_type = {{.*}} enum EnumConst {
+ENUM_CONST-NEXT: LOW,
+ENUM_CONST-NEXT: NORMAL,
+ENUM_CONST-NEXT: HIGH
+ENUM_CONST-NEXT:}
-CHECK: Type{{.*}} , name = "EnumEmpty", size = 4, decl = SimpleTypesTest.cpp:25, compiler_type = {{.*}} enum EnumEmpty {
-CHECK-NEXT:}
+ENUM_EMPTY: Type{{.*}} , name = "EnumEmpty", size = 4, decl = simpletypestest.cpp:25, compiler_type = {{.*}} enum EnumEmpty {
+ENUM_EMPTY-NEXT:}
-CHECK: Type{{.*}} , name = "EnumUChar", size = 1, decl = SimpleTypesTest.cpp:28, compiler_type = {{.*}} enum EnumUChar {
-CHECK-NEXT: ON,
-CHECK-NEXT: OFF,
-CHECK-NEXT: AUTO
-CHECK-NEXT:}
+ENUM_UCHAR: Type{{.*}} , name = "EnumUChar", size = 1, decl = simpletypestest.cpp:28, compiler_type = {{.*}} enum EnumUChar {
+ENUM_UCHAR-NEXT: ON,
+ENUM_UCHAR-NEXT: OFF,
+ENUM_UCHAR-NEXT: AUTO
+ENUM_UCHAR-NEXT:}
; Note that `enum EnumClass` is tested instead of `enum class EnumClass`
-CHECK: Type{{.*}} , name = "EnumClass", size = 4, decl = SimpleTypesTest.cpp:32, compiler_type = {{.*}} enum EnumClass {
-CHECK-NEXT: YES,
-CHECK-NEXT: NO,
-CHECK-NEXT: DEFAULT
-CHECK-NEXT:}
-
-CHECK: Type{{.*}} , name = "EnumStruct", size = 4, decl = SimpleTypesTest.cpp:35, compiler_type = {{.*}} enum EnumStruct {
-CHECK-NEXT: red,
-CHECK-NEXT: blue,
-CHECK-NEXT: black
-CHECK-NEXT:}
-
-CHECK-DAG: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\SimpleTypesTest.cpp'
+ENUM_CLASS: Type{{.*}} , name = "EnumClass", size = 4, decl = simpletypestest.cpp:32, compiler_type = {{.*}} enum EnumClass {
+ENUM_CLASS-NEXT: YES,
+ENUM_CLASS-NEXT: NO,
+ENUM_CLASS-NEXT: DEFAULT
+ENUM_CLASS-NEXT:}
+
+ENUM_STRUCT: Type{{.*}} , name = "EnumStruct", size = 4, decl = simpletypestest.cpp:35, compiler_type = {{.*}} enum EnumStruct {
+ENUM_STRUCT-NEXT: red,
+ENUM_STRUCT-NEXT: blue,
+ENUM_STRUCT-NEXT: black
+ENUM_STRUCT-NEXT:}
diff --git a/lit/SymbolFile/PDB/expressions.test b/lit/SymbolFile/PDB/expressions.test
new file mode 100644
index 000000000000..49016196117e
--- /dev/null
+++ b/lit/SymbolFile/PDB/expressions.test
@@ -0,0 +1,35 @@
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=msvc --nodefaultlib --output=%t.exe %S/Inputs/ExpressionsTest.cpp
+RUN: %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s
+
+// Check the variable value through `print`
+CHECK: (lldb) print result
+CHECK: (char) $0 = '\x1c'
+
+// Call the function just like in the code
+CHECK: (lldb) print N0::N1::sum(N0::N1::buf1, sizeof(N0::N1::buf1))
+CHECK: (char) $1 = '\x1c'
+
+// Try the relaxed namespaces search
+CHECK: (lldb) print N1::sum(N1::buf1, sizeof(N1::buf1))
+CHECK: (char) $2 = '\x1c'
+
+// Try the relaxed variables and functions search
+CHECK: (lldb) print sum(buf1, sizeof(buf1))
+CHECK: (char) $3 = '\x1c'
+
+// Make a crash during expression calculation
+CHECK: (lldb) print sum(buf1, 1000000000)
+CHECK: The process has been returned to the state before expression evaluation.
+
+// Make one more crash
+CHECK: (lldb) print sum(buf0, 1)
+CHECK: The process has been returned to the state before expression evaluation.
+
+// Check if the process state was restored succesfully
+CHECK: (lldb) print sum(buf0, result - 28)
+CHECK: (char) $4 = '\0'
+
+// Call the function with arbitrary parameters
+CHECK: (lldb) print sum(buf1 + 3, 3)
+CHECK: (char) $5 = '\f'
diff --git a/lit/SymbolFile/PDB/func-symbols.test b/lit/SymbolFile/PDB/func-symbols.test
index b13ff7e65bb0..fbbf5ddfb856 100644
--- a/lit/SymbolFile/PDB/func-symbols.test
+++ b/lit/SymbolFile/PDB/func-symbols.test
@@ -1,7 +1,5 @@
-REQUIRES: windows
-RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/FuncSymbolsTestMain.cpp /o %T/FuncSymbolsTestMain.cpp.obj
-RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/FuncSymbols.cpp /o %T/FuncSymbols.cpp.obj
-RUN: link %T/FuncSymbolsTestMain.cpp.obj %T/FuncSymbols.cpp.obj /DEBUG /nodefaultlib /Entry:main /OUT:%T/FuncSymbolsTest.exe
+REQUIRES: system-windows, lld
+RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%T/FuncSymbolsTest.exe %S/Inputs/FuncSymbolsTestMain.cpp %S/Inputs/FuncSymbols.cpp
RUN: lldb-test symbols %T/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-ONE %s
RUN: lldb-test symbols %T/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-TWO %s
@@ -9,16 +7,16 @@ RUN: lldb-test symbols %T/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-T
; In this test, We don't check demangled name of a mangled function.
CHECK-ONE: Module [[MD:.*]]
-CHECK-ONE-DAG: {{.*}}: SymbolVendor ([[MD]])
+CHECK-ONE-DAG: {{.*}}: SymbolVendor pdb ([[MD]])
CHECK-ONE-DAG: [[TY0:.*]]: Type{[[UID0:.*]]} , name = "Func_arg_array", decl = FuncSymbolsTestMain.cpp:3, compiler_type = {{.*}} int (int *)
CHECK-ONE-DAG: [[TY1:.*]]: Type{[[UID1:.*]]} , name = "Func_arg_void", decl = FuncSymbolsTestMain.cpp:4, compiler_type = {{.*}} void (void)
CHECK-ONE-DAG: [[TY2:.*]]: Type{[[UID2:.*]]} , name = "Func_arg_none", decl = FuncSymbolsTestMain.cpp:5, compiler_type = {{.*}} void (void)
CHECK-ONE-DAG: [[TY3:.*]]: Type{[[UID3:.*]]} , name = "Func_varargs", decl = FuncSymbolsTestMain.cpp:6, compiler_type = {{.*}} void (...)
-CHECK-ONE-DAG: [[TY4:.*]]: Type{[[UID4:.*]]} , name = "NS::Func", decl = FuncSymbolsTestMain.cpp:28, compiler_type = {{.*}} void (signed char, int)
+CHECK-ONE-DAG: [[TY4:.*]]: Type{[[UID4:.*]]} , name = "Func", decl = FuncSymbolsTestMain.cpp:28, compiler_type = {{.*}} void (char, int)
CHECK-ONE-DAG: [[TY5:.*]]: Type{[[UID5:.*]]} , name = "main", decl = FuncSymbolsTestMain.cpp:44, compiler_type = {{.*}} int (void)
-CHECK-ONE-DAG: [[TY6:.*]]: Type{[[UID6:.*]]} , name = "`anonymous namespace'::Func", decl = FuncSymbolsTestMain.cpp:24, compiler_type = {{.*}} void (int, const long, volatile _Bool, ...)
+CHECK-ONE-DAG: [[TY6:.*]]: Type{[[UID6:.*]]} , name = "Func", decl = FuncSymbolsTestMain.cpp:24, compiler_type = {{.*}} void (int, const long, volatile _Bool, ...)
CHECK-ONE-DAG: [[TY7:.*]]: Type{[[UID7:.*]]} , name = "StaticFunction", decl = FuncSymbolsTestMain.cpp:35, compiler_type = {{.*}} long (int)
-CHECK-ONE-DAG: [[TY8:.*]]: Type{[[UID8:.*]]} , name = "MemberTest::A::Func", decl = FuncSymbolsTestMain.cpp:12, compiler_type = {{.*}} int (int, ...)
+CHECK-ONE-DAG: [[TY8:.*]]: Type{[[UID8:.*]]} , name = "Func", decl = FuncSymbolsTestMain.cpp:12, compiler_type = {{.*}} int (int, ...)
CHECK-ONE-DAG: [[TY9:.*]]: Type{[[UID9:.*]]} , name = "TemplateFunc<1,int>", decl = FuncSymbolsTestMain.cpp:18, compiler_type = {{.*}} void (int)
CHECK-ONE-DAG: [[TY10:.*]]: Type{[[UID10:.*]]} , name = "TemplateFunc<1,int,int,int>", decl = FuncSymbolsTestMain.cpp:18, compiler_type = {{.*}} void (int, int, int)
CHECK-ONE-DAG: [[TY11:.*]]: Type{[[UID11:.*]]} , name = "InlinedFunction", decl = FuncSymbolsTestMain.cpp:40, compiler_type = {{.*}} void (long)
@@ -39,7 +37,7 @@ CHECK-ONE-DAG: Function{[[UID11]]}, mangled = ?InlinedFunction@@YAXJ@Z, demangle
; We expect new types observed in another compile unit
CHECK-TWO-DAG: [[TY30:.*]]: Type{[[UID30:.*]]} , name = "FunctionCall", decl = FuncSymbols.cpp:13, compiler_type = {{.*}} void (void)
-CHECK-TWO-DAG: [[TY31:.*]]: Type{[[UID31:.*]]} , name = "`anonymous namespace'::StaticFunction", decl = FuncSymbols.cpp:4, compiler_type = {{.*}} long (int)
+CHECK-TWO-DAG: [[TY31:.*]]: Type{[[UID31:.*]]} , name = "StaticFunction", decl = FuncSymbols.cpp:4, compiler_type = {{.*}} long (int)
CHECK-TWO-DAG: [[TY32:.*]]: Type{[[UID32:.*]]} , name = "InlinedFunction", decl = FuncSymbols.cpp:10, compiler_type = {{.*}} int (long)
CHECK-TWO: {{.*}}: CompileUnit{{.*}}, language = "c++", file = '{{.*}}\FuncSymbols.cpp'
diff --git a/lit/SymbolFile/PDB/function-level-linking.test b/lit/SymbolFile/PDB/function-level-linking.test
index 9b28ec1ba217..37b2cbc761b8 100644
--- a/lit/SymbolFile/PDB/function-level-linking.test
+++ b/lit/SymbolFile/PDB/function-level-linking.test
@@ -1,4 +1,5 @@
-REQUIRES: windows, lld
-RUN: clang-cl /c /Zi /Gy %S/Inputs/FunctionLevelLinkingTest.cpp /o %t.obj
+REQUIRES: system-windows, lld
+RUN: %clang_cl /c /Zi /Gy %S/Inputs/FunctionLevelLinkingTest.cpp /o %t.obj
RUN: lld-link /debug:full /nodefaultlib /entry:main /order:@%S/Inputs/FunctionLevelLinkingTest.ord %t.obj /out:%t.exe
-RUN: lldb-test symbols -verify %t.exe
+RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols -verify %t.exe
+RUN: env LLDB_USE_NATIVE_PDB_READER=0 lldb-test symbols -verify %t.exe
diff --git a/lit/SymbolFile/PDB/function-nested-block.test b/lit/SymbolFile/PDB/function-nested-block.test
index 93543c681130..9057d01c2584 100644
--- a/lit/SymbolFile/PDB/function-nested-block.test
+++ b/lit/SymbolFile/PDB/function-nested-block.test
@@ -1,7 +1,11 @@
-REQUIRES: windows, lld
-RUN: clang-cl /c /Zi %S/Inputs/FunctionNestedBlockTest.cpp /o %t.obj
-RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe
-RUN: lldb-test symbols -find=function -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck %s
+REQUIRES: system-windows, lld
+RUN: %build --compiler=clang-cl --nodefaultlib --output=%t.exe %S/Inputs/FunctionNestedBlockTest.cpp
+RUN: lldb-test symbols -find=function -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck --check-prefix=CHECK-FUNCTION %s
+RUN: lldb-test symbols -find=block -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck --check-prefix=CHECK-BLOCK %s
-CHECK: Found 1 functions:
-CHECK: name = "{{.*}}", mangled = "{{_?}}main"
+CHECK-FUNCTION: Found 1 functions:
+CHECK-FUNCTION: name = "{{.*}}", mangled = "{{_?}}main"
+
+CHECK-BLOCK: Found 1 blocks:
+CHECK-BLOCK: Blocks: id = {{.*}}, range = {{.*}}
+CHECK-BLOCK: id = {{.*}}, range = {{.*}}
diff --git a/lit/SymbolFile/PDB/lit.local.cfg b/lit/SymbolFile/PDB/lit.local.cfg
deleted file mode 100644
index df9b335dd131..000000000000
--- a/lit/SymbolFile/PDB/lit.local.cfg
+++ /dev/null
@@ -1 +0,0 @@
-config.suffixes = ['.test']
diff --git a/lit/SymbolFile/PDB/pointers.test b/lit/SymbolFile/PDB/pointers.test
new file mode 100644
index 000000000000..a8f84f14783d
--- /dev/null
+++ b/lit/SymbolFile/PDB/pointers.test
@@ -0,0 +1,38 @@
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/PointerTypeTest.cpp.obj %S/Inputs/PointerTypeTest.cpp
+RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/PointerTypeTest.cpp.exe %T/PointerTypeTest.cpp.obj
+RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck %s
+RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN-ST-F %s
+RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN-ST %s
+RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN %s
+RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=F %s
+
+CHECK: Module [[MOD:.*]]
+CHECK: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\PointerTypeTest.cpp'
+
+MAIN-ST-F: name = "f"
+MAIN-ST-F-SAME: decl = PointerTypeTest.cpp:8
+MAIN-ST-F-SAME: compiler_type = {{.*}} int (int)
+
+MAIN-ST: name = "ST", size = 4, decl = PointerTypeTest.cpp:6, compiler_type = {{.*}} struct ST {
+MAIN-ST-NEXT: int a;
+MAIN-ST-NEXT: int {{.*}}f(int);
+MAIN-ST-NEXT:}
+
+MAIN: Function{[[FID1:.*]]}, mangled = _main
+MAIN-NEXT: Block{[[FID1]]}
+MAIN: Variable{{.*}}, name = "array_pointer"
+MAIN-SAME: (int (*)[2][4]), scope = local
+MAIN: Variable{{.*}}, name = "p_int"
+MAIN-SAME: (int *), scope = local
+MAIN: Variable{{.*}}, name = "p_member_field"
+MAIN-SAME: (int ST::*), scope = local
+MAIN: Variable{{.*}}, name = "p_member_method"
+MAIN-SAME: (int (ST::*)(int) __attribute__((thiscall))), scope = local
+
+F: Function{[[FID2:.*]]}, demangled = {{.*}}f(int)
+F-NEXT: Block{[[FID2]]}
+F: Variable{{.*}}, name = "this"
+F-SAME: (ST *), scope = parameter, location = {{.*}}, artificial
+F: Variable{{.*}}, name = "x"
+F-SAME: (int), scope = parameter, decl = PointerTypeTest.cpp:8
diff --git a/lit/SymbolFile/PDB/type-quals.test b/lit/SymbolFile/PDB/type-quals.test
index fbe10c0d8d64..734509f78345 100644
--- a/lit/SymbolFile/PDB/type-quals.test
+++ b/lit/SymbolFile/PDB/type-quals.test
@@ -1,39 +1,39 @@
-REQUIRES: windows
-RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/TypeQualsTest.cpp /o %T/TypeQualsTest.cpp.obj
-RUN: link %T/TypeQualsTest.cpp.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/TypeQualsTest.cpp.exe
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/TypeQualsTest.cpp.obj %S/Inputs/TypeQualsTest.cpp
+RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/TypeQualsTest.cpp.exe %T/TypeQualsTest.cpp.obj
RUN: lldb-test symbols %T/TypeQualsTest.cpp.exe | FileCheck %s
CHECK: Module [[MOD:.*]]
-CHECK-DAG: {{^[0-9A-F]+}}: SymbolVendor ([[MOD]])
-CHECK: Type{{.*}} , name = "const int", size = 4, compiler_type = {{.*}} const int
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int **const
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const *
-CHECK: Type{{.*}} , name = "Func1", {{.*}}, compiler_type = {{.*}} void (const int *, const int *, const int **const, const int *const *)
-
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} volatile int *
-CHECK: Type{{.*}} , name = "Func2", {{.*}}, compiler_type = {{.*}} void (volatile int *, volatile int *)
-
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int *
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int *&
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int &
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} const int &
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int &&
-CHECK: Type{{.*}} , name = "Func3", {{.*}}, compiler_type = {{.*}} void (int *&, int &, const int &, int &&)
+CHECK-DAG: {{^[0-9A-F]+}}: SymbolVendor pdb ([[MOD]])
+CHECK-DAG: Type{{.*}} , name = "const int", size = 4, compiler_type = {{.*}} const int
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} const int **const
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} const int *const *
+CHECK-DAG: Type{{.*}} , name = "Func1", {{.*}}, compiler_type = {{.*}} void (const int *, const int *, const int **const, const int *const *)
+
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} volatile int *
+CHECK-DAG: Type{{.*}} , name = "Func2", {{.*}}, compiler_type = {{.*}} void (volatile int *, volatile int *)
+
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} int *
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} int *&
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} int &&
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} int &
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} const int &
+CHECK-DAG: Type{{.*}} , name = "Func3", {{.*}}, compiler_type = {{.*}} void (int *&, int &, const int &, int &&)
// FIXME: __unaligned is not supported.
-CHECK: Type{{.*}} , name = "Func4", {{.*}}, compiler_type = {{.*}} void (int *, int *)
+CHECK-DAG: Type{{.*}} , name = "Func4", {{.*}}, compiler_type = {{.*}} void (int *, int *)
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int *__restrict
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} int &__restrict
-CHECK: Type{{.*}} , name = "Func5", {{.*}}, compiler_type = {{.*}} void (int, int *__restrict, int &__restrict)
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} int *__restrict
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} int &__restrict
+CHECK-DAG: Type{{.*}} , name = "Func5", {{.*}}, compiler_type = {{.*}} void (int, int *__restrict, int &__restrict)
-CHECK: Type{{.*}} , name = "Func6", {{.*}}, compiler_type = {{.*}} void (const volatile int *__restrict)
+CHECK-DAG: Type{{.*}} , name = "Func6", {{.*}}, compiler_type = {{.*}} void (const volatile int *__restrict)
-CHECK: Type{{.*}} , size = 400, compiler_type = {{.*}} volatile int *[100]
-CHECK: Type{{.*}} , size = 4000, compiler_type = {{.*}} volatile int *[10][100]
+CHECK-DAG: Type{{.*}} , size = 400, compiler_type = {{.*}} volatile int *[100]
+CHECK-DAG: Type{{.*}} , size = 4000, compiler_type = {{.*}} volatile int *[10][100]
-CHECK: Type{{.*}} , size = 4, compiler_type = {{.*}} long *__restrict
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} long *__restrict
CHECK-DAG: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\TypeQualsTest.cpp'
diff --git a/lit/SymbolFile/PDB/typedefs.test b/lit/SymbolFile/PDB/typedefs.test
index 659ef6392d1c..caf23a8c1664 100644
--- a/lit/SymbolFile/PDB/typedefs.test
+++ b/lit/SymbolFile/PDB/typedefs.test
@@ -1,6 +1,5 @@
-REQUIRES: windows
-RUN: clang-cl -m32 /Z7 /c /GS- %S/Inputs/SimpleTypesTest.cpp /o %T/SimpleTypesTest.cpp.typedefs.obj
-RUN: link %T/SimpleTypesTest.cpp.typedefs.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/SimpleTypesTest.cpp.typedefs.exe
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%T/SimpleTypesTest.cpp.typedefs.exe %S/Inputs/SimpleTypesTest.cpp
RUN: lldb-test symbols %T/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s
; Generate 32-bit target
@@ -13,7 +12,7 @@ RUN: lldb-test symbols %T/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s
; both of them is the same.
CHECK: Module [[MOD:.*]]
-CHECK: {{^[0-9A-F]+}}: SymbolVendor ([[MOD]])
+CHECK: {{^[0-9A-F]+}}: SymbolVendor pdb ([[MOD]])
CHECK-DAG: name = "char32_t", size = 4, compiler_type = {{.*}} char32_t
CHECK-DAG: name = "char16_t", size = 2, compiler_type = {{.*}} char16_t
CHECK-DAG: Type{{.*}} , name = "unsigned long", size = 4, compiler_type = {{.*}} unsigned long
@@ -46,9 +45,10 @@ CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} void *
CHECK-DAG: Type{{.*}} , name = "long", size = 4, compiler_type = {{.*}} long
CHECK-DAG: Type{{.*}} , name = "unsigned short", size = 2, compiler_type = {{.*}} unsigned short
CHECK-DAG: Type{{.*}} , name = "unsigned int", size = 4, compiler_type = {{.*}} unsigned int
+CHECK-DAG: Type{{.*}} , name = "char", size = 1, compiler_type = {{.*}} char
CHECK-DAG: Type{{.*}} , name = "signed char", size = 1, compiler_type = {{.*}} signed char
-CHECK-DAG: Type{{.*}} , compiler_type = {{.*}} signed char (void *, long, unsigned short, unsigned int, ...)
-CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} signed char (*)(void *, long, unsigned short, unsigned int, ...)
+CHECK-DAG: Type{{.*}} , compiler_type = {{.*}} char (void *, long, unsigned short, unsigned int, ...)
+CHECK-DAG: Type{{.*}} , size = 4, compiler_type = {{.*}} char (*)(void *, long, unsigned short, unsigned int, ...)
CHECK-DAG: Type{{.*}} , name = "VarArgsFuncTypedef", compiler_type = {{.*}} typedef VarArgsFuncTypedef
CHECK-DAG: Type{{.*}} , name = "float", size = 4, compiler_type = {{.*}} float
diff --git a/lit/SymbolFile/PDB/udt-layout.test b/lit/SymbolFile/PDB/udt-layout.test
new file mode 100644
index 000000000000..726f633efe5b
--- /dev/null
+++ b/lit/SymbolFile/PDB/udt-layout.test
@@ -0,0 +1,51 @@
+REQUIRES: system-windows, lld
+RUN: %build --compiler=clang-cl --output=%t.exe %S/Inputs/UdtLayoutTest.cpp
+RUN: %lldb -b -s %S/Inputs/UdtLayoutTest.script -- %t.exe | FileCheck %s
+
+CHECK:(int) int C::abc = 123
+CHECK:(List [16]) ls = {
+CHECK: [15] = {
+CHECK: Prev = 0x00000000
+CHECK: Next = 0x00000000
+CHECK: Value = {
+CHECK: B<0> = {
+CHECK: A = {
+CHECK: _u = (_u1 = '\x02', _u2 = 2, _u3 = 2)
+CHECK: }
+CHECK: _a = '\x01'
+CHECK: _b = 2
+CHECK: _c = 3
+CHECK: }
+CHECK: B<1> = {
+CHECK: A = {
+CHECK: _u = (_u1 = '\x02', _u2 = 2, _u3 = 2)
+CHECK: }
+CHECK: _a = '\x02'
+CHECK: _b = 4
+CHECK: _c = 6
+CHECK: }
+CHECK: B<2> = {
+CHECK: A = {
+CHECK: _u = (_u1 = '\x02', _u2 = 2, _u3 = 2)
+CHECK: }
+CHECK: _a = '\x03'
+CHECK: _b = 6
+CHECK: _c = 9
+CHECK: }
+CHECK: B<3> = {
+CHECK: A = {
+CHECK: _u = (_u1 = '\x02', _u2 = 2, _u3 = 2)
+CHECK: }
+CHECK: _a = '\x04'
+CHECK: _b = 8
+CHECK: _c = 12
+CHECK: }
+CHECK: A = {
+CHECK: _u = (_u1 = '\x02', _u2 = 2, _u3 = 2)
+CHECK: }
+CHECK: _x = 5
+CHECK: _y = 10
+CHECK: _z = '\x0f'
+CHECK: }
+CHECK: }
+CHECK:}
diff --git a/lit/SymbolFile/PDB/variables-locations.test b/lit/SymbolFile/PDB/variables-locations.test
index b70339fa23ac..7696dc92cee8 100644
--- a/lit/SymbolFile/PDB/variables-locations.test
+++ b/lit/SymbolFile/PDB/variables-locations.test
@@ -1,6 +1,6 @@
-REQUIRES: windows
-RUN: clang-cl /Zi %S/Inputs/VariablesLocationsTest.cpp /o %t.exe
-RUN: %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s
+REQUIRES: system-windows, lld
+RUN: %build --compiler=clang-cl --output=%t.exe %S/Inputs/VariablesLocationsTest.cpp
+RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s
CHECK: g_var = 2222
diff --git a/lit/SymbolFile/PDB/variables.test b/lit/SymbolFile/PDB/variables.test
index 6d37cd975b45..2e9b59471091 100644
--- a/lit/SymbolFile/PDB/variables.test
+++ b/lit/SymbolFile/PDB/variables.test
@@ -1,58 +1,66 @@
-REQUIRES: windows
-RUN: clang-cl /Z7 /c /GS- %S/Inputs/VariablesTest.cpp /o %T/VariablesTest.cpp.obj
-RUN: link %T/VariablesTest.cpp.obj /DEBUG /nodefaultlib /ENTRY:main /OUT:%T/VariablesTest.cpp.exe
-RUN: lldb-test symbols %T/VariablesTest.cpp.exe | FileCheck %s
+REQUIRES: system-windows, msvc
+RUN: %build --compiler=clang-cl --mode=compile --arch=64 --nodefaultlib --output=%T/VariablesTest.cpp.obj %S/Inputs/VariablesTest.cpp
+RUN: %build --compiler=msvc --mode=link --arch=64 --nodefaultlib --output=%T/VariablesTest.cpp.exe %T/VariablesTest.cpp.obj
+RUN: lldb-test symbols %T/VariablesTest.cpp.exe > %T/VariablesTest.out
+RUN: FileCheck --check-prefix=GLOBALS --input-file=%T/VariablesTest.out %s
+RUN: FileCheck --check-prefix=FUNC-F --input-file=%T/VariablesTest.out %s
+RUN: FileCheck --check-prefix=FUNC-MAIN --input-file=%T/VariablesTest.out %s
+RUN: FileCheck --check-prefix=FUNC-CONSTRUCTOR --input-file=%T/VariablesTest.out %s
+RUN: FileCheck --check-prefix=FUNC-MEMBER --input-file=%T/VariablesTest.out %s
-CHECK: Module [[MOD:.*]]
-CHECK: SymbolVendor ([[MOD]])
-CHECK: CompileUnit{{.*}}, language = "c++", file = '{{.*}}\VariablesTest.cpp'
-CHECK-DAG: Variable{{.*}}, name = "g_IntVar"
-CHECK-SAME: scope = global, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "m_StaticClassMember"
-CHECK-SAME: scope = global, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "g_pConst"
-CHECK-SAME: scope = global, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "same_name_var"
-CHECK-SAME: scope = global, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "g_EnumVar"
-CHECK-SAME: scope = global, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "g_tls"
-CHECK-SAME: scope = thread local, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "ClassVar"
-CHECK-SAME: scope = global, location = {{.*}}, external
-CHECK-DAG: Variable{{.*}}, name = "g_Const"
-CHECK-SAME: scope = ??? (2)
+GLOBALS: Module [[MOD:.*]]
+GLOBALS: SymbolVendor pdb ([[MOD]])
+GLOBALS: CompileUnit{{.*}}, language = "c++", file = '{{.*}}\VariablesTest.cpp'
+GLOBALS-DAG: Variable{{.*}}, name = "g_IntVar"
+GLOBALS-SAME: scope = global, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "m_StaticClassMember"
+GLOBALS-SAME: scope = global, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "g_pConst"
+GLOBALS-SAME: scope = global, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "same_name_var"
+GLOBALS-SAME: scope = global, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "g_EnumVar"
+GLOBALS-SAME: scope = global, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "g_tls"
+GLOBALS-SAME: scope = thread local, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "ClassVar"
+GLOBALS-SAME: scope = global, location = {{.*}}, external
+GLOBALS-DAG: Variable{{.*}}, name = "g_Const"
+GLOBALS-SAME: scope = ??? (2)
+GLOBALS: Function
-CHECK-DAG: Function{[[FID1:.*]]}, mangled = ?f@@YAHHH@Z
-CHECK-NEXT: Block{[[FID1]]}
-CHECK-DAG: Variable{{.*}}, name = "var_arg1"
-CHECK-SAME: scope = parameter
-CHECK-DAG: Variable{{.*}}, name = "var_arg2"
-CHECK-SAME: scope = parameter
-CHECK-DAG: Variable{{.*}}, name = "same_name_var"
-CHECK-SAME: scope = local
+FUNC-F: Function{{.*}}, mangled = ?f@@YAHHH@Z
+FUNC-F-NEXT: Block
+FUNC-F-NEXT: Variable{{.*}}, name = "var_arg1"
+FUNC-F-SAME: scope = parameter
+FUNC-F-NEXT: Variable{{.*}}, name = "var_arg2"
+FUNC-F-SAME: scope = parameter
+FUNC-F-NEXT: Variable{{.*}}, name = "same_name_var"
+FUNC-F-SAME: scope = local
-CHECK-DAG: Function{[[FID2:.*]]}, mangled = main
-CHECK-NEXT: Block{[[FID2]]}
-CHECK-DAG: Variable{{.*}}, name = "same_name_var"
-CHECK-SAME: scope = local
-CHECK-DAG: Variable{{.*}}, name = "local_const"
-CHECK-SAME: scope = local
-CHECK-DAG: Variable{{.*}}, name = "local_pCString"
-CHECK-SAME: scope = local
-CHECK-DAG: Variable{{.*}}, name = "a"
-CHECK-SAME: scope = local
+FUNC-MAIN: Function{{.*}}, mangled = main
+FUNC-MAIN-NEXT: Block
+FUNC-MAIN-NEXT: Variable{{.*}}, name = "same_name_var"
+FUNC-MAIN-SAME: scope = local
+FUNC-MAIN-NEXT: Variable{{.*}}, name = "local_const"
+FUNC-MAIN-SAME: scope = local
+FUNC-MAIN-NEXT: Variable{{.*}}, name = "local_CString"
+FUNC-MAIN-SAME: scope = local
+FUNC-MAIN-NEXT: Variable{{.*}}, name = "local_pCString"
+FUNC-MAIN-SAME: scope = local
+FUNC-MAIN-NEXT: Variable{{.*}}, name = "a"
+FUNC-MAIN-SAME: scope = local
-CHECK-DAG: Function{[[FID3:.*]]}, mangled = ??0Class@@QEAA@H@Z
-CHECK-NEXT: Block{[[FID3]]}
-CHECK-DAG: Variable{{.*}}, name = "this"
-CHECK-SAME: scope = parameter
-CHECK-SAME: artificial
-CHECK-DAG: Variable{{.*}}, name = "a"
-CHECK-SAME: scope = parameter
+FUNC-CONSTRUCTOR: Function{{.*}}, mangled = ??0Class@@QEAA@H@Z
+FUNC-CONSTRUCTOR-NEXT: Block
+FUNC-CONSTRUCTOR-NEXT: Variable{{.*}}, name = "this"
+FUNC-CONSTRUCTOR-SAME: scope = parameter
+FUNC-CONSTRUCTOR-SAME: artificial
+FUNC-CONSTRUCTOR-NEXT: Variable{{.*}}, name = "a"
+FUNC-CONSTRUCTOR-SAME: scope = parameter
-CHECK-DAG: Function{[[FID4:.*]]}, mangled = ?Func@Class@@QEAAXXZ
-CHECK-NEXT: Block{[[FID4]]}
-CHECK-DAG: Variable{{.*}}, name = "this"
-CHECK-SAME: scope = parameter
-CHECK-SAME: artificial \ No newline at end of file
+FUNC-MEMBER: Function{{.*}}, mangled = ?Func@Class@@QEAAXXZ
+FUNC-MEMBER-NEXT: Block
+FUNC-MEMBER-NEXT: Variable{{.*}}, name = "this"
+FUNC-MEMBER-SAME: scope = parameter
+FUNC-MEMBER-SAME: artificial
diff --git a/lit/SymbolFile/PDB/vbases.test b/lit/SymbolFile/PDB/vbases.test
new file mode 100644
index 000000000000..57239e07c87d
--- /dev/null
+++ b/lit/SymbolFile/PDB/vbases.test
@@ -0,0 +1,15 @@
+REQUIRES: system-windows, lld
+RUN: %build --compiler=clang-cl --output=%t.exe %S/Inputs/VBases.cpp
+RUN: %lldb -b -s %S/Inputs/VBases.script -- %t.exe | FileCheck %s
+
+CHECK: {
+CHECK: A = (a = '\x01')
+CHECK: B = (b = 2)
+CHECK: c = 3
+CHECK: }
+
+CHECK: {
+CHECK: A = (a = '\x01')
+CHECK: B = (b = 2)
+CHECK: c = 3
+CHECK: }
diff --git a/lit/Unit/lit.cfg b/lit/Unit/lit.cfg.py
index 338adfd7bd9a..3633c73a1d40 100644
--- a/lit/Unit/lit.cfg
+++ b/lit/Unit/lit.cfg.py
@@ -3,8 +3,10 @@
# Configuration file for the 'lit' test runner.
import os
+import sys
import lit.formats
+from lit.llvm import llvm_config
# name: The name of this test suite.
config.name = 'lldb-Unit'
@@ -17,5 +19,12 @@ config.suffixes = []
config.test_source_root = os.path.join(config.lldb_obj_root, 'unittests')
config.test_exec_root = config.test_source_root
+# One of our unit tests dynamically links against python.dll, and on Windows
+# it needs to be able to find it at runtime. This is fine if Python is on your
+# system PATH, but if it's not, then this unit test executable will fail to run.
+# We can solve this by forcing the Python directory onto the system path here.
+llvm_config.with_system_environment('PATH')
+llvm_config.with_environment('PATH', os.path.dirname(sys.executable), append_path=True)
+
# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.GoogleTest(config.llvm_build_mode, 'Tests')
diff --git a/lit/Unit/lit.site.cfg.in b/lit/Unit/lit.site.cfg.py.in
index 9c43172e61e0..0c629fdfaa56 100644
--- a/lit/Unit/lit.site.cfg.in
+++ b/lit/Unit/lit.site.cfg.py.in
@@ -1,6 +1,6 @@
@LIT_SITE_CFG_IN_HEADER@
-config.test_exec_root = "@LLVM_BINARY_DIR@"
+config.test_exec_root = "@LLDB_BINARY_DIR@"
config.llvm_src_root = "@LLVM_SOURCE_DIR@"
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
@@ -22,5 +22,8 @@ except KeyError as e:
key, = e.args
lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
+import lit.llvm
+lit.llvm.initialize(lit_config, config)
+
# Let the main config do the real work.
-lit_config.load_config(config, "@LLDB_SOURCE_DIR@/lit/Unit/lit.cfg")
+lit_config.load_config(config, "@LLDB_SOURCE_DIR@/lit/Unit/lit.cfg.py")
diff --git a/lit/helper/__init__.py b/lit/helper/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/lit/helper/__init__.py
diff --git a/lit/helper/build.py b/lit/helper/build.py
new file mode 100755
index 000000000000..26f321d709f8
--- /dev/null
+++ b/lit/helper/build.py
@@ -0,0 +1,787 @@
+#! /usr/bin/env python
+
+from __future__ import print_function
+
+import argparse
+import os
+import signal
+import subprocess
+import sys
+
+if sys.platform == 'win32':
+ # This module was renamed in Python 3. Make sure to import it using a
+ # consistent name regardless of python version.
+ try:
+ import winreg
+ except:
+ import _winreg as winreg
+
+if __name__ != "__main__":
+ raise RuntimeError("Do not import this script, run it instead")
+
+
+parser = argparse.ArgumentParser(description='LLDB compilation wrapper')
+parser.add_argument('--arch',
+ metavar='arch',
+ dest='arch',
+ required=True,
+ default='host',
+ choices=['32', '64', 'host'],
+ help='Specify the architecture to target.')
+
+parser.add_argument('--compiler',
+ metavar='compiler',
+ dest='compiler',
+ required=True,
+ help='Path to a compiler executable, or one of the values [any, msvc, clang-cl, gcc, clang]')
+
+parser.add_argument('--tools-dir',
+ metavar='directory',
+ dest='tools_dir',
+ required=False,
+ action='append',
+ help='If specified, a path to search in addition to PATH when --compiler is not an exact path')
+
+if sys.platform == 'darwin':
+ parser.add_argument('--apple-sdk',
+ metavar='apple_sdk',
+ dest='apple_sdk',
+ default="macosx",
+ help='Specify the name of the Apple SDK (macosx, macosx.internal, iphoneos, iphoneos.internal, or path to SDK) and use the appropriate tools from that SDK\'s toolchain.')
+
+parser.add_argument('--output', '-o',
+ dest='output',
+ metavar='file',
+ required=False,
+ default='',
+ help='Path to output file')
+
+parser.add_argument('--outdir', '-d',
+ dest='outdir',
+ metavar='directory',
+ required=False,
+ help='Directory for output files')
+
+parser.add_argument('--nodefaultlib',
+ dest='nodefaultlib',
+ action='store_true',
+ default=False,
+ help='When specified, the resulting image should not link against system libraries or include system headers. Useful when writing cross-targeting tests.')
+
+parser.add_argument('--opt',
+ dest='opt',
+ default='none',
+ choices=['none', 'basic', 'lto'],
+ help='Optimization level')
+
+parser.add_argument('--mode',
+ dest='mode',
+ default='compile-and-link',
+ choices=['compile', 'link', 'compile-and-link'],
+ help='Specifies whether to compile, link, or both')
+
+parser.add_argument('--noclean',
+ dest='clean',
+ action='store_false',
+ default=True,
+ help='Dont clean output file before building')
+
+parser.add_argument('--verbose',
+ dest='verbose',
+ action='store_true',
+ default=False,
+ help='Print verbose output')
+
+parser.add_argument('-n', '--dry-run',
+ dest='dry',
+ action='store_true',
+ default=False,
+ help='Print the commands that would run, but dont actually run them')
+
+parser.add_argument('inputs',
+ metavar='file',
+ nargs='+',
+ help='Source file(s) to compile / object file(s) to link')
+
+
+args = parser.parse_args(args=sys.argv[1:])
+
+
+def to_string(b):
+ """Return the parameter as type 'str', possibly encoding it.
+
+ In Python2, the 'str' type is the same as 'bytes'. In Python3, the
+ 'str' type is (essentially) Python2's 'unicode' type, and 'bytes' is
+ distinct.
+
+ This function is copied from llvm/utils/lit/lit/util.py
+ """
+ if isinstance(b, str):
+ # In Python2, this branch is taken for types 'str' and 'bytes'.
+ # In Python3, this branch is taken only for 'str'.
+ return b
+ if isinstance(b, bytes):
+ # In Python2, this branch is never taken ('bytes' is handled as 'str').
+ # In Python3, this is true only for 'bytes'.
+ try:
+ return b.decode('utf-8')
+ except UnicodeDecodeError:
+ # If the value is not valid Unicode, return the default
+ # repr-line encoding.
+ return str(b)
+
+ # By this point, here's what we *don't* have:
+ #
+ # - In Python2:
+ # - 'str' or 'bytes' (1st branch above)
+ # - In Python3:
+ # - 'str' (1st branch above)
+ # - 'bytes' (2nd branch above)
+ #
+ # The last type we might expect is the Python2 'unicode' type. There is no
+ # 'unicode' type in Python3 (all the Python3 cases were already handled). In
+ # order to get a 'str' object, we need to encode the 'unicode' object.
+ try:
+ return b.encode('utf-8')
+ except AttributeError:
+ raise TypeError('not sure how to convert %s to %s' % (type(b), str))
+
+def format_text(lines, indent_0, indent_n):
+ result = ' ' * indent_0 + lines[0]
+ for next in lines[1:]:
+ result = result + '\n{0}{1}'.format(' ' * indent_n, next)
+ return result
+
+def print_environment(env):
+ if env is None:
+ print(' Inherited')
+ return
+ for e in env:
+ value = env[e]
+ lines = value.split(os.pathsep)
+ formatted_value = format_text(lines, 0, 7 + len(e))
+ print(' {0} = {1}'.format(e, formatted_value))
+
+def find_executable(binary_name, search_paths):
+ if sys.platform == 'win32':
+ binary_name = binary_name + '.exe'
+
+ search_paths = os.pathsep.join(search_paths)
+ paths = search_paths + os.pathsep + os.environ.get('PATH', '')
+ for path in paths.split(os.pathsep):
+ p = os.path.join(path, binary_name)
+ if os.path.exists(p) and not os.path.isdir(p):
+ return os.path.normpath(p)
+ return None
+
+def find_toolchain(compiler, tools_dir):
+ if compiler == 'msvc':
+ return ('msvc', find_executable('cl', tools_dir))
+ if compiler == 'clang-cl':
+ return ('clang-cl', find_executable('clang-cl', tools_dir))
+ if compiler == 'gcc':
+ return ('gcc', find_executable('g++', tools_dir))
+ if compiler == 'clang':
+ return ('clang', find_executable('clang++', tools_dir))
+ if compiler == 'any':
+ priorities = []
+ if sys.platform == 'win32':
+ priorities = ['clang-cl', 'msvc', 'clang', 'gcc']
+ else:
+ priorities = ['clang', 'gcc', 'clang-cl']
+ for toolchain in priorities:
+ (type, dir) = find_toolchain(toolchain, tools_dir)
+ if type and dir:
+ return (type, dir)
+ # Could not find any toolchain.
+ return (None, None)
+
+ # From here on, assume that |compiler| is a path to a file.
+ file = os.path.basename(compiler)
+ name, ext = os.path.splitext(file)
+ if file.lower() == 'cl.exe':
+ return 'msvc'
+ if name == 'clang-cl':
+ return 'clang-cl'
+ if name.startswith('clang'):
+ return 'clang'
+ if name.startswith('gcc') or name.startswith('g++'):
+ return 'gcc'
+ if name == 'cc' or name == 'c++':
+ return 'generic'
+ return 'unknown'
+
+class Builder(object):
+ def __init__(self, toolchain_type, args, obj_ext):
+ self.toolchain_type = toolchain_type
+ self.inputs = args.inputs
+ self.arch = args.arch
+ self.opt = args.opt
+ self.outdir = args.outdir
+ self.compiler = args.compiler
+ self.clean = args.clean
+ self.output = args.output
+ self.mode = args.mode
+ self.nodefaultlib = args.nodefaultlib
+ self.verbose = args.verbose
+ self.obj_ext = obj_ext
+
+ def _exe_file_name(self):
+ assert self.mode != 'compile'
+ return self.output
+
+ def _output_name(self, input, extension, with_executable=False):
+ basename = os.path.splitext(os.path.basename(input))[0] + extension
+ if with_executable:
+ exe_basename = os.path.basename(self._exe_file_name())
+ basename = exe_basename + '-' + basename
+
+ output = os.path.join(self.outdir, basename)
+ return os.path.normpath(output)
+
+ def _obj_file_names(self):
+ if self.mode == 'link':
+ return self.inputs
+
+ if self.mode == 'compile-and-link':
+ # Object file names should factor in both the input file (source)
+ # name and output file (executable) name, to ensure that two tests
+ # which share a common source file don't race to write the same
+ # object file.
+ return [self._output_name(x, self.obj_ext, True) for x in self.inputs]
+
+ if self.mode == 'compile' and self.output:
+ return [self.output]
+
+ return [self._output_name(x, self.obj_ext) for x in self.inputs]
+
+ def build_commands(self):
+ commands = []
+ if self.mode == 'compile' or self.mode == 'compile-and-link':
+ for input, output in zip(self.inputs, self._obj_file_names()):
+ commands.append(self._get_compilation_command(input, output))
+ if self.mode == 'link' or self.mode == 'compile-and-link':
+ commands.append(self._get_link_command())
+ return commands
+
+
+class MsvcBuilder(Builder):
+ def __init__(self, toolchain_type, args):
+ Builder.__init__(self, toolchain_type, args, '.obj')
+
+ self.msvc_arch_str = 'x86' if self.arch == '32' else 'x64'
+
+ if toolchain_type == 'msvc':
+ # Make sure we're using the appropriate toolchain for the desired
+ # target type.
+ compiler_parent_dir = os.path.dirname(self.compiler)
+ selected_target_version = os.path.basename(compiler_parent_dir)
+ if selected_target_version != self.msvc_arch_str:
+ host_dir = os.path.dirname(compiler_parent_dir)
+ self.compiler = os.path.join(host_dir, self.msvc_arch_str, 'cl.exe')
+ if self.verbose:
+ print('Using alternate compiler "{0}" to match selected target.'.format(self.compiler))
+
+ if self.mode == 'link' or self.mode == 'compile-and-link':
+ self.linker = self._find_linker('link') if toolchain_type == 'msvc' else self._find_linker('lld-link')
+ if not self.linker:
+ raise ValueError('Unable to find an appropriate linker.')
+
+ self.compile_env, self.link_env = self._get_visual_studio_environment()
+
+ def _find_linker(self, name):
+ if sys.platform == 'win32':
+ name = name + '.exe'
+ compiler_dir = os.path.dirname(self.compiler)
+ linker_path = os.path.join(compiler_dir, name)
+ if not os.path.exists(linker_path):
+ raise ValueError('Could not find \'{}\''.format(linker_path))
+ return linker_path
+
+ def _get_vc_install_dir(self):
+ dir = os.getenv('VCINSTALLDIR', None)
+ if dir:
+ if self.verbose:
+ print('Using %VCINSTALLDIR% {}'.format(dir))
+ return dir
+
+ dir = os.getenv('VSINSTALLDIR', None)
+ if dir:
+ if self.verbose:
+ print('Using %VSINSTALLDIR% {}'.format(dir))
+ return os.path.join(dir, 'VC')
+
+ dir = os.getenv('VS2019INSTALLDIR', None)
+ if dir:
+ if self.verbose:
+ print('Using %VS2019INSTALLDIR% {}'.format(dir))
+ return os.path.join(dir, 'VC')
+
+ dir = os.getenv('VS2017INSTALLDIR', None)
+ if dir:
+ if self.verbose:
+ print('Using %VS2017INSTALLDIR% {}'.format(dir))
+ return os.path.join(dir, 'VC')
+
+ dir = os.getenv('VS2015INSTALLDIR', None)
+ if dir:
+ if self.verbose:
+ print('Using %VS2015INSTALLDIR% {}'.format(dir))
+ return os.path.join(dir, 'VC')
+ return None
+
+ def _get_vctools_version(self):
+ ver = os.getenv('VCToolsVersion', None)
+ if ver:
+ if self.verbose:
+ print('Using %VCToolsVersion% {}'.format(ver))
+ return ver
+
+ vcinstalldir = self._get_vc_install_dir()
+ vcinstalldir = os.path.join(vcinstalldir, 'Tools', 'MSVC')
+ subdirs = next(os.walk(vcinstalldir))[1]
+ if not subdirs:
+ return None
+
+ from distutils.version import StrictVersion
+ subdirs.sort(key=lambda x : StrictVersion(x))
+
+ if self.verbose:
+ full_path = os.path.join(vcinstalldir, subdirs[-1])
+ print('Using VC tools version directory {0} found by directory walk.'.format(full_path))
+ return subdirs[-1]
+
+ def _get_vctools_install_dir(self):
+ dir = os.getenv('VCToolsInstallDir', None)
+ if dir:
+ if self.verbose:
+ print('Using %VCToolsInstallDir% {}'.format(dir))
+ return dir
+
+ vcinstalldir = self._get_vc_install_dir()
+ if not vcinstalldir:
+ return None
+ vctoolsver = self._get_vctools_version()
+ if not vctoolsver:
+ return None
+ result = os.path.join(vcinstalldir, 'Tools', 'MSVC', vctoolsver)
+ if not os.path.exists(result):
+ return None
+ if self.verbose:
+ print('Using VC tools install dir {} found by directory walk'.format(result))
+ return result
+
+ def _find_windows_sdk_in_registry_view(self, view):
+ products_key = None
+ roots_key = None
+ installed_options_keys = []
+ try:
+ sam = view | winreg.KEY_READ
+ products_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
+ r'Software\Microsoft\Windows Kits\Installed Products',
+ 0,
+ sam)
+
+ # This is the GUID for the desktop component. If this is present
+ # then the components required for the Desktop SDK are installed.
+ # If not it will throw an exception.
+ winreg.QueryValueEx(products_key, '{5A3D81EC-D870-9ECF-D997-24BDA6644752}')
+
+ roots_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,
+ r'Software\Microsoft\Windows Kits\Installed Roots',
+ 0,
+ sam)
+ root_dir = winreg.QueryValueEx(roots_key, 'KitsRoot10')
+ root_dir = to_string(root_dir[0])
+ sdk_versions = []
+ index = 0
+ while True:
+ # Installed SDK versions are stored as sub-keys of the
+ # 'Installed Roots' key. Find all of their names, then sort
+ # them by version
+ try:
+ ver_key = winreg.EnumKey(roots_key, index)
+ sdk_versions.append(ver_key)
+ index = index + 1
+ except WindowsError:
+ break
+ if not sdk_versions:
+ return (None, None)
+
+ # Windows SDK version numbers consist of 4 dotted components, so we
+ # have to use LooseVersion, as StrictVersion supports 3 or fewer.
+ from distutils.version import LooseVersion
+ sdk_versions.sort(key=lambda x : LooseVersion(x), reverse=True)
+ option_value_name = 'OptionId.DesktopCPP' + self.msvc_arch_str
+ for v in sdk_versions:
+ try:
+ version_subkey = v + r'\Installed Options'
+ key = winreg.OpenKey(roots_key, version_subkey)
+ installed_options_keys.append(key)
+ (value, value_type) = winreg.QueryValueEx(key, option_value_name)
+ if value == 1:
+ # The proper architecture is installed. Return the
+ # associated paths.
+ if self.verbose:
+ print('Found Installed Windows SDK v{0} at {1}'.format(v, root_dir))
+ return (root_dir, v)
+ except:
+ continue
+ except:
+ return (None, None)
+ finally:
+ del products_key
+ del roots_key
+ for k in installed_options_keys:
+ del k
+ return (None, None)
+
+ def _find_windows_sdk_in_registry(self):
+ # This could be a clang-cl cross-compile. If so, there's no registry
+ # so just exit.
+ if sys.platform != 'win32':
+ return (None, None)
+ if self.verbose:
+ print('Looking for Windows SDK in 64-bit registry.')
+ dir, ver = self._find_windows_sdk_in_registry_view(winreg.KEY_WOW64_64KEY)
+ if not dir or not ver:
+ if self.verbose:
+ print('Looking for Windows SDK in 32-bit registry.')
+ dir, ver = self._find_windows_sdk_in_registry_view(winreg.KEY_WOW64_32KEY)
+
+ return (dir, ver)
+
+ def _get_winsdk_dir(self):
+ # If a Windows SDK is specified in the environment, use that. Otherwise
+ # try to find one in the Windows registry.
+ dir = os.getenv('WindowsSdkDir', None)
+ if not dir or not os.path.exists(dir):
+ return self._find_windows_sdk_in_registry()
+ ver = os.getenv('WindowsSDKLibVersion', None)
+ if not ver:
+ return self._find_windows_sdk_in_registry()
+
+ ver = ver.rstrip('\\')
+ if self.verbose:
+ print('Using %WindowsSdkDir% {}'.format(dir))
+ print('Using %WindowsSDKLibVersion% {}'.format(ver))
+ return (dir, ver)
+
+ def _get_msvc_native_toolchain_dir(self):
+ assert self.toolchain_type == 'msvc'
+ compiler_dir = os.path.dirname(self.compiler)
+ target_dir = os.path.dirname(compiler_dir)
+ host_name = os.path.basename(target_dir)
+ host_name = host_name[4:].lower()
+ return os.path.join(target_dir, host_name)
+
+ def _get_visual_studio_environment(self):
+ vctools = self._get_vctools_install_dir()
+ winsdk, winsdkver = self._get_winsdk_dir()
+
+ if not vctools and self.verbose:
+ print('Unable to find VC tools installation directory.')
+ if (not winsdk or not winsdkver) and self.verbose:
+ print('Unable to find Windows SDK directory.')
+
+ vcincludes = []
+ vclibs = []
+ sdkincludes = []
+ sdklibs = []
+ if vctools is not None:
+ includes = [['ATLMFC', 'include'], ['include']]
+ libs = [['ATLMFC', 'lib'], ['lib']]
+ vcincludes = [os.path.join(vctools, *y) for y in includes]
+ vclibs = [os.path.join(vctools, *y) for y in libs]
+ if winsdk is not None:
+ includes = [['include', winsdkver, 'ucrt'],
+ ['include', winsdkver, 'shared'],
+ ['include', winsdkver, 'um'],
+ ['include', winsdkver, 'winrt'],
+ ['include', winsdkver, 'cppwinrt']]
+ libs = [['lib', winsdkver, 'ucrt'],
+ ['lib', winsdkver, 'um']]
+ sdkincludes = [os.path.join(winsdk, *y) for y in includes]
+ sdklibs = [os.path.join(winsdk, *y) for y in libs]
+
+ includes = vcincludes + sdkincludes
+ libs = vclibs + sdklibs
+ libs = [os.path.join(x, self.msvc_arch_str) for x in libs]
+ compileenv = None
+ linkenv = None
+ defaultenv = {}
+ if sys.platform == 'win32':
+ defaultenv = { x : os.environ[x] for x in
+ ['SystemDrive', 'SystemRoot', 'TMP', 'TEMP'] }
+ # The directory to mspdbcore.dll needs to be in PATH, but this is
+ # always in the native toolchain path, not the cross-toolchain
+ # path. So, for example, if we're using HostX64\x86 then we need
+ # to add HostX64\x64 to the path, and if we're using HostX86\x64
+ # then we need to add HostX86\x86 to the path.
+ if self.toolchain_type == 'msvc':
+ defaultenv['PATH'] = self._get_msvc_native_toolchain_dir()
+
+ if includes:
+ compileenv = {}
+ compileenv['INCLUDE'] = os.pathsep.join(includes)
+ compileenv.update(defaultenv)
+ if libs:
+ linkenv = {}
+ linkenv['LIB'] = os.pathsep.join(libs)
+ linkenv.update(defaultenv)
+ return (compileenv, linkenv)
+
+ def _ilk_file_names(self):
+ if self.mode == 'link':
+ return []
+
+ return [self._output_name(x, '.ilk') for x in self.inputs]
+
+ def _pdb_file_name(self):
+ if self.mode == 'compile':
+ return None
+ return os.path.splitext(self.output)[0] + '.pdb'
+
+ def _get_compilation_command(self, source, obj):
+ args = []
+
+ args.append(self.compiler)
+ if self.toolchain_type == 'clang-cl':
+ args.append('-m' + self.arch)
+
+ if self.opt == 'none':
+ args.append('/Od')
+ elif self.opt == 'basic':
+ args.append('/O2')
+ elif self.opt == 'lto':
+ if self.toolchain_type == 'msvc':
+ args.append('/GL')
+ args.append('/Gw')
+ else:
+ args.append('-flto=thin')
+ if self.nodefaultlib:
+ args.append('/GS-')
+ args.append('/GR-')
+ args.append('/Z7')
+ if self.toolchain_type == 'clang-cl':
+ args.append('-Xclang')
+ args.append('-fkeep-static-consts')
+ args.append('/c')
+
+ args.append('/Fo' + obj)
+ args.append(source)
+
+ return ('compiling', [source], obj,
+ self.compile_env,
+ args)
+
+ def _get_link_command(self):
+ args = []
+ args.append(self.linker)
+ args.append('/DEBUG:FULL')
+ args.append('/INCREMENTAL:NO')
+ if self.nodefaultlib:
+ args.append('/nodefaultlib')
+ args.append('/entry:main')
+ args.append('/PDB:' + self._pdb_file_name())
+ args.append('/OUT:' + self._exe_file_name())
+ args.extend(self._obj_file_names())
+
+ return ('linking', self._obj_file_names(), self._exe_file_name(),
+ self.link_env,
+ args)
+
+ def build_commands(self):
+ commands = []
+ if self.mode == 'compile' or self.mode == 'compile-and-link':
+ for input, output in zip(self.inputs, self._obj_file_names()):
+ commands.append(self._get_compilation_command(input, output))
+ if self.mode == 'link' or self.mode == 'compile-and-link':
+ commands.append(self._get_link_command())
+ return commands
+
+ def output_files(self):
+ outputs = []
+ if self.mode == 'compile' or self.mode == 'compile-and-link':
+ outputs.extend(self._ilk_file_names())
+ outputs.extend(self._obj_file_names())
+ if self.mode == 'link' or self.mode == 'compile-and-link':
+ outputs.append(self._pdb_file_name())
+ outputs.append(self._exe_file_name())
+
+ return [x for x in outputs if x is not None]
+
+class GccBuilder(Builder):
+ def __init__(self, toolchain_type, args):
+ Builder.__init__(self, toolchain_type, args, '.o')
+
+ def _get_compilation_command(self, source, obj):
+ args = []
+
+ args.append(self.compiler)
+ args.append('-m' + self.arch)
+
+ args.append('-g')
+ if self.opt == 'none':
+ args.append('-O0')
+ elif self.opt == 'basic':
+ args.append('-O2')
+ elif self.opt == 'lto':
+ args.append('-flto=thin')
+ if self.nodefaultlib:
+ args.append('-nostdinc')
+ args.append('-static')
+ args.append('-c')
+
+ args.extend(['-o', obj])
+ args.append(source)
+
+ return ('compiling', [source], obj, None, args)
+
+ def _get_link_command(self):
+ args = []
+ args.append(self.compiler)
+ args.append('-m' + self.arch)
+ if self.nodefaultlib:
+ args.append('-nostdlib')
+ args.append('-static')
+ main_symbol = 'main'
+ if sys.platform == 'darwin':
+ main_symbol = '_main'
+ args.append('-Wl,-e,' + main_symbol)
+ args.extend(['-o', self._exe_file_name()])
+ args.extend(self._obj_file_names())
+
+ return ('linking', self._obj_file_names(), self._exe_file_name(), None, args)
+
+
+ def output_files(self):
+ outputs = []
+ if self.mode == 'compile' or self.mode == 'compile-and-link':
+ outputs.extend(self._obj_file_names())
+ if self.mode == 'link' or self.mode == 'compile-and-link':
+ outputs.append(self._exe_file_name())
+
+ return outputs
+
+def indent(text, spaces):
+ def prefixed_lines():
+ prefix = ' ' * spaces
+ for line in text.splitlines(True):
+ yield prefix + line
+ return ''.join(prefixed_lines())
+
+def build(commands):
+ global args
+ for (status, inputs, output, env, child_args) in commands:
+ print('\n\n')
+ inputs = [os.path.basename(x) for x in inputs]
+ output = os.path.basename(output)
+ print(status + ' {0} -> {1}'.format('+'.join(inputs), output))
+
+ if args.verbose:
+ print(' Command Line: ' + ' '.join(child_args))
+ print(' Env:')
+ print_environment(env)
+ if args.dry:
+ continue
+
+ popen = subprocess.Popen(child_args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env,
+ universal_newlines=True)
+ stdout, stderr = popen.communicate()
+ res = popen.wait()
+ if res == -signal.SIGINT:
+ raise KeyboardInterrupt
+ print(' STDOUT:')
+ print(indent(stdout, 4))
+ if res != 0:
+ print(' STDERR:')
+ print(indent(stderr, 4))
+ sys.exit(res)
+
+def clean(files):
+ global args
+ if not files:
+ return
+ for o in files:
+ file = o if args.verbose else os.path.basename(o)
+ print('Cleaning {0}'.format(file))
+ try:
+ if os.path.exists(o):
+ if not args.dry:
+ os.remove(o)
+ if args.verbose:
+ print(' The file was successfully cleaned.')
+ elif args.verbose:
+ print(' The file does not exist.')
+ except:
+ if args.verbose:
+ print(' The file could not be removed.')
+
+def fix_arguments(args):
+ if not args.inputs:
+ raise ValueError('No input files specified')
+
+ if args.output and args.mode == 'compile' and len(args.inputs) > 1:
+ raise ValueError('Cannot specify -o with mode=compile and multiple source files. Use --outdir instead.')
+
+ if not args.dry:
+ args.inputs = [os.path.abspath(x) for x in args.inputs]
+
+ # If user didn't specify the outdir, use the directory of the first input.
+ if not args.outdir:
+ if args.output:
+ args.outdir = os.path.dirname(args.output)
+ else:
+ args.outdir = os.path.dirname(args.inputs[0])
+ args.outdir = os.path.abspath(args.outdir)
+ args.outdir = os.path.normpath(args.outdir)
+
+ # If user specified a non-absolute path for the output file, append the
+ # output directory to it.
+ if args.output:
+ if not os.path.isabs(args.output):
+ args.output = os.path.join(args.outdir, args.output)
+ args.output = os.path.normpath(args.output)
+
+fix_arguments(args)
+
+(toolchain_type, toolchain_path) = find_toolchain(args.compiler, args.tools_dir)
+if not toolchain_path or not toolchain_type:
+ print('Unable to find toolchain {0}'.format(args.compiler))
+ sys.exit(1)
+
+if args.verbose:
+ print('Script Arguments:')
+ print(' Arch: ' + args.arch)
+ print(' Compiler: ' + args.compiler)
+ print(' Outdir: ' + args.outdir)
+ print(' Output: ' + args.output)
+ print(' Nodefaultlib: ' + str(args.nodefaultlib))
+ print(' Opt: ' + args.opt)
+ print(' Mode: ' + args.mode)
+ print(' Clean: ' + str(args.clean))
+ print(' Verbose: ' + str(args.verbose))
+ print(' Dryrun: ' + str(args.dry))
+ print(' Inputs: ' + format_text(args.inputs, 0, 10))
+ print('Script Environment:')
+ print_environment(os.environ)
+
+args.compiler = toolchain_path
+if not os.path.exists(args.compiler) and not args.dry:
+ raise ValueError('The toolchain {} does not exist.'.format(args.compiler))
+
+if toolchain_type == 'msvc' or toolchain_type=='clang-cl':
+ builder = MsvcBuilder(toolchain_type, args)
+else:
+ builder = GccBuilder(toolchain_type, args)
+
+if args.clean:
+ clean(builder.output_files())
+
+cmds = builder.build_commands()
+
+build(cmds)
diff --git a/lit/helper/toolchain.py b/lit/helper/toolchain.py
new file mode 100644
index 000000000000..938f343badcc
--- /dev/null
+++ b/lit/helper/toolchain.py
@@ -0,0 +1,122 @@
+import os
+import itertools
+import platform
+import subprocess
+import sys
+
+import lit.util
+from lit.llvm import llvm_config
+from lit.llvm.subst import FindTool
+from lit.llvm.subst import ToolSubst
+
+def use_lldb_substitutions(config):
+ # Set up substitutions for primary tools. These tools must come from config.lldb_tools_dir
+ # which is basically the build output directory. We do not want to find these in path or
+ # anywhere else, since they are specifically the programs which are actually being tested.
+
+ dsname = 'debugserver' if platform.system() in ['Darwin'] else 'lldb-server'
+ dsargs = [] if platform.system() in ['Darwin'] else ['gdbserver']
+ lldbmi = ToolSubst('%lldbmi',
+ command=FindTool('lldb-mi'),
+ extra_args=['--synchronous'],
+ unresolved='ignore')
+
+
+ build_script = os.path.dirname(__file__)
+ build_script = os.path.join(build_script, 'build.py')
+ build_script_args = [build_script,
+ '--compiler=any', # Default to best compiler
+ '--arch=' + str(config.lldb_bitness)]
+ if config.lldb_lit_tools_dir:
+ build_script_args.append('--tools-dir={0}'.format(config.lldb_lit_tools_dir))
+ if config.lldb_tools_dir:
+ build_script_args.append('--tools-dir={0}'.format(config.lldb_tools_dir))
+
+ primary_tools = [
+ ToolSubst('%lldb',
+ command=FindTool('lldb'),
+ extra_args=['-S',
+ os.path.join(config.test_source_root,
+ 'lit-lldb-init')]),
+ lldbmi,
+ ToolSubst('%debugserver',
+ command=FindTool(dsname),
+ extra_args=dsargs,
+ unresolved='ignore'),
+ 'lldb-test',
+ ToolSubst('%build',
+ command="'" + sys.executable + "'",
+ extra_args=build_script_args)
+ ]
+
+ llvm_config.add_tool_substitutions(primary_tools,
+ [config.lldb_tools_dir])
+ if lldbmi.was_resolved:
+ config.available_features.add('lldb-mi')
+
+def _use_msvc_substitutions(config):
+ # If running from a Visual Studio Command prompt (e.g. vcvars), this will
+ # detect the include and lib paths, and find cl.exe and link.exe and create
+ # substitutions for each of them that explicitly specify /I and /L paths
+ cl = lit.util.which('cl')
+ link = lit.util.which('link')
+
+ if not cl or not link:
+ return
+
+ cl = '"' + cl + '"'
+ link = '"' + link + '"'
+ includes = os.getenv('INCLUDE', '').split(';')
+ libs = os.getenv('LIB', '').split(';')
+
+ config.available_features.add('msvc')
+ compiler_flags = ['"/I{}"'.format(x) for x in includes if os.path.exists(x)]
+ linker_flags = ['"/LIBPATH:{}"'.format(x) for x in libs if os.path.exists(x)]
+
+ tools = [
+ ToolSubst('%msvc_cl', command=cl, extra_args=compiler_flags),
+ ToolSubst('%msvc_link', command=link, extra_args=linker_flags)]
+ llvm_config.add_tool_substitutions(tools)
+ return
+
+def use_support_substitutions(config):
+ # Set up substitutions for support tools. These tools can be overridden at the CMake
+ # level (by specifying -DLLDB_LIT_TOOLS_DIR), installed, or as a last resort, we can use
+ # the just-built version.
+ flags = []
+ if platform.system() in ['Darwin']:
+ try:
+ out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip()
+ res = 0
+ except OSError:
+ res = -1
+ if res == 0 and out:
+ sdk_path = lit.util.to_string(out)
+ llvm_config.lit_config.note('using SDKROOT: %r' % sdk_path)
+ flags = ['-isysroot', sdk_path]
+ elif platform.system() in ['OpenBSD', 'Linux']:
+ flags = ['-pthread']
+
+
+ additional_tool_dirs=[]
+ if config.lldb_lit_tools_dir:
+ additional_tool_dirs.append(config.lldb_lit_tools_dir)
+
+ llvm_config.use_clang(additional_flags=flags,
+ additional_tool_dirs=additional_tool_dirs,
+ required=True)
+
+ if sys.platform == 'win32':
+ _use_msvc_substitutions(config)
+
+ have_lld = llvm_config.use_lld(additional_tool_dirs=additional_tool_dirs,
+ required=False)
+ if have_lld:
+ config.available_features.add('lld')
+
+
+ support_tools = ['yaml2obj', 'obj2yaml', 'llvm-pdbutil',
+ 'llvm-mc', 'llvm-readobj', 'llvm-objdump',
+ 'llvm-objcopy']
+ additional_tool_dirs += [config.lldb_tools_dir, config.llvm_tools_dir]
+ llvm_config.add_tool_substitutions(support_tools, additional_tool_dirs)
diff --git a/lit/lit-lldb-init b/lit/lit-lldb-init
index b3a5d4dc9841..40bece698df3 100644
--- a/lit/lit-lldb-init
+++ b/lit/lit-lldb-init
@@ -1,2 +1,3 @@
# LLDB init file for the LIT tests.
settings set symbols.enable-external-lookup false
+settings set interpreter.echo-comment-commands false
diff --git a/lit/lit.cfg b/lit/lit.cfg
deleted file mode 100644
index 7e1fcf7520ca..000000000000
--- a/lit/lit.cfg
+++ /dev/null
@@ -1,174 +0,0 @@
-# -*- Python -*-
-
-import os
-import platform
-import re
-import subprocess
-import locale
-
-import lit.formats
-import lit.util
-
-def binary_feature(on, feature, off_prefix):
- return feature if on else off_prefix + feature
-
-# Configuration file for the 'lit' test runner.
-
-# name: The name of this test suite.
-config.name = 'lldb'
-
-# testFormat: The test format to use to interpret tests.
-#
-# For now we require '&&' between commands, until they get globally killed and
-# the test runner updated.
-execute_external = (platform.system() != 'Windows'
- or lit_config.getBashPath() not in [None, ""])
-config.test_format = lit.formats.ShTest(execute_external)
-
-# suffixes: We only support unit tests
-config.suffixes = []
-
-config.excludes = ['Inputs']
-
-# test_source_root: The root path where tests are located.
-config.test_source_root = os.path.dirname(__file__)
-
-# test_exec_root: The root path where tests should be run.
-config.test_exec_root = os.path.join(config.lldb_obj_root, 'lit')
-
-# Tweak the PATH to include the tools dir and the scripts dir.
-lldb_tools_dir = config.lldb_tools_dir
-llvm_tools_dir = config.llvm_tools_dir
-path = os.path.pathsep.join((config.lldb_tools_dir, config.llvm_tools_dir, config.environment['PATH']))
-
-config.environment['PATH'] = path
-
-path = os.path.pathsep.join((config.lldb_libs_dir, config.llvm_libs_dir,
- config.environment.get('LD_LIBRARY_PATH','')))
-config.environment['LD_LIBRARY_PATH'] = path
-
-# Propagate LLVM_SRC_ROOT into the environment.
-config.environment['LLVM_SRC_ROOT'] = getattr(config, 'llvm_src_root', '')
-
-# Propagate PYTHON_EXECUTABLE into the environment
-config.environment['PYTHON_EXECUTABLE'] = getattr(config, 'python_executable', '')
-
-# Register substitutions
-config.substitutions.append(('%python', config.python_executable))
-
-debugserver = lit.util.which('debugserver', lldb_tools_dir)
-lldb = "%s -S %s/lit-lldb-init" % (lit.util.which('lldb', lldb_tools_dir),
- config.test_source_root)
-
-lldbmi = lit.util.which('lldb-mi', lldb_tools_dir)
-
-if not os.path.exists(config.cc):
- config.cc = lit.util.which(config.cc, config.environment['PATH'])
-
-if not os.path.exists(config.cxx):
- config.cxx = lit.util.which(config.cxx, config.environment['PATH'])
-
-if platform.system() in ['Darwin']:
- try:
- out = subprocess.check_output(['xcrun', '--show-sdk-path']).strip()
- res = 0
- except OSError:
- res = -1
- if res == 0 and out:
- sdk_path = out
- lit_config.note('using SDKROOT: %r' % sdk_path)
- config.cc += " -isysroot %s" % sdk_path
- config.cxx += " -isysroot %s" % sdk_path
-
-if platform.system() in ['OpenBSD']:
- config.cc += " -pthread"
- config.cxx += " -pthread"
-
-config.substitutions.append(('%cc', config.cc))
-config.substitutions.append(('%cxx', config.cxx))
-
-config.substitutions.append(('%lldbmi', lldbmi + " --synchronous"))
-config.substitutions.append(('%lldb', lldb))
-
-if debugserver is not None:
- config.substitutions.append(('%debugserver', debugserver))
-
-for pattern in [r"\bFileCheck\b",
- r"\blldb-test\b",
- r"\byaml2obj\b",
- r"\| \bnot\b"]:
- tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_]+)\\b\W*$",
- pattern)
- tool_pipe = tool_match.group(2)
- tool_name = tool_match.group(4)
- tool_path = lit.util.which(tool_name, config.environment['PATH'])
- if not tool_path:
- # Warn, but still provide a substitution.
- lit_config.note(
- 'Did not find ' + tool_name + ' in ' + config.environment['PATH'])
- config.substitutions.append((pattern, tool_pipe + tool_path))
-
-# Shell execution
-if platform.system() not in ['Windows'] or lit_config.getBashPath() != '':
- config.available_features.add('shell')
-
-# Running on Darwin OS
-if platform.system() in ['Darwin']:
- config.available_features.add('darwin')
- config.available_features.add('system-linker-mach-o')
-
-# Running on ELF based *nix
-if platform.system() in ['FreeBSD', 'Linux']:
- config.available_features.add('system-linker-elf')
- if platform.system() in ['FreeBSD']:
- config.available_features.add('freebsd')
- else:
- config.available_features.add('linux')
-
-config.available_features.add(
- binary_feature(platform.system() in ['Windows'], 'windows', 'no'))
-
-if re.match(r'^arm(hf.*-linux)|(.*-linux-gnuabihf)', config.target_triple):
- config.available_features.add("armhf-linux")
-
-if re.match(r'icc', config.cc):
- config.available_features.add("compiler-icc")
-elif re.match(r'clang', config.cc):
- config.available_features.add("compiler-clang")
-elif re.match(r'gcc', config.cc):
- config.available_features.add("compiler-gcc")
-elif re.match(r'cl', config.cc):
- config.available_features.add("compiler-msvc")
-
-config.available_features.add(binary_feature(config.have_zlib, "zlib", "no"))
-if config.have_lld:
- config.available_features.add("lld")
-
-# llvm-config knows whether it is compiled with asserts (and)
-# whether we are operating in release/debug mode.
-import subprocess
-try:
- llvm_config_cmd = \
- subprocess.Popen([os.path.join(llvm_tools_dir, 'llvm-config'),
- '--build-mode', '--assertion-mode', '--targets-built'],
- stdout = subprocess.PIPE)
-except OSError as why:
- print("Could not find llvm-config in " + llvm_tools_dir)
- exit(42)
-
-llvm_config_output = llvm_config_cmd.stdout.read().decode('utf_8')
-llvm_config_output_list = llvm_config_output.split("\n")
-
-if re.search(r'DEBUG', llvm_config_output_list[0]):
- config.available_features.add('debug')
-if re.search(r'ON', llvm_config_output_list[1]):
- config.available_features.add('asserts')
-if re.search(r'ARM', llvm_config_output_list[2]):
- config.available_features.add('arm')
-if re.search(r'Mips', llvm_config_output_list[2]):
- config.available_features.add('mips')
-if re.search(r'PowerPC', llvm_config_output_list[2]):
- config.available_features.add('powerpc')
-if re.search(r'X86', llvm_config_output_list[2]):
- config.available_features.add('x86')
-llvm_config_cmd.wait()
diff --git a/lit/lit.cfg.py b/lit/lit.cfg.py
new file mode 100644
index 000000000000..e1db7621e328
--- /dev/null
+++ b/lit/lit.cfg.py
@@ -0,0 +1,75 @@
+# -*- Python -*-
+
+import os
+import re
+import shutil
+import site
+import sys
+
+import lit.formats
+from lit.llvm import llvm_config
+from lit.llvm.subst import FindTool
+from lit.llvm.subst import ToolSubst
+
+site.addsitedir(os.path.dirname(__file__))
+from helper import toolchain
+
+# name: The name of this test suite.
+config.name = 'LLDB'
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
+
+# suffixes: A list of file extensions to treat as test files. This is overriden
+# by individual lit.local.cfg files in the test subdirectories.
+config.suffixes = ['.test', '.cpp', '.s']
+
+# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
+# subdirectories contain auxiliary inputs for various tests in their parent
+# directories.
+config.excludes = ['Inputs', 'CMakeLists.txt', 'README.txt', 'LICENSE.txt']
+
+# test_source_root: The root path where tests are located.
+config.test_source_root = os.path.dirname(__file__)
+
+# test_exec_root: The root path where tests should be run.
+config.test_exec_root = os.path.join(config.lldb_obj_root, 'lit')
+
+
+llvm_config.use_default_substitutions()
+
+toolchain.use_lldb_substitutions(config)
+
+toolchain.use_support_substitutions(config)
+
+
+if re.match(r'^arm(hf.*-linux)|(.*-linux-gnuabihf)', config.target_triple):
+ config.available_features.add("armhf-linux")
+
+def calculate_arch_features(arch_string):
+ # This will add a feature such as x86, arm, mips, etc for each built
+ # target
+ features = []
+ for arch in arch_string.split():
+ features.append(arch.lower())
+ return features
+
+# Run llvm-config and add automatically add features for whether we have
+# assertions enabled, whether we are in debug mode, and what targets we
+# are built for.
+llvm_config.feature_config(
+ [('--assertion-mode', {'ON': 'asserts'}),
+ ('--build-mode', {'DEBUG': 'debug'}),
+ ('--targets-built', calculate_arch_features)
+ ])
+
+# Clean the module caches in the test build directory. This is
+# necessary in an incremental build whenever clang changes underneath,
+# so doing it once per lit.py invocation is close enough.
+
+for i in ['module-cache-clang', 'module-cache-lldb']:
+ cachedir = os.path.join(config.lldb_libs_dir, '..',
+ 'lldb-test-build.noindex', i)
+ if os.path.isdir(cachedir):
+ print("Deleting module cache at %s."%cachedir)
+ shutil.rmtree(cachedir)
diff --git a/lit/lit.site.cfg.in b/lit/lit.site.cfg.py.in
index 55942db64c4f..fbf88efcc2f5 100644
--- a/lit/lit.site.cfg.in
+++ b/lit/lit.site.cfg.py.in
@@ -4,29 +4,36 @@ config.llvm_src_root = "@LLVM_SOURCE_DIR@"
config.llvm_obj_root = "@LLVM_BINARY_DIR@"
config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
+config.llvm_shlib_dir = "@SHLIBDIR@"
config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
config.lldb_obj_root = "@LLDB_BINARY_DIR@"
config.lldb_libs_dir = "@LLDB_LIBS_DIR@"
config.lldb_tools_dir = "@LLDB_TOOLS_DIR@"
+# Since it comes from the command line, it may have backslashes which
+# should not need to be escaped.
+config.lldb_lit_tools_dir = r"@LLDB_LIT_TOOLS_DIR@"
config.target_triple = "@TARGET_TRIPLE@"
config.python_executable = "@PYTHON_EXECUTABLE@"
-config.cc = "@LLDB_TEST_C_COMPILER@"
-config.cxx = "@LLDB_TEST_CXX_COMPILER@"
config.have_zlib = @LLVM_ENABLE_ZLIB@
-config.have_lld = @LLDB_HAVE_LLD@
+config.host_triple = "@LLVM_HOST_TRIPLE@"
+config.lldb_bitness = 64 if @LLDB_IS_64_BITS@ else 32
# Support substitution of the tools and libs dirs with user parameters. This is
# used when we can't determine the tool dir at configuration time.
try:
config.llvm_tools_dir = config.llvm_tools_dir % lit_config.params
config.llvm_libs_dir = config.llvm_libs_dir % lit_config.params
+ config.llvm_shlib_dir = config.llvm_shlib_dir % lit_config.params
config.lldb_libs_dir = config.lldb_libs_dir % lit_config.params
config.lldb_tools_dir = config.lldb_tools_dir % lit_config.params
- config.cc = config.cc % lit_config.params
- config.cxx = config.cxx % lit_config.params
+ config.lldb_lit_tools_dir = config.lldb_lit_tools_dir % lit_config.params
+
except KeyError as e:
key, = e.args
lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key))
+import lit.llvm
+lit.llvm.initialize(lit_config, config)
+
# Let the main config do the real work.
-lit_config.load_config(config, "@LLDB_SOURCE_DIR@/lit/lit.cfg")
+lit_config.load_config(config, "@LLDB_SOURCE_DIR@/lit/lit.cfg.py")
diff --git a/lit/tools/lldb-mi/breakpoint/break-insert-enable-pending.test b/lit/tools/lldb-mi/breakpoint/break-insert-enable-pending.test
new file mode 100644
index 000000000000..48f86b4d678c
--- /dev/null
+++ b/lit/tools/lldb-mi/breakpoint/break-insert-enable-pending.test
@@ -0,0 +1,47 @@
+# XFAIL: system-windows
+# -> llvm.org/pr24452
+#
+# RUN: %clang -o %t %p/inputs/break-insert-pending.c -g
+# RUN: %lldbmi %t < %s | FileCheck %s
+
+# Test for enabling pending breakpoints globally
+
+-break-insert printf
+# CHECK: ^error,msg="Command 'break-insert'. Breakpoint location 'printf' not found
+
+-gdb-set breakpoint pending on
+# CHECK: ^done
+-gdb-show breakpoint pending
+# CHECK: ^done,value="on"
+-break-insert printf
+# CHECK: ^done,bkpt={number="2",type="breakpoint",disp="keep",enabled="y",addr="0xffffffffffffffff",func="??",file="??",fullname="??/??",line="0",pending=["printf"],times="0",original-location="printf"}
+
+-exec-run
+# CHECK: ^running
+# CHECK: *stopped,reason="breakpoint-hit",disp="del",bkptno="2",frame={level="0",addr="{{0x[0-9a-f]*[^f][0-9a-f]*}}"
+-break-disable 2
+# CHECK: ^done
+-exec-continue
+# CHECK: ^running
+# CHECK: *stopped,reason="exited-normally"
+
+# Test that it can be turned back off
+-gdb-show breakpoint pending
+# CHECK: ^done,value="on"
+-gdb-set breakpoint pending off
+# CHECK: ^done
+-gdb-show breakpoint pending
+# CHECK: ^done,value="off"
+-break-insert printf-non-existent
+# CHECK: ^error,msg="Command 'break-insert'. Breakpoint location 'printf-non-existent' not found"
+# Check that enable/disable with 1 and 0 works
+-gdb-set breakpoint pending 1
+# CHECK: ^done
+-gdb-show breakpoint pending
+# CHECK: ^done,value="on"
+-gdb-set breakpoint pending 0
+# CHECK: ^done
+-gdb-show breakpoint pending
+# CHECK: ^done,value="off"
+-gdb-set breakpoint pending garbage
+# CHECK: ^done
diff --git a/lit/tools/lldb-mi/breakpoint/break-insert.test b/lit/tools/lldb-mi/breakpoint/break-insert.test
index cecf9e2443ae..ef50bf530077 100644
--- a/lit/tools/lldb-mi/breakpoint/break-insert.test
+++ b/lit/tools/lldb-mi/breakpoint/break-insert.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o a.exe %p/inputs/break-insert.c -g
+# RUN: %build %p/inputs/break-insert.c --nodefaultlib -o a.exe
# RUN: %lldbmi < %s | FileCheck %s
# Test that a breakpoint can be inserted before creating a target.
diff --git a/lit/tools/lldb-mi/breakpoint/inputs/break-insert-pending.c b/lit/tools/lldb-mi/breakpoint/inputs/break-insert-pending.c
new file mode 100644
index 000000000000..99722abfbd4b
--- /dev/null
+++ b/lit/tools/lldb-mi/breakpoint/inputs/break-insert-pending.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main(int argc, char const *argv[]) {
+ printf("Print a formatted string so that GCC does not optimize this printf call: %s\n", argv[0]);
+ return 0;
+}
diff --git a/lit/tools/lldb-mi/data/data-info-line.test b/lit/tools/lldb-mi/data/data-info-line.test
index c224efa4de2d..287e833ab9ef 100644
--- a/lit/tools/lldb-mi/data/data-info-line.test
+++ b/lit/tools/lldb-mi/data/data-info-line.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/data-info-line.c -g
+# RUN: %build %p/inputs/data-info-line.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -data-info-line command.
diff --git a/lit/tools/lldb-mi/exec/exec-continue.test b/lit/tools/lldb-mi/exec/exec-continue.test
index c363422373d3..d51393e5c716 100644
--- a/lit/tools/lldb-mi/exec/exec-continue.test
+++ b/lit/tools/lldb-mi/exec/exec-continue.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-continue command.
diff --git a/lit/tools/lldb-mi/exec/exec-finish.test b/lit/tools/lldb-mi/exec/exec-finish.test
index 03c6b158fcf3..b2a50c5267fd 100644
--- a/lit/tools/lldb-mi/exec/exec-finish.test
+++ b/lit/tools/lldb-mi/exec/exec-finish.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-finish command.
diff --git a/lit/tools/lldb-mi/exec/exec-interrupt.test b/lit/tools/lldb-mi/exec/exec-interrupt.test
index 81a3e72ee7e6..2c063236d7f5 100644
--- a/lit/tools/lldb-mi/exec/exec-interrupt.test
+++ b/lit/tools/lldb-mi/exec/exec-interrupt.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-interrupt command.
diff --git a/lit/tools/lldb-mi/exec/exec-next-instruction.test b/lit/tools/lldb-mi/exec/exec-next-instruction.test
index 1dcca0468490..abd4e526375f 100644
--- a/lit/tools/lldb-mi/exec/exec-next-instruction.test
+++ b/lit/tools/lldb-mi/exec/exec-next-instruction.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-next-instruction command.
diff --git a/lit/tools/lldb-mi/exec/exec-next.test b/lit/tools/lldb-mi/exec/exec-next.test
index a4dd737b5ddb..87d9d44bb582 100644
--- a/lit/tools/lldb-mi/exec/exec-next.test
+++ b/lit/tools/lldb-mi/exec/exec-next.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-next command.
diff --git a/lit/tools/lldb-mi/exec/exec-step-instruction.test b/lit/tools/lldb-mi/exec/exec-step-instruction.test
index a02bc01a07d6..0613fb5c7934 100644
--- a/lit/tools/lldb-mi/exec/exec-step-instruction.test
+++ b/lit/tools/lldb-mi/exec/exec-step-instruction.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-step-instruction command.
diff --git a/lit/tools/lldb-mi/exec/exec-step.test b/lit/tools/lldb-mi/exec/exec-step.test
index 095bba714ec8..976afb33bcd4 100644
--- a/lit/tools/lldb-mi/exec/exec-step.test
+++ b/lit/tools/lldb-mi/exec/exec-step.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c -g
+# RUN: %build %p/inputs/main.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -exec-step command.
diff --git a/lit/tools/lldb-mi/symbol/symbol-list-lines.test b/lit/tools/lldb-mi/symbol/symbol-list-lines.test
index f40ad2f94e40..792f283db1bb 100644
--- a/lit/tools/lldb-mi/symbol/symbol-list-lines.test
+++ b/lit/tools/lldb-mi/symbol/symbol-list-lines.test
@@ -1,7 +1,4 @@
-# XFAIL: windows
-# -> llvm.org/pr24452
-#
-# RUN: %cc -o %t %p/inputs/main.c %p/inputs/symbol-list-lines.c %p/inputs/list-lines-helper.c -g
+# RUN: %build %p/inputs/main.c %p/inputs/symbol-list-lines.c %p/inputs/list-lines-helper.c --nodefaultlib -o %t
# RUN: %lldbmi %t < %s | FileCheck %s
# Test lldb-mi -symbol-list-lines command.
@@ -14,7 +11,7 @@
# CHECK: ^error,msg="File Handler. Invalid file name path"
-symbol-list-lines symbol-list-lines.c
-# CHECK: ^done,lines=[{pc="0x{{[0-9A-Fa-f]+}}",line="3"},{pc="0x{{[0-9A-Fa-f]+}}",line="4"},{pc="0x{{[0-9A-Fa-f]+}}",line="5"}]
+# CHECK: ^done,lines=[{pc="0x{{[0-9A-Fa-f]+}}",line="3"},{pc="0x{{[0-9A-Fa-f]+}}",line="4"},{pc="0x{{[0-9A-Fa-f]+}}",line="5"}{{.*}}]
-symbol-list-lines list-lines-helper.c
-# CHECK: ^done,lines=[{pc="0x{{[0-9A-Fa-f]+}}",line="1"},{pc="0x{{[0-9A-Fa-f]+}}",line="2"},{pc="0x{{[0-9A-Fa-f]+}}",line="3"}]
+# CHECK: ^done,lines=[{pc="0x{{[0-9A-Fa-f]+}}",line="1"},{pc="0x{{[0-9A-Fa-f]+}}",line="2"},{pc="0x{{[0-9A-Fa-f]+}}",line="3"}{{.*}}]
diff --git a/lit/tools/lldb-mi/target/inputs/main.c b/lit/tools/lldb-mi/target/inputs/main.c
new file mode 100644
index 000000000000..8c74b3496f7c
--- /dev/null
+++ b/lit/tools/lldb-mi/target/inputs/main.c
@@ -0,0 +1,4 @@
+int main(void) {
+ int x = 0;
+ return x;
+}
diff --git a/lit/tools/lldb-mi/target/inputs/target-select-so-path.py b/lit/tools/lldb-mi/target/inputs/target-select-so-path.py
new file mode 100644
index 000000000000..5eb07d84237c
--- /dev/null
+++ b/lit/tools/lldb-mi/target/inputs/target-select-so-path.py
@@ -0,0 +1,50 @@
+import os
+import sys
+import subprocess
+from threading import Timer
+
+
+hostname = 'localhost'
+
+(r, w) = os.pipe()
+kwargs = {}
+if sys.version_info >= (3,2):
+ kwargs['pass_fds'] = [w]
+
+args = sys.argv
+# Get debugserver, lldb-mi and FileCheck executables' paths with arguments.
+debugserver = ' '.join([args[1], '--pipe', str(w), hostname + ':0'])
+lldbmi = args[2]
+test_file = args[3]
+filecheck = 'FileCheck ' + test_file
+
+# Run debugserver, lldb-mi and FileCheck.
+debugserver_proc = subprocess.Popen(debugserver.split(), **kwargs)
+lldbmi_proc = subprocess.Popen(lldbmi, stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE, shell=True)
+filecheck_proc = subprocess.Popen(filecheck, stdin=subprocess.PIPE,
+ shell=True)
+
+timeout_sec = 30
+timer = Timer(timeout_sec, exit, [filecheck_proc.returncode])
+try:
+ timer.start()
+
+ # Get a tcp port chosen by debugserver.
+ # The number quite big to get lldb-server's output and to not hang.
+ bytes_to_read = 10
+ port_bytes = os.read(r, bytes_to_read)
+ port = str(port_bytes.decode('utf-8').strip('\x00'))
+
+ with open(test_file, 'r') as f:
+ # Replace '$PORT' with a free port number and pass
+ # test's content to lldb-mi.
+ lldbmi_proc.stdin.write(f.read().replace('$PORT', port).encode('utf-8'))
+ out, err = lldbmi_proc.communicate()
+ filecheck_proc.stdin.write(out)
+ filecheck_proc.communicate()
+finally:
+ timer.cancel()
+
+debugserver_proc.kill()
+exit(filecheck_proc.returncode)
diff --git a/lit/Expr/lit.local.cfg b/lit/tools/lldb-mi/target/lit.local.cfg
index df9b335dd131..df9b335dd131 100644
--- a/lit/Expr/lit.local.cfg
+++ b/lit/tools/lldb-mi/target/lit.local.cfg
diff --git a/lit/tools/lldb-mi/target/target-select-so-path.test b/lit/tools/lldb-mi/target/target-select-so-path.test
new file mode 100644
index 000000000000..785030bf2fd3
--- /dev/null
+++ b/lit/tools/lldb-mi/target/target-select-so-path.test
@@ -0,0 +1,25 @@
+# UNSUPPORTED: windows, darwin
+#
+# RUN: %clang -o %t %p/inputs/main.c -g
+# RUN: %python %p/inputs/target-select-so-path.py "%debugserver" "%lldbmi %t" %s
+
+# Test that -target-select command can hook up a path
+# added by gdb-set solib-search-path.
+
+# Check that we have a valid target created via file-exec-and-symbols.
+# CHECK: ^done
+
+-interpreter-exec console "target modules search-paths list"
+# CHECK ^done
+
+-gdb-set solib-search-path /example/dir
+# CHECK: ^done
+
+-target-select remote localhost:$PORT
+# CHECK: ^connected
+
+-interpreter-exec console "target modules search-paths list"
+# CHECK: ~"[0] \".\" -> \"/example/dir\"\n"
+# CHECK-NEXT: ^done
+
+-gdb-exit
diff --git a/lldb.xcodeproj/project.pbxproj b/lldb.xcodeproj/project.pbxproj
index d8a714415320..b2ab9696a3aa 100644
--- a/lldb.xcodeproj/project.pbxproj
+++ b/lldb.xcodeproj/project.pbxproj
@@ -110,6 +110,8 @@
23E2E5251D90373D006F38BB /* ArchSpecTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E5161D903689006F38BB /* ArchSpecTest.cpp */; };
AF2E02A31FA2CEAF00A86C34 /* ArchitectureArm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2E02A11FA2CEAF00A86C34 /* ArchitectureArm.cpp */; };
AF2E02A41FA2CEAF00A86C34 /* ArchitectureArm.h in Headers */ = {isa = PBXBuildFile; fileRef = AF2E02A21FA2CEAF00A86C34 /* ArchitectureArm.h */; };
+ 2647B63221C4366300A81D15 /* ArchitectureMips.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2647B63021C4366300A81D15 /* ArchitectureMips.cpp */; };
+ 2647B63121C4366300A81D15 /* ArchitectureMips.h in Headers */ = {isa = PBXBuildFile; fileRef = 2647B62F21C4366200A81D15 /* ArchitectureMips.h */; };
4C14CEFB2057258D00DEEF94 /* ArchitecturePPC64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C14CEF82057258D00DEEF94 /* ArchitecturePPC64.cpp */; };
2689007D13353E2200698AC0 /* Args.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6C10F1B85900F91463 /* Args.cpp */; };
23CB153C1D66DA9300EDDDE1 /* ArgsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F93E1BDD33CE00BA9A93 /* ArgsTest.cpp */; };
@@ -119,6 +121,7 @@
268900D013353E6F00698AC0 /* Block.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1310F1B8EC00F91463 /* Block.cpp */; };
49DEF1251CD7C6DF006A7C7D /* BlockPointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DEF11F1CD7BD90006A7C7D /* BlockPointer.cpp */; };
2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0A10F1B83100F91463 /* Breakpoint.cpp */; };
+ 2660387E211CA98200329572 /* BreakpointBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660387D211CA98200329572 /* BreakpointBase.cpp */; };
2689FFF113353DB600698AC0 /* BreakpointID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0B10F1B83100F91463 /* BreakpointID.cpp */; };
2689FFF313353DB600698AC0 /* BreakpointIDList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E0C10F1B83100F91463 /* BreakpointIDList.cpp */; };
23E2E5321D903832006F38BB /* BreakpointIDTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E2E52D1D90382B006F38BB /* BreakpointIDTest.cpp */; };
@@ -133,9 +136,11 @@
2689000313353DB600698AC0 /* BreakpointResolverFileLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5410FE555900271C65 /* BreakpointResolverFileLine.cpp */; };
4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; };
2689000513353DB600698AC0 /* BreakpointResolverName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D0DD5510FE555900271C65 /* BreakpointResolverName.cpp */; };
+ 4CCF9F612143014D006CC7EA /* BreakpointResolverScripted.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCF9F5E2143012F006CC7EA /* BreakpointResolverScripted.cpp */; };
2689000713353DB600698AC0 /* BreakpointSite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1310F1B83100F91463 /* BreakpointSite.cpp */; };
2689000913353DB600698AC0 /* BreakpointSiteList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E1410F1B83100F91463 /* BreakpointSiteList.cpp */; };
- 2689003113353E0400698AC0 /* Broadcaster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E6D10F1B85900F91463 /* Broadcaster.cpp */; };
+ 2647B63A21C436AC00A81D15 /* Broadcaster.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2647B63921C436AB00A81D15 /* Broadcaster.cpp */; };
+ 2647B63621C4368300A81D15 /* Broadcaster.h in Headers */ = {isa = PBXBuildFile; fileRef = 2647B63521C4368300A81D15 /* Broadcaster.h */; };
23CB15431D66DA9300EDDDE1 /* BroadcasterTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */; };
949EEDAE1BA7671C008C63CF /* CF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 949EEDAC1BA76719008C63CF /* CF.cpp */; };
2689007613353E1A00698AC0 /* CFCBundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7EED10F1B8AD00F91463 /* CFCBundle.cpp */; };
@@ -158,6 +163,7 @@
268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E69030129C6BEF00DDECD9 /* ClangExternalASTSourceCallbacks.cpp */; };
4966DCC4148978A10028481B /* ClangExternalASTSourceCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4966DCC3148978A10028481B /* ClangExternalASTSourceCommon.cpp */; };
2689005F13353E0E00698AC0 /* ClangFunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */; };
+ 228B1B672113340200E61C70 /* ClangHighlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58A080AB2112AABB00D5580F /* ClangHighlighter.cpp */; };
4CD44D5820C603CB0003557C /* ClangHost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD44D5620C603A80003557C /* ClangHost.cpp */; };
4959511F1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */; };
2689006313353E0E00698AC0 /* ClangPersistentVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */; };
@@ -191,6 +197,7 @@
2689002113353DDE00698AC0 /* CommandObjectQuit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3910F1B84700F91463 /* CommandObjectQuit.cpp */; };
2689008413353E2200698AC0 /* CommandObjectRegexCommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DFBC59113B48F300DD817F /* CommandObjectRegexCommand.cpp */; };
2689002213353DDE00698AC0 /* CommandObjectRegister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3B10F1B84700F91463 /* CommandObjectRegister.cpp */; };
+ AFCB1D5C219CD5A800730AD5 /* CommandObjectReproducer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFCB1D5A219CD5A700730AD5 /* CommandObjectReproducer.cpp */; };
2689002313353DDE00698AC0 /* CommandObjectScript.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E3D10F1B84700F91463 /* CommandObjectScript.cpp */; };
2689002413353DDE00698AC0 /* CommandObjectSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E4010F1B84700F91463 /* CommandObjectSettings.cpp */; };
2689002513353DDE00698AC0 /* CommandObjectSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E4210F1B84700F91463 /* CommandObjectSource.cpp */; };
@@ -207,6 +214,7 @@
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2642FBA813D003B400ED6808 /* CommunicationKDP.cpp */; };
964463EC1A330C0500154ED8 /* CompactUnwindInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 964463EB1A330C0500154ED8 /* CompactUnwindInfo.cpp */; };
268900D513353E6F00698AC0 /* CompileUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1510F1B8EC00F91463 /* CompileUnit.cpp */; };
+ AFD966B8217140B6006714AC /* CompileUnitIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD966B4217140B5006714AC /* CompileUnitIndex.cpp */; };
265192C61BA8E905002F08F6 /* CompilerDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 265192C51BA8E905002F08F6 /* CompilerDecl.cpp */; };
2657AFB71B86910100958979 /* CompilerDeclContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2657AFB61B86910100958979 /* CompilerDeclContext.cpp */; };
268900D213353E6F00698AC0 /* CompilerType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49E45FAD11F660FE008F7B28 /* CompilerType.cpp */; };
@@ -220,9 +228,6 @@
945261BF1B9A11FC00BF138D /* CxxStringTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B31B9A11E800BF138D /* CxxStringTypes.cpp */; };
6D95DC001B9DC057000E318A /* DIERef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D95DBFD1B9DC057000E318A /* DIERef.cpp */; };
269DDD4A1B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */; };
- AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */; };
- 6D0F61481C80AAD600A4ECEE /* DWARFASTParserJava.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61441C80AACF00A4ECEE /* DWARFASTParserJava.cpp */; };
- 4CC7C6581D529B950076FF94 /* DWARFASTParserOCaml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C6521D5299140076FF94 /* DWARFASTParserOCaml.cpp */; };
268900B713353E5F00698AC0 /* DWARFAbbreviationDeclaration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89B310F57C5600BB2B04 /* DWARFAbbreviationDeclaration.cpp */; };
266E829D1B8E542C008FCA06 /* DWARFAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */; };
4CD44D4220B777850003557C /* DWARFBaseDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD44D4020B777850003557C /* DWARFBaseDIE.cpp */; };
@@ -246,13 +251,14 @@
2689006613353E0E00698AC0 /* DWARFExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */; };
268900C613353E5F00698AC0 /* DWARFFormValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89D310F57C5600BB2B04 /* DWARFFormValue.cpp */; };
4CD44CFB20B37C440003557C /* DWARFIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD44CF820B37C440003557C /* DWARFIndex.cpp */; };
+ 4C38996421B9AECD002BAEF4 /* DWARFLocationExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C38996221B9AECC002BAEF4 /* DWARFLocationExpression.cpp */; };
AFE228832060699D0042D0C8 /* DWARFUnit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7F2AAA5920601BE000A422D8 /* DWARFUnit.cpp */; };
26FFC19B14FC072100087D58 /* DYLDRendezvous.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19514FC072100087D58 /* DYLDRendezvous.cpp */; };
49CA96FC1E6AACC900C03FEE /* DataBufferHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E61E6AAC6600C03FEE /* DataBufferHeap.cpp */; };
49CA96FD1E6AACC900C03FEE /* DataBufferLLVM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E71E6AAC6600C03FEE /* DataBufferLLVM.cpp */; };
49CA96FE1E6AACC900C03FEE /* DataEncoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E81E6AAC6600C03FEE /* DataEncoder.cpp */; };
49CA96FF1E6AACC900C03FEE /* DataExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96E91E6AAC6600C03FEE /* DataExtractor.cpp */; };
- 23CB15391D66DA9300EDDDE1 /* DataExtractorTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB14E81D66CC0E00EDDDE1 /* DataExtractorTest.cpp */; };
+ AFA1B62C219E0ED900A8AB7E /* DataExtractorTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFA1B62B219E0ED900A8AB7E /* DataExtractorTest.cpp */; };
94CB255C16B069770059775D /* DataVisualization.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94CB255816B069770059775D /* DataVisualization.cpp */; };
23D4007E1C210201000C3885 /* DebugMacros.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23E77CDB1C20F2F2007192AD /* DebugMacros.cpp */; };
AF116BEF20CF234B0071093F /* DebugNamesDWARFIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF116BED20CF234B0071093F /* DebugNamesDWARFIndex.cpp */; };
@@ -288,13 +294,14 @@
AFDBC36E204663AF00B9C8F2 /* EmulateInstructionPPC64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFDBC36C204663AF00B9C8F2 /* EmulateInstructionPPC64.cpp */; };
9A22A163135E30370024DDC3 /* EmulationStateARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A22A15F135E30370024DDC3 /* EmulationStateARM.cpp */; };
6B74D89B200696BB0074051B /* Environment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 22DC561920064C9600A7E9E8 /* Environment.cpp */; };
- 2689003D13353E0400698AC0 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7910F1B85900F91463 /* Event.cpp */; };
+ 2647B63C21C436B400A81D15 /* Event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2647B63B21C436B400A81D15 /* Event.cpp */; };
+ 2647B63421C4367A00A81D15 /* Event.h in Headers */ = {isa = PBXBuildFile; fileRef = 2647B63321C4367A00A81D15 /* Event.h */; };
+ 2660387A211CA90F00329572 /* ExceptionBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26603874211CA90E00329572 /* ExceptionBreakpoint.cpp */; };
268900EB13353E6F00698AC0 /* ExecutionContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */; };
4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C88BC291BA3722B00AA0964 /* Expression.cpp */; };
49A1CAC51430E8DE00306AC9 /* ExpressionSourceCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */; };
4984BA161B979973008658D4 /* ExpressionVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4984BA151B979973008658D4 /* ExpressionVariable.cpp */; };
4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */ = {isa = PBXBuildFile; fileRef = 4984BA171B979C08008658D4 /* ExpressionVariable.h */; };
- AFC2DCE71E6E2ED000283714 /* FastDemangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */; };
2689006E13353E1A00698AC0 /* File.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C6EA213011581005E16B0 /* File.cpp */; };
3FDFDDBD199C3A06009756A7 /* FileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */; };
3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBE199D345E009756A7 /* FileCache.cpp */; };
@@ -313,12 +320,15 @@
AF23B4DB19009C66003E2A58 /* FreeBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */; };
268900D913353E6F00698AC0 /* FuncUnwinders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */; };
268900D813353E6F00698AC0 /* Function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1810F1B8EC00F91463 /* Function.cpp */; };
+ 2660387C211CA90F00329572 /* FunctionBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26603877211CA90E00329572 /* FunctionBreakpoint.cpp */; };
4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */; };
2374D7531D4BB2FF005C9575 /* GDBRemoteClientBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2374D74E1D4BB299005C9575 /* GDBRemoteClientBase.cpp */; };
23CB153A1D66DA9300EDDDE1 /* GDBRemoteClientBaseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2370A37D1D66C587000E7BE6 /* GDBRemoteClientBaseTest.cpp */; };
2689009D13353E4200698AC0 /* GDBRemoteCommunication.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE5B1315B29C001D6D71 /* GDBRemoteCommunication.cpp */; };
26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; };
23CB153D1D66DA9300EDDDE1 /* GDBRemoteCommunicationClientTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2370A37E1D66C587000E7BE6 /* GDBRemoteCommunicationClientTest.cpp */; };
+ AF8AD945219CD45800614785 /* GDBRemoteCommunicationHistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD943219CD45700614785 /* GDBRemoteCommunicationHistory.cpp */; };
+ AFCB1D59219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFCB1D57219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.cpp */; };
26744EF31338317700EF765A /* GDBRemoteCommunicationServer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */; };
6D55B2901A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */; };
6D55B2911A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D55B28E1A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp */; };
@@ -326,16 +336,10 @@
2689009E13353E4200698AC0 /* GDBRemoteRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618EE5D1315B29C001D6D71 /* GDBRemoteRegisterContext.cpp */; };
E7E94ABC1B54961F00D0AE30 /* GDBRemoteSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E73A15A41B548EC500786197 /* GDBRemoteSignals.cpp */; };
23CB15461D66DA9300EDDDE1 /* GDBRemoteTestUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2370A37F1D66C587000E7BE6 /* GDBRemoteTestUtils.cpp */; };
- AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */; };
- AE44FB4C1BB4BB540033EB62 /* GoFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB4A1BB4BB540033EB62 /* GoFormatterFunctions.cpp */; };
- AE44FB471BB4BB090033EB62 /* GoLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB451BB4BB090033EB62 /* GoLanguage.cpp */; };
- AE44FB3E1BB485960033EB62 /* GoLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */; };
- AE44FB311BB07EB80033EB62 /* GoLexer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */; };
- AE44FB321BB07EBC0033EB62 /* GoParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */; };
- 23CB15331D66DA9300EDDDE1 /* GoParserTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEC6FF9F1BE970A2007882C1 /* GoParserTest.cpp */; };
- AE44FB301BB07EB20033EB62 /* GoUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */; };
6D95DC011B9DC057000E318A /* HashedNameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D95DBFE1B9DC057000E318A /* HashedNameToDIE.cpp */; };
2666ADC81B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2666ADC31B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp */; };
+ 58A080B42112AB3800D5580F /* Highlighter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58A080A92112AA9400D5580F /* Highlighter.cpp */; };
+ 58A080B32112AB2900D5580F /* HighlighterTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58A080B12112AB2200D5580F /* HighlighterTest.cpp */; };
AF1729D6182C907200E0AB97 /* HistoryThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1729D4182C907200E0AB97 /* HistoryThread.cpp */; };
AF1729D7182C907200E0AB97 /* HistoryUnwind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */; };
2689007113353E1A00698AC0 /* Host.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E1C1236C5D400C660B5 /* Host.cpp */; };
@@ -367,16 +371,14 @@
26BC179A18C7F2B300D2196D /* JITLoaderList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC179818C7F2B300D2196D /* JITLoaderList.cpp */; };
942829561A89614C00521B30 /* JSON.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 942829551A89614C00521B30 /* JSON.cpp */; };
8C3BD9A01EF5D1FF0016C343 /* JSONTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C3BD99F1EF5D1B50016C343 /* JSONTest.cpp */; };
- 6D0F61431C80AAAE00A4ECEE /* JavaASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61411C80AAAA00A4ECEE /* JavaASTContext.cpp */; };
- 6D0F61591C80AB3500A4ECEE /* JavaFormatterFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61511C80AB3000A4ECEE /* JavaFormatterFunctions.cpp */; };
- 6D0F615A1C80AB3900A4ECEE /* JavaLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F61531C80AB3000A4ECEE /* JavaLanguage.cpp */; };
- 6D0F614E1C80AB0700A4ECEE /* JavaLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D0F614A1C80AB0400A4ECEE /* JavaLanguageRuntime.cpp */; };
- 6D0F614F1C80AB0C00A4ECEE /* JavaLanguageRuntime.h in Headers */ = {isa = PBXBuildFile; fileRef = 6D0F614B1C80AB0400A4ECEE /* JavaLanguageRuntime.h */; };
+ 2660387B211CA90F00329572 /* JSONUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26603875211CA90E00329572 /* JSONUtils.cpp */; };
2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; };
2669424D1A6DC32B0063BE93 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; };
+ 26792623211CA42300EE1D10 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; };
26B42C4D1187ABA50079C8C8 /* LLDB.h in Headers */ = {isa = PBXBuildFile; fileRef = 26B42C4C1187ABA50079C8C8 /* LLDB.h */; settings = {ATTRIBUTES = (Public, ); }; };
943BDEFE1AA7B2F800789CE8 /* LLDBAssert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 943BDEFD1AA7B2F800789CE8 /* LLDBAssert.cpp */; };
6D762BEE1B1605D2006C929D /* LLDBServerUtilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */; };
+ 26F7619B211CBBB30044F6EA /* LLDBUtils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26F76199211CBBB30044F6EA /* LLDBUtils.cpp */; };
2660AAB914622483003A9694 /* LLDBWrapPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */; settings = {COMPILER_FLAGS = "-Dregister="; }; };
AEB0E4591BD6E9F800B24093 /* LLVMUserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */; };
94B638531B8F8E6C004FE1E4 /* Language.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B638521B8F8E6C004FE1E4 /* Language.cpp */; };
@@ -388,17 +390,23 @@
945261C11B9A11FC00BF138D /* LibCxxInitializerList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B71B9A11E800BF138D /* LibCxxInitializerList.cpp */; };
945261C21B9A11FC00BF138D /* LibCxxList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B81B9A11E800BF138D /* LibCxxList.cpp */; };
945261C31B9A11FC00BF138D /* LibCxxMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261B91B9A11E800BF138D /* LibCxxMap.cpp */; };
+ E4A63A9120F55D28000D9548 /* LibCxxOptional.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A63A9020F55D27000D9548 /* LibCxxOptional.cpp */; };
AF9FF1F71FAA79FE00474976 /* LibCxxQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9FF1F61FAA79FE00474976 /* LibCxxQueue.cpp */; };
AF9FF1F51FAA79A400474976 /* LibCxxTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9FF1F41FAA79A400474976 /* LibCxxTuple.cpp */; };
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */; };
+ E414F6F121388F6C00C50BC6 /* LibCxxVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E414F6F021388F6B00C50BC6 /* LibCxxVariant.cpp */; };
+ E414F6EE21388F0300C50BC6 /* LibCxxVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = E414F6ED21388F0200C50BC6 /* LibCxxVariant.h */; };
945261C51B9A11FC00BF138D /* LibCxxVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BB1B9A11E800BF138D /* LibCxxVector.cpp */; };
945261C61B9A11FC00BF138D /* LibStdcpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945261BC1B9A11E800BF138D /* LibStdcpp.cpp */; };
4CDB8D6E1DBA91B6006C5B13 /* LibStdcppTuple.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CDB8D681DBA91A6006C5B13 /* LibStdcppTuple.cpp */; };
4CDB8D6D1DBA91B6006C5B13 /* LibStdcppUniquePointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CDB8D671DBA91A6006C5B13 /* LibStdcppUniquePointer.cpp */; };
268900DA13353E6F00698AC0 /* LineEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */; };
268900DB13353E6F00698AC0 /* LineTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1A10F1B8EC00F91463 /* LineTable.cpp */; };
+ 2647B64421C43BB000A81D15 /* LinuxProcMaps.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2647B64221C43BB000A81D15 /* LinuxProcMaps.cpp */; };
+ 2647B64321C43BB000A81D15 /* LinuxProcMaps.h in Headers */ = {isa = PBXBuildFile; fileRef = 2647B64121C43BAF00A81D15 /* LinuxProcMaps.h */; };
23059A0719532B96007B8189 /* LinuxSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23059A0519532B96007B8189 /* LinuxSignals.cpp */; };
- 2689004113353E0400698AC0 /* Listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7E10F1B85900F91463 /* Listener.cpp */; };
+ 2647B63E21C436BD00A81D15 /* Listener.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2647B63D21C436BC00A81D15 /* Listener.cpp */; };
+ 2647B63821C4369500A81D15 /* Listener.h in Headers */ = {isa = PBXBuildFile; fileRef = 2647B63721C4369500A81D15 /* Listener.h */; };
9A3D43EC1F3237F900EB767C /* ListenerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3D43E31F3237D500EB767C /* ListenerTest.cpp */; };
255EFF741AFABA720069F277 /* LockFileBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255EFF731AFABA720069F277 /* LockFileBase.cpp */; };
255EFF761AFABA950069F277 /* LockFilePosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 255EFF751AFABA950069F277 /* LockFilePosix.cpp */; };
@@ -479,6 +487,7 @@
266942451A6DC2AC0063BE93 /* MIUtilString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941EE1A6DC2AC0063BE93 /* MIUtilString.cpp */; };
2669424A1A6DC2AC0063BE93 /* MIUtilThreadBaseStd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941F81A6DC2AC0063BE93 /* MIUtilThreadBaseStd.cpp */; };
2669424B1A6DC2AC0063BE93 /* MIUtilVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266941FA1A6DC2AC0063BE93 /* MIUtilVariant.cpp */; };
+ AF395C03219254F300894EC3 /* MSVCUndecoratedNameParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF395C01219254F200894EC3 /* MSVCUndecoratedNameParser.cpp */; };
D67521381EA17C4200439694 /* MainLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D67521351EA17C3900439694 /* MainLoop.cpp */; };
9A20573A1F3B8E7E00F6C293 /* MainLoopTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A2057301F3B8E7600F6C293 /* MainLoopTest.cpp */; };
8C3BD9961EF45DA50016C343 /* MainThreadCheckerRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8C3BD9951EF45D9B0016C343 /* MainThreadCheckerRuntime.cpp */; };
@@ -510,8 +519,6 @@
3F81691A1ABA2419001DA9DF /* NameMatches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8169181ABA2419001DA9DF /* NameMatches.cpp */; };
9A3D43D81F3151C400EB767C /* NameMatchesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3D43CB1F3150D200EB767C /* NameMatchesTest.cpp */; };
268900C913353E5F00698AC0 /* NameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */; };
- 232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */; };
- 232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */; };
232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */; };
267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */; };
23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; };
@@ -519,21 +526,19 @@
267A47FF1B1411D90021A5BC /* NativeWatchpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FE1B1411D90021A5BC /* NativeWatchpointList.cpp */; };
AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */; };
AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */; };
- 4CC7C6571D52997A0076FF94 /* OCamlASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */; };
- 4CC7C6501D5298F30076FF94 /* OCamlLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */; };
942612F81B952C9B00EF842E /* ObjCLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B6385E1B8FB7A2004FE1E4 /* ObjCLanguage.cpp */; };
268900ED13353E6F00698AC0 /* ObjCLanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */; };
94B638631B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94B638621B8FB7F1004FE1E4 /* ObjCPlusPlusLanguage.cpp */; };
2689009613353E4200698AC0 /* ObjectContainerBSDArchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26A3B4AC1181454800381BC2 /* ObjectContainerBSDArchive.cpp */; };
2689009713353E4200698AC0 /* ObjectContainerUniversalMachO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C898010F57C5600BB2B04 /* ObjectContainerUniversalMachO.cpp */; };
268900DC13353E6F00698AC0 /* ObjectFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */; };
+ 4C9BF11B21C0467700FA4036 /* ObjectFileBreakpad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C9BF11921C0467700FA4036 /* ObjectFileBreakpad.cpp */; };
2689009913353E4200698AC0 /* ObjectFileELF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C898510F57C5600BB2B04 /* ObjectFileELF.cpp */; };
26EFC4CD18CFAF0D00865D87 /* ObjectFileJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */; };
2689009A13353E4200698AC0 /* ObjectFileMachO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C898810F57C5600BB2B04 /* ObjectFileMachO.cpp */; };
26E152261419CAD4007967D0 /* ObjectFilePECOFF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26E152231419CACA007967D0 /* ObjectFilePECOFF.cpp */; };
26651A18133BF9E0005B64B7 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26651A17133BF9DF005B64B7 /* Opcode.cpp */; };
266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */; };
- AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */; };
2698699B15E6CBD0002415FF /* OperatingSystemPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2698699815E6CBD0002415FF /* OperatingSystemPython.cpp */; };
4C719395207D235400FDF430 /* OptionArgParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C719394207D235400FDF430 /* OptionArgParser.cpp */; };
26D5E15F135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D5E15E135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp */; };
@@ -574,6 +579,10 @@
4CA0C6CC20F929C700CFE6BB /* PDBLocationToDWARFExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CA0C6CA20F929C600CFE6BB /* PDBLocationToDWARFExpression.cpp */; };
268900EE13353E6F00698AC0 /* PathMappingList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 495BBACB119A0DBE00418BEA /* PathMappingList.cpp */; };
2668A2EE20AF417D00D94111 /* PathMappingListTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2668A2ED20AF417D00D94111 /* PathMappingListTest.cpp */; };
+ AF815DF921C855B400023A34 /* PdbAstBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF815DF721C855B400023A34 /* PdbAstBuilder.cpp */; };
+ AFD966BA217140B6006714AC /* PdbIndex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD966B6217140B6006714AC /* PdbIndex.cpp */; };
+ AF0F459E219FA1C800C1E612 /* PdbSymUid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0F459D219FA1C800C1E612 /* PdbSymUid.cpp */; };
+ AFD966B9217140B6006714AC /* PdbUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD966B5217140B6006714AC /* PdbUtil.cpp */; };
25420ED21A649D88009ADBCB /* PipeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 25420ED11A649D88009ADBCB /* PipeBase.cpp */; };
2377C2F819E613C100737875 /* PipePosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2377C2F719E613C100737875 /* PipePosix.cpp */; };
268900EF13353E6F00698AC0 /* Platform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264A43BD1320BCEB005B4096 /* Platform.cpp */; };
@@ -595,6 +604,7 @@
26EFB61C1BFE8D3E00544801 /* PlatformNetBSD.h in Headers */ = {isa = PBXBuildFile; fileRef = 26EFB6191BFE8D3E00544801 /* PlatformNetBSD.h */; };
4CE4EFAA1E8999B900A80C06 /* PlatformOpenBSD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE4EFA61E8999B000A80C06 /* PlatformOpenBSD.cpp */; };
945759671534941F005A9070 /* PlatformPOSIX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 945759651534941F005A9070 /* PlatformPOSIX.cpp */; };
+ AF663250216EB9C300BB510D /* PlatformRemoteAppleBridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF66324E216EB9C300BB510D /* PlatformRemoteAppleBridge.cpp */; };
AF8AD6371BEC28C400150209 /* PlatformRemoteAppleTV.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */; };
AF8AD6381BEC28C400150209 /* PlatformRemoteAppleTV.h in Headers */ = {isa = PBXBuildFile; fileRef = AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */; };
AF8AD6391BEC28C400150209 /* PlatformRemoteAppleWatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */; };
@@ -631,7 +641,6 @@
AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0C112718580CD800C4C45B /* QueueItem.cpp */; };
AF26703B1852D01E00B6CC36 /* QueueList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF2670391852D01E00B6CC36 /* QueueList.cpp */; };
4939EA8D1BD56B6D00084382 /* REPL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4939EA8C1BD56B6D00084382 /* REPL.cpp */; };
- 94BA8B6D176F8C9B005A91B5 /* Range.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94BA8B6C176F8C9B005A91B5 /* Range.cpp */; };
268900F113353E6F00698AC0 /* RegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3710F1B90C00F91463 /* RegisterContext.cpp */; };
26957D9813D381C900670048 /* RegisterContextDarwin_arm.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */; };
AF9107EE168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF9107EC168570D200DBCD3C /* RegisterContextDarwin_arm64.cpp */; };
@@ -660,6 +669,10 @@
26474CBE18D0CB2D0073DEBA /* RegisterContextMach_i386.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CB818D0CB2D0073DEBA /* RegisterContextMach_i386.cpp */; };
26474CC018D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CBA18D0CB2D0073DEBA /* RegisterContextMach_x86_64.cpp */; };
26474CC918D0CB5B0073DEBA /* RegisterContextMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */; };
+ 2619C4852107A9A2009CDE81 /* RegisterContextMinidump_ARM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */; };
+ 2619C4872107A9A2009CDE81 /* RegisterContextMinidump_ARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */; };
+ 2619C4842107A9A2009CDE81 /* RegisterContextMinidump_ARM64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */; };
+ 2619C4862107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h in Headers */ = {isa = PBXBuildFile; fileRef = 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */; };
947CF7761DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */; };
AFD65C811D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */; };
AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */; };
@@ -698,6 +711,10 @@
23D065901D4A7BEE0008EDE6 /* RenderScriptRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D065841D4A7BDA0008EDE6 /* RenderScriptRuntime.cpp */; };
9485545A1DCBAE3B00345FF5 /* RenderScriptScriptGroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 948554591DCBAE3B00345FF5 /* RenderScriptScriptGroup.cpp */; };
23D065911D4A7BEE0008EDE6 /* RenderScriptx86ABIFixups.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23D065861D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.cpp */; };
+ AFCB1D5F219CD5EA00730AD5 /* Reproducer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFCB1D5E219CD5EA00730AD5 /* Reproducer.cpp */; };
+ 4FBC04ED211A06200015A814 /* RichManglingContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4FBC04EC211A06200015A814 /* RichManglingContext.cpp */; };
+ 4FBC04EF211A06820015A814 /* RichManglingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 4FBC04EE211A06820015A814 /* RichManglingContext.h */; };
+ 4FBC04F5211A13770015A814 /* RichManglingContextTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4FBC04F3211A0F0F0015A814 /* RichManglingContextTest.cpp */; };
26DE204511618ADA00A093E2 /* SBAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26DE204411618ADA00A093E2 /* SBAddress.cpp */; };
26DE204311618ACA00A093E2 /* SBAddress.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE204211618ACA00A093E2 /* SBAddress.h */; settings = {ATTRIBUTES = (Public, ); }; };
254FBBA51A91670E00BD6378 /* SBAttachInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 254FBBA41A91670E00BD6378 /* SBAttachInfo.cpp */; };
@@ -746,6 +763,8 @@
26DE205311618FAC00A093E2 /* SBFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 26DE205211618FAC00A093E2 /* SBFunction.h */; settings = {ATTRIBUTES = (Public, ); }; };
9A3576AA116E9AC700E8ED2F /* SBHostOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */; };
9A3576A8116E9AB700E8ED2F /* SBHostOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A3576A7116E9AB700E8ED2F /* SBHostOS.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ AFB2F2F621B71AF30078DEF1 /* SBInitializerOptions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFB2F2F421B71AE90078DEF1 /* SBInitializerOptions.cpp */; };
+ 4C38996D21BA11CA002BAEF4 /* SBInitializerOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C38996C21BA11CA002BAEF4 /* SBInitializerOptions.h */; settings = {ATTRIBUTES = (Public, ); }; };
9AC703AF117675410086C050 /* SBInstruction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703AE117675410086C050 /* SBInstruction.cpp */; };
9AC7038E117674FB0086C050 /* SBInstruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 9AC7038D117674EB0086C050 /* SBInstruction.h */; settings = {ATTRIBUTES = (Public, ); }; };
9AC703B1117675490086C050 /* SBInstructionList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AC703B0117675490086C050 /* SBInstructionList.cpp */; };
@@ -847,10 +866,11 @@
26D7E45D13D5E30A007FD12B /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */; };
23CB15451D66DA9300EDDDE1 /* SocketAddressTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */; };
23CB153B1D66DA9300EDDDE1 /* SocketTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F93A1BDD332400BA9A93 /* SocketTest.cpp */; };
- 232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */; };
+ 26603879211CA90F00329572 /* SourceBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26603870211CA90D00329572 /* SourceBreakpoint.cpp */; };
2689004C13353E0400698AC0 /* SourceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8F10F1B85900F91463 /* SourceManager.cpp */; };
268900F313353E6F00698AC0 /* StackFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3810F1B90C00F91463 /* StackFrame.cpp */; };
268900F413353E6F00698AC0 /* StackFrameList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */; };
+ 8CF46A6220522A9800423DDF /* StackFrameRecognizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */; };
268900F513353E6F00698AC0 /* StackID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3A10F1B90C00F91463 /* StackID.cpp */; };
2689004D13353E0400698AC0 /* State.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9010F1B85900F91463 /* State.cpp */; };
9A3D43ED1F3237F900EB767C /* StateTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3D43E21F3237D500EB767C /* StateTest.cpp */; };
@@ -885,14 +905,15 @@
268900DD13353E6F00698AC0 /* Symbol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1B10F1B8EC00F91463 /* Symbol.cpp */; };
268900DE13353E6F00698AC0 /* SymbolContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1C10F1B8EC00F91463 /* SymbolContext.cpp */; };
268900DF13353E6F00698AC0 /* SymbolFile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F1D10F1B8EC00F91463 /* SymbolFile.cpp */; };
+ AF97744721E9947E006876A7 /* SymbolFileBreakpad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF97744621E9947B006876A7 /* SymbolFileBreakpad.cpp */; };
268900CA13353E5F00698AC0 /* SymbolFileDWARF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89D910F57C5600BB2B04 /* SymbolFileDWARF.cpp */; };
268900CC13353E5F00698AC0 /* SymbolFileDWARFDebugMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89DB10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.cpp */; };
6D95DC021B9DC057000E318A /* SymbolFileDWARFDwo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D95DBFF1B9DC057000E318A /* SymbolFileDWARFDwo.cpp */; };
4C7D48251F5099B2005314B4 /* SymbolFileDWARFDwoDwp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D481F1F509964005314B4 /* SymbolFileDWARFDwoDwp.cpp */; };
4C7D48241F5099A1005314B4 /* SymbolFileDWARFDwp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C7D481C1F509963005314B4 /* SymbolFileDWARFDwp.cpp */; };
9A2057121F3B824B00F6C293 /* SymbolFileDWARFTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A20570A1F3B81F300F6C293 /* SymbolFileDWARFTests.cpp */; };
+ AFD966BB217140B6006714AC /* SymbolFileNativePDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFD966B7217140B6006714AC /* SymbolFileNativePDB.cpp */; };
AF6335E21C87B21E00F7D554 /* SymbolFilePDB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF6335E01C87B21E00F7D554 /* SymbolFilePDB.cpp */; };
- AF6335E31C87B21E00F7D554 /* SymbolFilePDB.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6335E11C87B21E00F7D554 /* SymbolFilePDB.h */; };
268900CE13353E5F00698AC0 /* SymbolFileSymtab.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260C89DE10F57C5600BB2B04 /* SymbolFileSymtab.cpp */; };
268900E013353E6F00698AC0 /* SymbolVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF94005711C03F6500085DB9 /* SymbolVendor.cpp */; };
2635879417822FC2004C30BA /* SymbolVendorELF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2635879017822E56004C30BA /* SymbolVendorELF.cpp */; };
@@ -917,6 +938,7 @@
23CB15421D66DA9300EDDDE1 /* TaskPoolTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9451BDD346100BA9A93 /* TaskPoolTest.cpp */; };
2689007413353E1A00698AC0 /* Terminal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 268DA873130095ED00C9483A /* Terminal.cpp */; };
4CEC86A4204738C5009B37B1 /* TestArm64InstEmulation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CEC86A3204738C5009B37B1 /* TestArm64InstEmulation.cpp */; };
+ AF7F97682141FA4500795BC0 /* TestArmv7Disassembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF7F97662141FA3800795BC0 /* TestArmv7Disassembly.cpp */; };
23CB15401D66DA9300EDDDE1 /* TestClangASTContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23CB150C1D66CF5600EDDDE1 /* TestClangASTContext.cpp */; };
9A20572D1F3B8E6600F6C293 /* TestCompletion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A20572B1F3B8E6200F6C293 /* TestCompletion.cpp */; };
9A2057171F3B861400F6C293 /* TestDWARFCallFrameInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A2057131F3B860D00F6C293 /* TestDWARFCallFrameInfo.cpp */; };
@@ -973,6 +995,7 @@
54067BF11DF2041B00749AA5 /* UBSanRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 54067BEC1DF2034B00749AA5 /* UBSanRuntime.cpp */; };
2579065D1BD0488100178368 /* UDPSocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2579065B1BD0488100178368 /* UDPSocket.cpp */; };
49CA97001E6AACC900C03FEE /* UUID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49CA96EA1E6AAC6600C03FEE /* UUID.cpp */; };
+ AF0578C4217FA80700CF9D80 /* UdtRecordCompleter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF0578C2217FA80700CF9D80 /* UdtRecordCompleter.cpp */; };
268900CD13353E5F00698AC0 /* UniqueDWARFASTType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26B8B42312EEC52A00A831B2 /* UniqueDWARFASTType.cpp */; };
2689010C13353E6F00698AC0 /* UnixSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C00987011500B4300F316B0 /* UnixSignals.cpp */; };
9A2057201F3B8D2500F6C293 /* UnixSignalsTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A20571E1F3B8D2100F6C293 /* UnixSignalsTest.cpp */; };
@@ -992,6 +1015,7 @@
2654A6901E552ED500DA1013 /* VASprintf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2654A68F1E552ED500DA1013 /* VASprintf.cpp */; };
9A2057031F3A605200F6C293 /* VASprintfTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3D43C41F3150D200EB767C /* VASprintfTest.cpp */; };
AFC2DCF01E6E2FD200283714 /* VMRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AFC2DCEF1E6E2FD200283714 /* VMRange.cpp */; };
+ 26603878211CA90F00329572 /* VSCode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660386E211CA90D00329572 /* VSCode.cpp */; };
2689005613353E0400698AC0 /* Value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9910F1B85900F91463 /* Value.cpp */; };
2689005713353E0400698AC0 /* ValueObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9A10F1B85900F91463 /* ValueObject.cpp */; };
94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; };
@@ -1040,6 +1064,7 @@
2656BBC41AE073A800441749 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
2670F8121862B44A006B332C /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
26780C611867C33D00234593 /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2670F8111862B44A006B332C /* libncurses.dylib */; };
+ 26792622211CA41E00EE1D10 /* libncurses.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 26792621211CA41E00EE1D10 /* libncurses.tbd */; };
26680233115FD1A7008E1FE4 /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F5C37410F3F61B009D5894 /* libobjc.dylib */; };
23CB154A1D66DA9300EDDDE1 /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 2326CF4E1BDD687800A5CEAC /* libpanel.dylib */; };
260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
@@ -1064,6 +1089,7 @@
E769331E1A94D18100C73337 /* lldb-server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E769331D1A94D18100C73337 /* lldb-server.cpp */; };
26680214115FD12C008E1FE4 /* lldb-types.h in Headers */ = {isa = PBXBuildFile; fileRef = 26BC7C2910F1B3BC00F91463 /* lldb-types.h */; settings = {ATTRIBUTES = (Public, ); }; };
94145431175E63B500284436 /* lldb-versioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 94145430175D7FDE00284436 /* lldb-versioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 2679261E211CA3F200EE1D10 /* lldb-vscode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26792619211CA3E100EE1D10 /* lldb-vscode.cpp */; };
AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = AF90106315AB7C5700FF120D /* lldb.1 */; };
2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E7410F1B85900F91463 /* lldb.cpp */; };
AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF415AE51D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp */; };
@@ -1113,6 +1139,13 @@
remoteGlobalIDString = 26680206115FD0ED008E1FE4;
remoteInfo = LLDB;
};
+ 2679261F211CA40700EE1D10 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 26680206115FD0ED008E1FE4;
+ remoteInfo = LLDB;
+ };
2687EACA1508115000DD8C2E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -1254,6 +1287,15 @@
name = "Copy Files";
runOnlyForDeploymentPostprocessing = 1;
};
+ 2679260A211CA3AC00EE1D10 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
940B04E31A89875C0045D5F7 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -1399,6 +1441,8 @@
23E2E5161D903689006F38BB /* ArchSpecTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchSpecTest.cpp; sourceTree = "<group>"; };
AF2E02A11FA2CEAF00A86C34 /* ArchitectureArm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchitectureArm.cpp; sourceTree = "<group>"; };
AF2E02A21FA2CEAF00A86C34 /* ArchitectureArm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchitectureArm.h; sourceTree = "<group>"; };
+ 2647B63021C4366300A81D15 /* ArchitectureMips.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ArchitectureMips.cpp; path = source/Plugins/Architecture/Mips/ArchitectureMips.cpp; sourceTree = SOURCE_ROOT; };
+ 2647B62F21C4366200A81D15 /* ArchitectureMips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ArchitectureMips.h; path = source/Plugins/Architecture/Mips/ArchitectureMips.h; sourceTree = SOURCE_ROOT; };
4C14CEF82057258D00DEEF94 /* ArchitecturePPC64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArchitecturePPC64.cpp; sourceTree = "<group>"; };
4C14CEF72057258D00DEEF94 /* ArchitecturePPC64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArchitecturePPC64.h; sourceTree = "<group>"; };
26BC7E6C10F1B85900F91463 /* Args.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Args.cpp; path = source/Utility/Args.cpp; sourceTree = "<group>"; };
@@ -1417,6 +1461,8 @@
49DEF1201CD7BD90006A7C7D /* BlockPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlockPointer.h; path = Language/CPlusPlus/BlockPointer.h; sourceTree = "<group>"; };
26BC7E0A10F1B83100F91463 /* Breakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Breakpoint.cpp; path = source/Breakpoint/Breakpoint.cpp; sourceTree = "<group>"; };
26BC7CEE10F1B71400F91463 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Breakpoint.h; path = include/lldb/Breakpoint/Breakpoint.h; sourceTree = "<group>"; };
+ 2660387D211CA98200329572 /* BreakpointBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointBase.cpp; path = "tools/lldb-vscode/BreakpointBase.cpp"; sourceTree = "<group>"; };
+ 26603872211CA90D00329572 /* BreakpointBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointBase.h; path = "tools/lldb-vscode/BreakpointBase.h"; sourceTree = "<group>"; };
26BC7E0B10F1B83100F91463 /* BreakpointID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointID.cpp; path = source/Breakpoint/BreakpointID.cpp; sourceTree = "<group>"; };
26BC7CEF10F1B71400F91463 /* BreakpointID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointID.h; path = include/lldb/Breakpoint/BreakpointID.h; sourceTree = "<group>"; };
26BC7E0C10F1B83100F91463 /* BreakpointIDList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointIDList.cpp; path = source/Breakpoint/BreakpointIDList.cpp; sourceTree = "<group>"; };
@@ -1444,12 +1490,14 @@
4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileRegex.h; path = include/lldb/Breakpoint/BreakpointResolverFileRegex.h; sourceTree = "<group>"; };
26D0DD5510FE555900271C65 /* BreakpointResolverName.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverName.cpp; path = source/Breakpoint/BreakpointResolverName.cpp; sourceTree = "<group>"; };
26D0DD5210FE554D00271C65 /* BreakpointResolverName.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverName.h; path = include/lldb/Breakpoint/BreakpointResolverName.h; sourceTree = "<group>"; };
+ 4CCF9F5E2143012F006CC7EA /* BreakpointResolverScripted.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverScripted.cpp; path = source/Breakpoint/BreakpointResolverScripted.cpp; sourceTree = "<group>"; };
+ 4CCF9F6021430141006CC7EA /* BreakpointResolverScripted.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverScripted.h; path = include/lldb/Breakpoint/BreakpointResolverScripted.h; sourceTree = "<group>"; };
26BC7E1310F1B83100F91463 /* BreakpointSite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointSite.cpp; path = source/Breakpoint/BreakpointSite.cpp; sourceTree = "<group>"; };
26BC7CF710F1B71400F91463 /* BreakpointSite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointSite.h; path = include/lldb/Breakpoint/BreakpointSite.h; sourceTree = "<group>"; };
26BC7E1410F1B83100F91463 /* BreakpointSiteList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointSiteList.cpp; path = source/Breakpoint/BreakpointSiteList.cpp; sourceTree = "<group>"; };
26BC7CF810F1B71400F91463 /* BreakpointSiteList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointSiteList.h; path = include/lldb/Breakpoint/BreakpointSiteList.h; sourceTree = "<group>"; };
- 26BC7E6D10F1B85900F91463 /* Broadcaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Broadcaster.cpp; path = source/Core/Broadcaster.cpp; sourceTree = "<group>"; };
- 26BC7D5410F1B77400F91463 /* Broadcaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Broadcaster.h; path = include/lldb/Core/Broadcaster.h; sourceTree = "<group>"; };
+ 2647B63921C436AB00A81D15 /* Broadcaster.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Broadcaster.cpp; path = source/Utility/Broadcaster.cpp; sourceTree = "<group>"; };
+ 2647B63521C4368300A81D15 /* Broadcaster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Broadcaster.h; path = include/lldb/Utility/Broadcaster.h; sourceTree = "<group>"; };
23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BroadcasterTest.cpp; sourceTree = "<group>"; };
949EEDAC1BA76719008C63CF /* CF.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = CF.cpp; path = Language/ObjC/CF.cpp; sourceTree = "<group>"; };
949EEDAD1BA76719008C63CF /* CF.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CF.h; path = Language/ObjC/CF.h; sourceTree = "<group>"; };
@@ -1487,6 +1535,7 @@
23E2E5191D9036F2006F38BB /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
23E2E5361D9048FB006F38BB /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
2669415B1A6DC2AB0063BE93 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = "tools/lldb-mi/CMakeLists.txt"; sourceTree = SOURCE_ROOT; };
+ 26792617211CA3E100EE1D10 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = "tools/lldb-vscode/CMakeLists.txt"; sourceTree = "<group>"; };
9A1890311F47D5D400394BCA /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = TestingSupport/CMakeLists.txt; sourceTree = "<group>"; };
4CB443BC1249920C00C13DC2 /* CPPLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CPPLanguageRuntime.cpp; path = source/Target/CPPLanguageRuntime.cpp; sourceTree = "<group>"; };
4CB443BB1249920C00C13DC2 /* CPPLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CPPLanguageRuntime.h; path = include/lldb/Target/CPPLanguageRuntime.h; sourceTree = "<group>"; };
@@ -1518,6 +1567,8 @@
26BC7D5510F1B77400F91463 /* ClangForward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangForward.h; path = include/lldb/Core/ClangForward.h; sourceTree = "<group>"; };
4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunctionCaller.cpp; path = ExpressionParser/Clang/ClangFunctionCaller.cpp; sourceTree = "<group>"; };
4C98D3E0118FB98F00E575D0 /* ClangFunctionCaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangFunctionCaller.h; path = ExpressionParser/Clang/ClangFunctionCaller.h; sourceTree = "<group>"; };
+ 58A080AB2112AABB00D5580F /* ClangHighlighter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangHighlighter.cpp; path = Language/ClangCommon/ClangHighlighter.cpp; sourceTree = "<group>"; };
+ 58A080AD2112AAC500D5580F /* ClangHighlighter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangHighlighter.h; path = Language/ClangCommon/ClangHighlighter.h; sourceTree = "<group>"; };
4CD44D5620C603A80003557C /* ClangHost.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ClangHost.cpp; path = ExpressionParser/Clang/ClangHost.cpp; sourceTree = "<group>"; };
4CD44D5720C603A90003557C /* ClangHost.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ClangHost.h; path = ExpressionParser/Clang/ClangHost.h; sourceTree = "<group>"; };
4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangModulesDeclVendor.cpp; path = ExpressionParser/Clang/ClangModulesDeclVendor.cpp; sourceTree = "<group>"; };
@@ -1584,6 +1635,8 @@
26DFBC52113B48D600DD817F /* CommandObjectRegexCommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectRegexCommand.h; path = include/lldb/Interpreter/CommandObjectRegexCommand.h; sourceTree = "<group>"; };
26BC7E3B10F1B84700F91463 /* CommandObjectRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectRegister.cpp; path = source/Commands/CommandObjectRegister.cpp; sourceTree = "<group>"; };
26BC7D2210F1B76300F91463 /* CommandObjectRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectRegister.h; path = source/Commands/CommandObjectRegister.h; sourceTree = "<group>"; };
+ AFCB1D5A219CD5A700730AD5 /* CommandObjectReproducer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectReproducer.cpp; path = source/Commands/CommandObjectReproducer.cpp; sourceTree = "<group>"; };
+ AFCB1D5B219CD5A700730AD5 /* CommandObjectReproducer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectReproducer.h; path = source/Commands/CommandObjectReproducer.h; sourceTree = "<group>"; };
26BC7E3D10F1B84700F91463 /* CommandObjectScript.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectScript.cpp; path = source/Interpreter/CommandObjectScript.cpp; sourceTree = "<group>"; };
26BC7D2410F1B76300F91463 /* CommandObjectScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectScript.h; path = source/Interpreter/CommandObjectScript.h; sourceTree = "<group>"; };
26BC7E4010F1B84700F91463 /* CommandObjectSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectSettings.cpp; path = source/Commands/CommandObjectSettings.cpp; sourceTree = "<group>"; };
@@ -1616,6 +1669,8 @@
964463ED1A330C1B00154ED8 /* CompactUnwindInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompactUnwindInfo.h; path = include/lldb/Symbol/CompactUnwindInfo.h; sourceTree = "<group>"; };
26BC7F1510F1B8EC00F91463 /* CompileUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompileUnit.cpp; path = source/Symbol/CompileUnit.cpp; sourceTree = "<group>"; };
26BC7C5710F1B6E900F91463 /* CompileUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompileUnit.h; path = include/lldb/Symbol/CompileUnit.h; sourceTree = "<group>"; };
+ AFD966B4217140B5006714AC /* CompileUnitIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompileUnitIndex.cpp; path = source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp; sourceTree = SOURCE_ROOT; };
+ AFD966BD217140C8006714AC /* CompileUnitIndex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CompileUnitIndex.h; path = source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h; sourceTree = SOURCE_ROOT; };
265192C51BA8E905002F08F6 /* CompilerDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerDecl.cpp; path = source/Symbol/CompilerDecl.cpp; sourceTree = "<group>"; };
265192C41BA8E8F8002F08F6 /* CompilerDecl.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = CompilerDecl.h; path = include/lldb/Symbol/CompilerDecl.h; sourceTree = "<group>"; };
2657AFB61B86910100958979 /* CompilerDeclContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompilerDeclContext.cpp; path = source/Symbol/CompilerDeclContext.cpp; sourceTree = "<group>"; };
@@ -1646,12 +1701,6 @@
269DDD451B8FD01A00D0DBD8 /* DWARFASTParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParser.h; sourceTree = "<group>"; };
269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserClang.cpp; sourceTree = "<group>"; };
269DDD491B8FD1C300D0DBD8 /* DWARFASTParserClang.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserClang.h; sourceTree = "<group>"; };
- AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserGo.cpp; sourceTree = "<group>"; };
- AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserGo.h; sourceTree = "<group>"; };
- 6D0F61441C80AACF00A4ECEE /* DWARFASTParserJava.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserJava.cpp; sourceTree = "<group>"; };
- 6D0F61451C80AACF00A4ECEE /* DWARFASTParserJava.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserJava.h; sourceTree = "<group>"; };
- 4CC7C6521D5299140076FF94 /* DWARFASTParserOCaml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFASTParserOCaml.cpp; sourceTree = "<group>"; };
- 4CC7C6511D5299140076FF94 /* DWARFASTParserOCaml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFASTParserOCaml.h; sourceTree = "<group>"; };
260C89B310F57C5600BB2B04 /* DWARFAbbreviationDeclaration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFAbbreviationDeclaration.cpp; sourceTree = "<group>"; };
260C89B410F57C5600BB2B04 /* DWARFAbbreviationDeclaration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFAbbreviationDeclaration.h; sourceTree = "<group>"; };
266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFAttribute.cpp; sourceTree = "<group>"; };
@@ -1698,6 +1747,8 @@
260C89D410F57C5600BB2B04 /* DWARFFormValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFFormValue.h; sourceTree = "<group>"; };
4CD44CF820B37C440003557C /* DWARFIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFIndex.cpp; sourceTree = "<group>"; };
4CD44CFE20B37C570003557C /* DWARFIndex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DWARFIndex.h; sourceTree = "<group>"; };
+ 4C38996221B9AECC002BAEF4 /* DWARFLocationExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DWARFLocationExpression.cpp; path = source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp; sourceTree = SOURCE_ROOT; };
+ 4C38996321B9AECC002BAEF4 /* DWARFLocationExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWARFLocationExpression.h; path = source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h; sourceTree = SOURCE_ROOT; };
7F2AAA5920601BE000A422D8 /* DWARFUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DWARFUnit.cpp; sourceTree = "<group>"; };
7F2AAA5820601BDF00A422D8 /* DWARFUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DWARFUnit.h; sourceTree = "<group>"; };
26FFC19514FC072100087D58 /* DYLDRendezvous.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DYLDRendezvous.cpp; sourceTree = "<group>"; };
@@ -1711,7 +1762,7 @@
49CA96F31E6AAC8E00C03FEE /* DataEncoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataEncoder.h; path = include/lldb/Utility/DataEncoder.h; sourceTree = "<group>"; };
49CA96E91E6AAC6600C03FEE /* DataExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataExtractor.cpp; path = source/Utility/DataExtractor.cpp; sourceTree = "<group>"; };
49CA96F41E6AAC8E00C03FEE /* DataExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataExtractor.h; path = include/lldb/Utility/DataExtractor.h; sourceTree = "<group>"; };
- 23CB14E81D66CC0E00EDDDE1 /* DataExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataExtractorTest.cpp; sourceTree = "<group>"; };
+ AFA1B62B219E0ED900A8AB7E /* DataExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataExtractorTest.cpp; sourceTree = "<group>"; };
94CB255816B069770059775D /* DataVisualization.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DataVisualization.cpp; path = source/DataFormatters/DataVisualization.cpp; sourceTree = "<group>"; };
94CB256016B069800059775D /* DataVisualization.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DataVisualization.h; path = include/lldb/DataFormatters/DataVisualization.h; sourceTree = "<group>"; };
3FDFED1E19BA6D55009756A7 /* Debug.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Debug.h; path = include/lldb/Host/Debug.h; sourceTree = "<group>"; };
@@ -1765,7 +1816,6 @@
26CFDCA2186163A4000E63E5 /* Editline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Editline.cpp; sourceTree = "<group>"; };
26CFDCA01861638D000E63E5 /* Editline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Editline.h; path = include/lldb/Host/Editline.h; sourceTree = "<group>"; };
2326CF511BDD693B00A5CEAC /* EditlineTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditlineTest.cpp; sourceTree = "<group>"; };
- 9481FE6B1B5F2D9200DED357 /* Either.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Either.h; path = include/lldb/Utility/Either.h; sourceTree = "<group>"; };
26D9FDC812F784FD0003F2EE /* EmulateInstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = EmulateInstruction.cpp; path = source/Core/EmulateInstruction.cpp; sourceTree = "<group>"; };
26D9FDC612F784E60003F2EE /* EmulateInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EmulateInstruction.h; path = include/lldb/Core/EmulateInstruction.h; sourceTree = "<group>"; };
9A22A15D135E30370024DDC3 /* EmulateInstructionARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EmulateInstructionARM.cpp; sourceTree = "<group>"; };
@@ -1783,8 +1833,10 @@
26BC7DD310F1B7D500F91463 /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Endian.h; path = include/lldb/Utility/Endian.h; sourceTree = "<group>"; };
22DC561920064C9600A7E9E8 /* Environment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Environment.cpp; path = source/Utility/Environment.cpp; sourceTree = "<group>"; };
6B74D89C2006972D0074051B /* Environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Environment.h; path = include/lldb/Utility/Environment.h; sourceTree = "<group>"; };
- 26BC7E7910F1B85900F91463 /* Event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Event.cpp; path = source/Core/Event.cpp; sourceTree = "<group>"; };
- 26BC7D6110F1B77400F91463 /* Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Event.h; path = include/lldb/Core/Event.h; sourceTree = "<group>"; };
+ 2647B63B21C436B400A81D15 /* Event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Event.cpp; path = source/Utility/Event.cpp; sourceTree = "<group>"; };
+ 2647B63321C4367A00A81D15 /* Event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Event.h; path = include/lldb/Utility/Event.h; sourceTree = "<group>"; };
+ 26603874211CA90E00329572 /* ExceptionBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExceptionBreakpoint.cpp; path = "tools/lldb-vscode/ExceptionBreakpoint.cpp"; sourceTree = "<group>"; };
+ 26603873211CA90E00329572 /* ExceptionBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExceptionBreakpoint.h; path = "tools/lldb-vscode/ExceptionBreakpoint.h"; sourceTree = "<group>"; };
26BC7F3510F1B90C00F91463 /* ExecutionContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExecutionContext.cpp; path = source/Target/ExecutionContext.cpp; sourceTree = "<group>"; };
26BC7DF210F1B81A00F91463 /* ExecutionContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExecutionContext.h; path = include/lldb/Target/ExecutionContext.h; sourceTree = "<group>"; };
26DAFD9711529BC7005A394E /* ExecutionContextScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExecutionContextScope.h; path = include/lldb/Target/ExecutionContextScope.h; sourceTree = "<group>"; };
@@ -1796,8 +1848,6 @@
4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ExpressionTypeSystemHelper.h; path = include/lldb/Expression/ExpressionTypeSystemHelper.h; sourceTree = "<group>"; };
4984BA151B979973008658D4 /* ExpressionVariable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ExpressionVariable.cpp; path = source/Expression/ExpressionVariable.cpp; sourceTree = "<group>"; };
4984BA171B979C08008658D4 /* ExpressionVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ExpressionVariable.h; path = include/lldb/Expression/ExpressionVariable.h; sourceTree = "<group>"; };
- AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FastDemangle.cpp; path = source/Utility/FastDemangle.cpp; sourceTree = "<group>"; };
- AFC2DCED1E6E2F9800283714 /* FastDemangle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = FastDemangle.h; path = include/lldb/Utility/FastDemangle.h; sourceTree = "<group>"; };
260C6EA213011581005E16B0 /* File.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = File.cpp; sourceTree = "<group>"; };
260C6EA013011578005E16B0 /* File.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = File.h; path = include/lldb/Host/File.h; sourceTree = "<group>"; };
3FDFDDBC199C3A06009756A7 /* FileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileAction.cpp; path = source/Target/FileAction.cpp; sourceTree = "<group>"; };
@@ -1838,6 +1888,8 @@
269FF07D12494F7D00225026 /* FuncUnwinders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FuncUnwinders.h; path = include/lldb/Symbol/FuncUnwinders.h; sourceTree = "<group>"; };
26BC7F1810F1B8EC00F91463 /* Function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Function.cpp; path = source/Symbol/Function.cpp; sourceTree = "<group>"; };
26BC7C5A10F1B6E900F91463 /* Function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Function.h; path = include/lldb/Symbol/Function.h; sourceTree = "<group>"; };
+ 26603877211CA90E00329572 /* FunctionBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FunctionBreakpoint.cpp; path = "tools/lldb-vscode/FunctionBreakpoint.cpp"; sourceTree = "<group>"; };
+ 26603871211CA90D00329572 /* FunctionBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FunctionBreakpoint.h; path = "tools/lldb-vscode/FunctionBreakpoint.h"; sourceTree = "<group>"; };
4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FunctionCaller.cpp; path = source/Expression/FunctionCaller.cpp; sourceTree = "<group>"; };
4C00832D1B9A58A700D5CF24 /* FunctionCaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FunctionCaller.h; path = include/lldb/Expression/FunctionCaller.h; sourceTree = "<group>"; };
2374D74E1D4BB299005C9575 /* GDBRemoteClientBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteClientBase.cpp; sourceTree = "<group>"; };
@@ -1848,6 +1900,10 @@
26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClient.cpp; sourceTree = "<group>"; };
26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationClient.h; sourceTree = "<group>"; };
2370A37E1D66C587000E7BE6 /* GDBRemoteCommunicationClientTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationClientTest.cpp; sourceTree = "<group>"; };
+ AF8AD943219CD45700614785 /* GDBRemoteCommunicationHistory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationHistory.cpp; sourceTree = "<group>"; };
+ AF8AD944219CD45700614785 /* GDBRemoteCommunicationHistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationHistory.h; sourceTree = "<group>"; };
+ AFCB1D57219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationReplayServer.cpp; sourceTree = "<group>"; };
+ AFCB1D56219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationReplayServer.h; sourceTree = "<group>"; };
26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServer.cpp; sourceTree = "<group>"; };
26744EF01338317700EF765A /* GDBRemoteCommunicationServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteCommunicationServer.h; sourceTree = "<group>"; };
6D55B28D1A8A806200A70529 /* GDBRemoteCommunicationServerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteCommunicationServerCommon.cpp; sourceTree = "<group>"; };
@@ -1862,26 +1918,12 @@
E73A15A51B548EC500786197 /* GDBRemoteSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GDBRemoteSignals.h; path = Utility/GDBRemoteSignals.h; sourceTree = "<group>"; };
2370A37F1D66C587000E7BE6 /* GDBRemoteTestUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GDBRemoteTestUtils.cpp; sourceTree = "<group>"; };
2370A3801D66C587000E7BE6 /* GDBRemoteTestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GDBRemoteTestUtils.h; sourceTree = "<group>"; };
- AE44FB261BB07DC60033EB62 /* GoAST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoAST.h; path = ExpressionParser/Go/GoAST.h; sourceTree = "<group>"; };
- AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoASTContext.cpp; path = source/Symbol/GoASTContext.cpp; sourceTree = "<group>"; };
- AEEA340F1ACA08A000AB639D /* GoASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoASTContext.h; path = include/lldb/Symbol/GoASTContext.h; sourceTree = "<group>"; };
- AE44FB4A1BB4BB540033EB62 /* GoFormatterFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoFormatterFunctions.cpp; path = Language/Go/GoFormatterFunctions.cpp; sourceTree = "<group>"; };
- AE44FB4B1BB4BB540033EB62 /* GoFormatterFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoFormatterFunctions.h; path = Language/Go/GoFormatterFunctions.h; sourceTree = "<group>"; };
- AE44FB451BB4BB090033EB62 /* GoLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLanguage.cpp; path = Language/Go/GoLanguage.cpp; sourceTree = "<group>"; };
- AE44FB461BB4BB090033EB62 /* GoLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GoLanguage.h; path = Language/Go/GoLanguage.h; sourceTree = "<group>"; };
- AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLanguageRuntime.cpp; path = Go/GoLanguageRuntime.cpp; sourceTree = "<group>"; };
- AE44FB3C1BB4858A0033EB62 /* GoLanguageRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoLanguageRuntime.h; path = Go/GoLanguageRuntime.h; sourceTree = "<group>"; };
- AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoLexer.cpp; path = ExpressionParser/Go/GoLexer.cpp; sourceTree = "<group>"; };
- AE44FB271BB07DC60033EB62 /* GoLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoLexer.h; path = ExpressionParser/Go/GoLexer.h; sourceTree = "<group>"; };
- AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoParser.cpp; path = ExpressionParser/Go/GoParser.cpp; sourceTree = "<group>"; };
- AE44FB281BB07DC60033EB62 /* GoParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoParser.h; path = ExpressionParser/Go/GoParser.h; sourceTree = "<group>"; };
- AEC6FF9F1BE970A2007882C1 /* GoParserTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GoParserTest.cpp; sourceTree = "<group>"; };
- AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GoUserExpression.cpp; path = ExpressionParser/Go/GoUserExpression.cpp; sourceTree = "<group>"; };
- AE44FB291BB07DC60033EB62 /* GoUserExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GoUserExpression.h; path = ExpressionParser/Go/GoUserExpression.h; sourceTree = "<group>"; };
6D95DBFE1B9DC057000E318A /* HashedNameToDIE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashedNameToDIE.cpp; sourceTree = "<group>"; };
26A0DA4D140F721D006DA411 /* HashedNameToDIE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HashedNameToDIE.h; sourceTree = "<group>"; };
2666ADC31B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HexagonDYLDRendezvous.cpp; sourceTree = "<group>"; };
2666ADC41B3CB675001FAFD3 /* HexagonDYLDRendezvous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexagonDYLDRendezvous.h; sourceTree = "<group>"; };
+ 58A080A92112AA9400D5580F /* Highlighter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Highlighter.cpp; path = source/Core/Highlighter.cpp; sourceTree = "<group>"; };
+ 58A080B12112AB2200D5580F /* HighlighterTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HighlighterTest.cpp; path = unittests/Language/Highlighting/HighlighterTest.cpp; sourceTree = SOURCE_ROOT; };
AF1729D4182C907200E0AB97 /* HistoryThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HistoryThread.cpp; path = Utility/HistoryThread.cpp; sourceTree = "<group>"; };
AF061F89182C980000B6A19C /* HistoryThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HistoryThread.h; path = Utility/HistoryThread.h; sourceTree = "<group>"; };
AF1729D5182C907200E0AB97 /* HistoryUnwind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HistoryUnwind.cpp; path = Utility/HistoryUnwind.cpp; sourceTree = "<group>"; };
@@ -1966,14 +2008,8 @@
942829551A89614C00521B30 /* JSON.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSON.cpp; path = source/Utility/JSON.cpp; sourceTree = "<group>"; };
942829541A89614000521B30 /* JSON.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = JSON.h; path = include/lldb/Utility/JSON.h; sourceTree = "<group>"; };
8C3BD99F1EF5D1B50016C343 /* JSONTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSONTest.cpp; sourceTree = "<group>"; };
- 6D0F61411C80AAAA00A4ECEE /* JavaASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaASTContext.cpp; path = source/Symbol/JavaASTContext.cpp; sourceTree = "<group>"; };
- 6D0F613D1C80AA8900A4ECEE /* JavaASTContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaASTContext.h; path = include/lldb/Symbol/JavaASTContext.h; sourceTree = "<group>"; };
- 6D0F61511C80AB3000A4ECEE /* JavaFormatterFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaFormatterFunctions.cpp; path = Language/Java/JavaFormatterFunctions.cpp; sourceTree = "<group>"; };
- 6D0F61521C80AB3000A4ECEE /* JavaFormatterFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaFormatterFunctions.h; path = Language/Java/JavaFormatterFunctions.h; sourceTree = "<group>"; };
- 6D0F61531C80AB3000A4ECEE /* JavaLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaLanguage.cpp; path = Language/Java/JavaLanguage.cpp; sourceTree = "<group>"; };
- 6D0F61541C80AB3000A4ECEE /* JavaLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaLanguage.h; path = Language/Java/JavaLanguage.h; sourceTree = "<group>"; };
- 6D0F614A1C80AB0400A4ECEE /* JavaLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JavaLanguageRuntime.cpp; path = Java/JavaLanguageRuntime.cpp; sourceTree = "<group>"; };
- 6D0F614B1C80AB0400A4ECEE /* JavaLanguageRuntime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JavaLanguageRuntime.h; path = Java/JavaLanguageRuntime.h; sourceTree = "<group>"; };
+ 26603875211CA90E00329572 /* JSONUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSONUtils.cpp; path = "tools/lldb-vscode/JSONUtils.cpp"; sourceTree = "<group>"; };
+ 26603876211CA90E00329572 /* JSONUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSONUtils.h; path = "tools/lldb-vscode/JSONUtils.h"; sourceTree = "<group>"; };
26680207115FD0ED008E1FE4 /* LLDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = LLDB.framework; sourceTree = BUILT_PRODUCTS_DIR; };
26B42C4C1187ABA50079C8C8 /* LLDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLDB.h; path = include/lldb/API/LLDB.h; sourceTree = "<group>"; };
943BDEFD1AA7B2F800789CE8 /* LLDBAssert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBAssert.cpp; path = source/Utility/LLDBAssert.cpp; sourceTree = "<group>"; };
@@ -1982,6 +2018,8 @@
6D762BEC1B1605CD006C929D /* LLDBServerUtilities.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBServerUtilities.cpp; path = "tools/lldb-server/LLDBServerUtilities.cpp"; sourceTree = "<group>"; };
6D762BED1B1605CD006C929D /* LLDBServerUtilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLDBServerUtilities.h; path = "tools/lldb-server/LLDBServerUtilities.h"; sourceTree = "<group>"; };
2361029A1CF38A2B00B8E0B9 /* LLDBStandalone.cmake */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LLDBStandalone.cmake; sourceTree = "<group>"; };
+ 26F76199211CBBB30044F6EA /* LLDBUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLDBUtils.cpp; path = "tools/lldb-vscode/LLDBUtils.cpp"; sourceTree = "<group>"; };
+ 26F7619A211CBBB30044F6EA /* LLDBUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLDBUtils.h; path = "tools/lldb-vscode/LLDBUtils.h"; sourceTree = "<group>"; };
26A4EEB511682AAC007A372A /* LLDBWrapPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = LLDBWrapPython.cpp; sourceTree = BUILT_PRODUCTS_DIR; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
AEB0E4581BD6E9F800B24093 /* LLVMUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLVMUserExpression.cpp; path = source/Expression/LLVMUserExpression.cpp; sourceTree = "<group>"; };
AEB0E45A1BD6EA1400B24093 /* LLVMUserExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LLVMUserExpression.h; path = include/lldb/Expression/LLVMUserExpression.h; sourceTree = "<group>"; };
@@ -2000,9 +2038,12 @@
945261B71B9A11E800BF138D /* LibCxxInitializerList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxInitializerList.cpp; path = Language/CPlusPlus/LibCxxInitializerList.cpp; sourceTree = "<group>"; };
945261B81B9A11E800BF138D /* LibCxxList.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxList.cpp; path = Language/CPlusPlus/LibCxxList.cpp; sourceTree = "<group>"; };
945261B91B9A11E800BF138D /* LibCxxMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxMap.cpp; path = Language/CPlusPlus/LibCxxMap.cpp; sourceTree = "<group>"; };
+ E4A63A9020F55D27000D9548 /* LibCxxOptional.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxOptional.cpp; path = Language/CPlusPlus/LibCxxOptional.cpp; sourceTree = "<group>"; };
AF9FF1F61FAA79FE00474976 /* LibCxxQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxQueue.cpp; path = Language/CPlusPlus/LibCxxQueue.cpp; sourceTree = "<group>"; };
AF9FF1F41FAA79A400474976 /* LibCxxTuple.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxTuple.cpp; path = Language/CPlusPlus/LibCxxTuple.cpp; sourceTree = "<group>"; };
945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxUnorderedMap.cpp; path = Language/CPlusPlus/LibCxxUnorderedMap.cpp; sourceTree = "<group>"; };
+ E414F6F021388F6B00C50BC6 /* LibCxxVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxVariant.cpp; path = Language/CPlusPlus/LibCxxVariant.cpp; sourceTree = "<group>"; };
+ E414F6ED21388F0200C50BC6 /* LibCxxVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LibCxxVariant.h; path = Language/CPlusPlus/LibCxxVariant.h; sourceTree = "<group>"; };
945261BB1B9A11E800BF138D /* LibCxxVector.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibCxxVector.cpp; path = Language/CPlusPlus/LibCxxVector.cpp; sourceTree = "<group>"; };
945261BC1B9A11E800BF138D /* LibStdcpp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibStdcpp.cpp; path = Language/CPlusPlus/LibStdcpp.cpp; sourceTree = "<group>"; };
945261BD1B9A11E800BF138D /* LibStdcpp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = LibStdcpp.h; path = Language/CPlusPlus/LibStdcpp.h; sourceTree = "<group>"; };
@@ -2012,10 +2053,12 @@
26BC7C5B10F1B6E900F91463 /* LineEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineEntry.h; path = include/lldb/Symbol/LineEntry.h; sourceTree = "<group>"; };
26BC7F1A10F1B8EC00F91463 /* LineTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LineTable.cpp; path = source/Symbol/LineTable.cpp; sourceTree = "<group>"; };
26BC7C5C10F1B6E900F91463 /* LineTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LineTable.h; path = include/lldb/Symbol/LineTable.h; sourceTree = "<group>"; };
+ 2647B64221C43BB000A81D15 /* LinuxProcMaps.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LinuxProcMaps.cpp; path = Utility/LinuxProcMaps.cpp; sourceTree = "<group>"; };
+ 2647B64121C43BAF00A81D15 /* LinuxProcMaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LinuxProcMaps.h; path = Utility/LinuxProcMaps.h; sourceTree = "<group>"; };
23059A0519532B96007B8189 /* LinuxSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LinuxSignals.cpp; path = Utility/LinuxSignals.cpp; sourceTree = "<group>"; };
23059A0619532B96007B8189 /* LinuxSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LinuxSignals.h; path = Utility/LinuxSignals.h; sourceTree = "<group>"; };
- 26BC7E7E10F1B85900F91463 /* Listener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Listener.cpp; path = source/Core/Listener.cpp; sourceTree = "<group>"; };
- 26BC7D6710F1B77400F91463 /* Listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Listener.h; path = include/lldb/Core/Listener.h; sourceTree = "<group>"; };
+ 2647B63D21C436BC00A81D15 /* Listener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Listener.cpp; path = source/Utility/Listener.cpp; sourceTree = "<group>"; };
+ 2647B63721C4369500A81D15 /* Listener.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Listener.h; path = include/lldb/Utility/Listener.h; sourceTree = "<group>"; };
9A3D43E31F3237D500EB767C /* ListenerTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ListenerTest.cpp; sourceTree = "<group>"; };
255EFF731AFABA720069F277 /* LockFileBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFileBase.cpp; sourceTree = "<group>"; };
255EFF751AFABA950069F277 /* LockFilePosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LockFilePosix.cpp; sourceTree = "<group>"; };
@@ -2178,12 +2221,13 @@
266941F91A6DC2AC0063BE93 /* MIUtilThreadBaseStd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilThreadBaseStd.h; path = "tools/lldb-mi/MIUtilThreadBaseStd.h"; sourceTree = SOURCE_ROOT; };
266941FA1A6DC2AC0063BE93 /* MIUtilVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MIUtilVariant.cpp; path = "tools/lldb-mi/MIUtilVariant.cpp"; sourceTree = SOURCE_ROOT; };
266941FB1A6DC2AC0063BE93 /* MIUtilVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MIUtilVariant.h; path = "tools/lldb-mi/MIUtilVariant.h"; sourceTree = SOURCE_ROOT; };
+ AF395C01219254F200894EC3 /* MSVCUndecoratedNameParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MSVCUndecoratedNameParser.cpp; path = Language/CPlusPlus/MSVCUndecoratedNameParser.cpp; sourceTree = "<group>"; };
+ AF395C00219254F200894EC3 /* MSVCUndecoratedNameParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSVCUndecoratedNameParser.h; path = Language/CPlusPlus/MSVCUndecoratedNameParser.h; sourceTree = "<group>"; };
D67521351EA17C3900439694 /* MainLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoop.cpp; sourceTree = "<group>"; };
9A2057301F3B8E7600F6C293 /* MainLoopTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainLoopTest.cpp; sourceTree = "<group>"; };
8C3BD9951EF45D9B0016C343 /* MainThreadCheckerRuntime.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = MainThreadCheckerRuntime.cpp; sourceTree = "<group>"; };
8C3BD9931EF45D9B0016C343 /* MainThreadCheckerRuntime.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainThreadCheckerRuntime.h; sourceTree = "<group>"; };
2665CD0D15080846002C8FAE /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
- 2669415F1A6DC2AB0063BE93 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = "tools/lldb-mi/Makefile"; sourceTree = SOURCE_ROOT; };
26BC7E8010F1B85900F91463 /* Mangled.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Mangled.cpp; path = source/Core/Mangled.cpp; sourceTree = "<group>"; };
26BC7D6910F1B77400F91463 /* Mangled.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Mangled.h; path = include/lldb/Core/Mangled.h; sourceTree = "<group>"; };
4F29D3CD21010F84003B549A /* MangledTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MangledTest.cpp; sourceTree = "<group>"; };
@@ -2234,9 +2278,6 @@
9A3D43CB1F3150D200EB767C /* NameMatchesTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameMatchesTest.cpp; sourceTree = "<group>"; };
2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameToDIE.cpp; sourceTree = "<group>"; };
2618D957124056C700F2B8FE /* NameToDIE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NameToDIE.h; sourceTree = "<group>"; };
- 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Host/common/NativeBreakpoint.cpp; sourceTree = "<group>"; };
- 267A47F31B14116E0021A5BC /* NativeBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = include/lldb/Host/common/NativeBreakpoint.h; sourceTree = "<group>"; };
- 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpointList.cpp; path = source/Host/common/NativeBreakpointList.cpp; sourceTree = "<group>"; };
267A47F41B1411750021A5BC /* NativeBreakpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = include/lldb/Host/common/NativeBreakpointList.h; sourceTree = "<group>"; };
232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = NativeProcessProtocol.cpp; path = source/Host/common/NativeProcessProtocol.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = include/lldb/Host/common/NativeProcessProtocol.h; sourceTree = "<group>"; };
@@ -2252,9 +2293,6 @@
267A47F91B1411AC0021A5BC /* NativeWatchpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeWatchpointList.h; path = include/lldb/Host/common/NativeWatchpointList.h; sourceTree = "<group>"; };
AF33B4BC1C1FA441001B28D9 /* NetBSDSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NetBSDSignals.cpp; path = Utility/NetBSDSignals.cpp; sourceTree = "<group>"; };
AF33B4BD1C1FA441001B28D9 /* NetBSDSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NetBSDSignals.h; path = Utility/NetBSDSignals.h; sourceTree = "<group>"; };
- 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OCamlASTContext.cpp; path = source/Symbol/OCamlASTContext.cpp; sourceTree = "<group>"; };
- 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OCamlLanguage.cpp; path = Language/OCaml/OCamlLanguage.cpp; sourceTree = "<group>"; };
- 4CC7C64C1D5298E20076FF94 /* OCamlLanguage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OCamlLanguage.h; path = Language/OCaml/OCamlLanguage.h; sourceTree = "<group>"; };
94B6385E1B8FB7A2004FE1E4 /* ObjCLanguage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCLanguage.cpp; path = Language/ObjC/ObjCLanguage.cpp; sourceTree = "<group>"; };
94B6385F1B8FB7A2004FE1E4 /* ObjCLanguage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ObjCLanguage.h; path = Language/ObjC/ObjCLanguage.h; sourceTree = "<group>"; };
4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCLanguageRuntime.cpp; path = source/Target/ObjCLanguageRuntime.cpp; sourceTree = "<group>"; };
@@ -2268,6 +2306,8 @@
260C898110F57C5600BB2B04 /* ObjectContainerUniversalMachO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectContainerUniversalMachO.h; sourceTree = "<group>"; };
26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjectFile.cpp; path = source/Symbol/ObjectFile.cpp; sourceTree = "<group>"; };
26BC7C5E10F1B6E900F91463 /* ObjectFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjectFile.h; path = include/lldb/Symbol/ObjectFile.h; sourceTree = "<group>"; };
+ 4C9BF11921C0467700FA4036 /* ObjectFileBreakpad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileBreakpad.cpp; sourceTree = "<group>"; };
+ 4C9BF11821C0467700FA4036 /* ObjectFileBreakpad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFileBreakpad.h; sourceTree = "<group>"; };
260C898510F57C5600BB2B04 /* ObjectFileELF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileELF.cpp; sourceTree = "<group>"; };
260C898610F57C5600BB2B04 /* ObjectFileELF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectFileELF.h; sourceTree = "<group>"; };
26EFC4CA18CFAF0D00865D87 /* ObjectFileJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ObjectFileJIT.cpp; sourceTree = "<group>"; };
@@ -2280,8 +2320,6 @@
26651A15133BF9CC005B64B7 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Opcode.h; path = include/lldb/Core/Opcode.h; sourceTree = "<group>"; };
266DFE9613FD656E00D0C574 /* OperatingSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystem.cpp; path = source/Target/OperatingSystem.cpp; sourceTree = "<group>"; };
266DFE9813FD658300D0C574 /* OperatingSystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = OperatingSystem.h; path = include/lldb/Target/OperatingSystem.h; sourceTree = "<group>"; };
- AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OperatingSystemGo.cpp; path = Go/OperatingSystemGo.cpp; sourceTree = "<group>"; };
- AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OperatingSystemGo.h; path = Go/OperatingSystemGo.h; sourceTree = "<group>"; };
2698699815E6CBD0002415FF /* OperatingSystemPython.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OperatingSystemPython.cpp; sourceTree = "<group>"; };
2698699915E6CBD0002415FF /* OperatingSystemPython.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OperatingSystemPython.h; sourceTree = "<group>"; };
4C719394207D235400FDF430 /* OptionArgParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptionArgParser.cpp; path = source/Interpreter/OptionArgParser.cpp; sourceTree = "<group>"; };
@@ -2355,6 +2393,8 @@
260A248D15D06C4F009981B0 /* OptionValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OptionValues.h; path = include/lldb/Interpreter/OptionValues.h; sourceTree = "<group>"; };
26BC7E8610F1B85900F91463 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Options.cpp; path = source/Interpreter/Options.cpp; sourceTree = "<group>"; };
26BC7D6D10F1B77400F91463 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Options.h; path = include/lldb/Interpreter/Options.h; sourceTree = "<group>"; };
+ DD5F951A21ADE5BD00B8265A /* Options.inc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.pascal; name = Options.inc; path = build/Debug/include/Options.inc; sourceTree = "<group>"; };
+ DD5F951B21ADE5F000B8265A /* Options.td */ = {isa = PBXFileReference; lastKnownFileType = text; name = Options.td; path = tools/driver/Options.td; sourceTree = "<group>"; };
4C562CC21CC07DDD00C52EAC /* PDBASTParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PDBASTParser.cpp; path = PDB/PDBASTParser.cpp; sourceTree = "<group>"; };
4C562CC31CC07DDD00C52EAC /* PDBASTParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDBASTParser.h; path = PDB/PDBASTParser.h; sourceTree = "<group>"; };
4CA0C6CA20F929C600CFE6BB /* PDBLocationToDWARFExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PDBLocationToDWARFExpression.cpp; path = PDB/PDBLocationToDWARFExpression.cpp; sourceTree = "<group>"; };
@@ -2364,6 +2404,14 @@
495BBACB119A0DBE00418BEA /* PathMappingList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingList.cpp; path = source/Target/PathMappingList.cpp; sourceTree = "<group>"; };
495BBACF119A0DE700418BEA /* PathMappingList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PathMappingList.h; path = include/lldb/Target/PathMappingList.h; sourceTree = "<group>"; };
2668A2ED20AF417D00D94111 /* PathMappingListTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PathMappingListTest.cpp; path = Target/PathMappingListTest.cpp; sourceTree = "<group>"; };
+ AF815DF721C855B400023A34 /* PdbAstBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PdbAstBuilder.cpp; path = source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp; sourceTree = SOURCE_ROOT; };
+ AF815DF821C855B400023A34 /* PdbAstBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PdbAstBuilder.h; path = source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h; sourceTree = SOURCE_ROOT; };
+ AFD966B6217140B6006714AC /* PdbIndex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PdbIndex.cpp; path = source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp; sourceTree = SOURCE_ROOT; };
+ AFD966BF217140C8006714AC /* PdbIndex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PdbIndex.h; path = source/Plugins/SymbolFile/NativePDB/PdbIndex.h; sourceTree = SOURCE_ROOT; };
+ AF0F459D219FA1C800C1E612 /* PdbSymUid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PdbSymUid.cpp; path = source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp; sourceTree = SOURCE_ROOT; };
+ AFD966BC217140C8006714AC /* PdbSymUid.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PdbSymUid.h; path = source/Plugins/SymbolFile/NativePDB/PdbSymUid.h; sourceTree = SOURCE_ROOT; };
+ AFD966B5217140B6006714AC /* PdbUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PdbUtil.cpp; path = source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp; sourceTree = SOURCE_ROOT; };
+ AFD966BE217140C8006714AC /* PdbUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PdbUtil.h; path = source/Plugins/SymbolFile/NativePDB/PdbUtil.h; sourceTree = SOURCE_ROOT; };
260A39A519647A3A004B4130 /* Pipe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Pipe.h; path = include/lldb/Host/Pipe.h; sourceTree = "<group>"; };
25420ED11A649D88009ADBCB /* PipeBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PipeBase.cpp; sourceTree = "<group>"; };
3F5E8AF31A40D4A500A73232 /* PipeBase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PipeBase.h; path = include/lldb/Host/PipeBase.h; sourceTree = "<group>"; };
@@ -2401,6 +2449,8 @@
4CE4EFA71E8999B000A80C06 /* PlatformOpenBSD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformOpenBSD.h; sourceTree = "<group>"; };
945759651534941F005A9070 /* PlatformPOSIX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PlatformPOSIX.cpp; path = POSIX/PlatformPOSIX.cpp; sourceTree = "<group>"; };
945759661534941F005A9070 /* PlatformPOSIX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlatformPOSIX.h; path = POSIX/PlatformPOSIX.h; sourceTree = "<group>"; };
+ AF66324E216EB9C300BB510D /* PlatformRemoteAppleBridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteAppleBridge.cpp; sourceTree = "<group>"; };
+ AF66324F216EB9C300BB510D /* PlatformRemoteAppleBridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteAppleBridge.h; sourceTree = "<group>"; };
AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteAppleTV.cpp; sourceTree = "<group>"; };
AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformRemoteAppleTV.h; sourceTree = "<group>"; };
AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformRemoteAppleWatch.cpp; sourceTree = "<group>"; };
@@ -2420,7 +2470,6 @@
26BC7D7010F1B77400F91463 /* PluginInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PluginInterface.h; path = include/lldb/Core/PluginInterface.h; sourceTree = "<group>"; };
26BC7E8A10F1B85900F91463 /* PluginManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PluginManager.cpp; path = source/Core/PluginManager.cpp; sourceTree = "<group>"; };
26BC7D7110F1B77400F91463 /* PluginManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PluginManager.h; path = include/lldb/Core/PluginManager.h; sourceTree = "<group>"; };
- 26BC7DD610F1B7D500F91463 /* Predicate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Predicate.h; path = include/lldb/Host/Predicate.h; sourceTree = "<group>"; };
26BC7F3610F1B90C00F91463 /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Process.cpp; path = source/Target/Process.cpp; sourceTree = "<group>"; };
26BC7DF310F1B81A00F91463 /* Process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Process.h; path = include/lldb/Target/Process.h; sourceTree = "<group>"; };
26BC17A218C7F4CB00D2196D /* ProcessElfCore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessElfCore.cpp; sourceTree = "<group>"; };
@@ -2474,8 +2523,6 @@
4939EA8C1BD56B6D00084382 /* REPL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = REPL.cpp; path = source/Expression/REPL.cpp; sourceTree = "<group>"; };
4939EA8B1BD56B3700084382 /* REPL.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = REPL.h; path = include/lldb/Expression/REPL.h; sourceTree = "<group>"; };
9A2057451F3B905C00F6C293 /* RNBSocketTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RNBSocketTest.cpp; path = debugserver/RNBSocketTest.cpp; sourceTree = "<group>"; };
- 94BA8B6C176F8C9B005A91B5 /* Range.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Range.cpp; path = source/Utility/Range.cpp; sourceTree = "<group>"; };
- 94BA8B6E176F8CA0005A91B5 /* Range.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Range.h; path = include/lldb/Utility/Range.h; sourceTree = "<group>"; };
2626B6AD143E1BEA00EF935C /* RangeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RangeMap.h; path = include/lldb/Core/RangeMap.h; sourceTree = "<group>"; };
26AB54111832DC3400EADFF3 /* RegisterCheckpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterCheckpoint.h; path = include/lldb/Target/RegisterCheckpoint.h; sourceTree = "<group>"; };
26BC7F3710F1B90C00F91463 /* RegisterContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContext.cpp; path = source/Target/RegisterContext.cpp; sourceTree = "<group>"; };
@@ -2533,6 +2580,10 @@
26474CC218D0CB5B0073DEBA /* RegisterContextMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextMemory.cpp; path = Utility/RegisterContextMemory.cpp; sourceTree = "<group>"; };
262D24E513FB8710002D1960 /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = "<group>"; };
26474CC318D0CB5B0073DEBA /* RegisterContextMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextMemory.h; path = Utility/RegisterContextMemory.h; sourceTree = "<group>"; };
+ 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_ARM.cpp; sourceTree = "<group>"; };
+ 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_ARM.h; sourceTree = "<group>"; };
+ 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_ARM64.cpp; sourceTree = "<group>"; };
+ 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_ARM64.h; sourceTree = "<group>"; };
947CF7741DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_32.cpp; sourceTree = "<group>"; };
947CF7721DC7B20300EF980B /* RegisterContextMinidump_x86_32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RegisterContextMinidump_x86_32.h; sourceTree = "<group>"; };
AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterContextMinidump_x86_64.cpp; sourceTree = "<group>"; };
@@ -2607,8 +2658,8 @@
2654A6841E54D5EE00DA1013 /* RegisterNumber.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterNumber.h; path = include/lldb/Target/RegisterNumber.h; sourceTree = "<group>"; };
4CA9D13C1FCE07AF00300E18 /* RegisterUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterUtilities.cpp; sourceTree = "<group>"; };
4CA9D13D1FCE07AF00300E18 /* RegisterUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterUtilities.h; sourceTree = "<group>"; };
- 26C6886E137880C400407EDF /* RegisterValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterValue.cpp; path = source/Core/RegisterValue.cpp; sourceTree = "<group>"; };
- 26C6886D137880B900407EDF /* RegisterValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterValue.h; path = include/lldb/Core/RegisterValue.h; sourceTree = "<group>"; };
+ 26C6886E137880C400407EDF /* RegisterValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterValue.cpp; path = source/Utility/RegisterValue.cpp; sourceTree = "<group>"; };
+ 26C6886D137880B900407EDF /* RegisterValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterValue.h; path = include/lldb/Utility/RegisterValue.h; sourceTree = "<group>"; };
26764C9F1E48F528008D3573 /* RegularExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegularExpression.cpp; path = source/Utility/RegularExpression.cpp; sourceTree = "<group>"; };
26764C9C1E48F516008D3573 /* RegularExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegularExpression.h; path = include/lldb/Utility/RegularExpression.h; sourceTree = "<group>"; };
23D065821D4A7BDA0008EDE6 /* RenderScriptExpressionOpts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderScriptExpressionOpts.cpp; sourceTree = "<group>"; };
@@ -2619,6 +2670,10 @@
948554581DCBAE3200345FF5 /* RenderScriptScriptGroup.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RenderScriptScriptGroup.h; sourceTree = "<group>"; };
23D065861D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderScriptx86ABIFixups.cpp; sourceTree = "<group>"; };
23D065871D4A7BDA0008EDE6 /* RenderScriptx86ABIFixups.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderScriptx86ABIFixups.h; sourceTree = "<group>"; };
+ AFCB1D5E219CD5EA00730AD5 /* Reproducer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Reproducer.cpp; path = source/Utility/Reproducer.cpp; sourceTree = "<group>"; };
+ 4FBC04EC211A06200015A814 /* RichManglingContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RichManglingContext.cpp; path = source/Core/RichManglingContext.cpp; sourceTree = "<group>"; };
+ 4FBC04EE211A06820015A814 /* RichManglingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RichManglingContext.h; path = include/lldb/Core/RichManglingContext.h; sourceTree = "<group>"; };
+ 4FBC04F3211A0F0F0015A814 /* RichManglingContextTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = RichManglingContextTest.cpp; sourceTree = "<group>"; };
26DE204411618ADA00A093E2 /* SBAddress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBAddress.cpp; path = source/API/SBAddress.cpp; sourceTree = "<group>"; };
26DE204211618ACA00A093E2 /* SBAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBAddress.h; path = include/lldb/API/SBAddress.h; sourceTree = "<group>"; };
2611FEEF142D83060017FEA3 /* SBAddress.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBAddress.i; sourceTree = "<group>"; };
@@ -2691,6 +2746,8 @@
9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBHostOS.cpp; path = source/API/SBHostOS.cpp; sourceTree = "<group>"; };
9A3576A7116E9AB700E8ED2F /* SBHostOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBHostOS.h; path = include/lldb/API/SBHostOS.h; sourceTree = "<group>"; };
2611FF00142D83060017FEA3 /* SBHostOS.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBHostOS.i; sourceTree = "<group>"; };
+ AFB2F2F421B71AE90078DEF1 /* SBInitializerOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBInitializerOptions.cpp; path = source/API/SBInitializerOptions.cpp; sourceTree = "<group>"; };
+ 4C38996C21BA11CA002BAEF4 /* SBInitializerOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBInitializerOptions.h; path = include/lldb/API/SBInitializerOptions.h; sourceTree = "<group>"; };
9AC703AE117675410086C050 /* SBInstruction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBInstruction.cpp; path = source/API/SBInstruction.cpp; sourceTree = "<group>"; };
9AC7038D117674EB0086C050 /* SBInstruction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBInstruction.h; path = include/lldb/API/SBInstruction.h; sourceTree = "<group>"; };
2611FF02142D83060017FEA3 /* SBInstruction.i */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c.preprocessed; path = SBInstruction.i; sourceTree = "<group>"; };
@@ -2816,9 +2873,8 @@
B2A58721143119810092BFBA /* SBWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBWatchpoint.h; path = include/lldb/API/SBWatchpoint.h; sourceTree = "<group>"; };
B2A5872514313B480092BFBA /* SBWatchpoint.i */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; path = SBWatchpoint.i; sourceTree = "<group>"; };
26BC7D7810F1B77400F91463 /* STLUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STLUtils.h; path = include/lldb/Core/STLUtils.h; sourceTree = "<group>"; };
- 4CAB257C18EC9DB800BAD33E /* SafeMachO.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SafeMachO.h; path = include/lldb/Utility/SafeMachO.h; sourceTree = "<group>"; };
- 26BC7E8D10F1B85900F91463 /* Scalar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Scalar.cpp; path = source/Core/Scalar.cpp; sourceTree = "<group>"; };
- 26BC7D7410F1B77400F91463 /* Scalar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scalar.h; path = include/lldb/Core/Scalar.h; sourceTree = "<group>"; };
+ 26BC7E8D10F1B85900F91463 /* Scalar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Scalar.cpp; path = source/Utility/Scalar.cpp; sourceTree = "<group>"; };
+ 26BC7D7410F1B77400F91463 /* Scalar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Scalar.h; path = include/lldb/Utility/Scalar.h; sourceTree = "<group>"; };
23CB14E91D66CC0E00EDDDE1 /* ScalarTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScalarTest.cpp; sourceTree = "<group>"; };
9A82010B10FFB49800182560 /* ScriptInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScriptInterpreter.cpp; path = source/Interpreter/ScriptInterpreter.cpp; sourceTree = "<group>"; };
26BC7DE510F1B7F900F91463 /* ScriptInterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ScriptInterpreter.h; path = include/lldb/Interpreter/ScriptInterpreter.h; sourceTree = "<group>"; };
@@ -2846,18 +2902,21 @@
26D7E45B13D5E2F9007FD12B /* SocketAddress.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SocketAddress.h; path = include/lldb/Host/SocketAddress.h; sourceTree = "<group>"; };
2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SocketAddressTest.cpp; sourceTree = "<group>"; };
2321F93A1BDD332400BA9A93 /* SocketTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SocketTest.cpp; sourceTree = "<group>"; };
- 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Host/common/SoftwareBreakpoint.cpp; sourceTree = "<group>"; };
- 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = include/lldb/Host/common/SoftwareBreakpoint.h; sourceTree = "<group>"; };
+ 26603870211CA90D00329572 /* SourceBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SourceBreakpoint.cpp; path = "tools/lldb-vscode/SourceBreakpoint.cpp"; sourceTree = "<group>"; };
+ 2660386D211CA90C00329572 /* SourceBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceBreakpoint.h; path = "tools/lldb-vscode/SourceBreakpoint.h"; sourceTree = "<group>"; };
26BC7E8F10F1B85900F91463 /* SourceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SourceManager.cpp; path = source/Core/SourceManager.cpp; sourceTree = "<group>"; };
26BC7D7610F1B77400F91463 /* SourceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceManager.h; path = include/lldb/Core/SourceManager.h; sourceTree = "<group>"; };
+ 26F76198211CB8870044F6EA /* SourceReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceReference.h; path = "tools/lldb-vscode/SourceReference.h"; sourceTree = "<group>"; };
26BC7F3810F1B90C00F91463 /* StackFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrame.cpp; path = source/Target/StackFrame.cpp; sourceTree = "<group>"; };
26BC7DF510F1B81A00F91463 /* StackFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackFrame.h; path = include/lldb/Target/StackFrame.h; sourceTree = "<group>"; };
26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrameList.cpp; path = source/Target/StackFrameList.cpp; sourceTree = "<group>"; };
26BC7DF610F1B81A00F91463 /* StackFrameList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackFrameList.h; path = include/lldb/Target/StackFrameList.h; sourceTree = "<group>"; };
+ 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = StackFrameRecognizer.cpp; path = source/Target/StackFrameRecognizer.cpp; sourceTree = "<group>"; };
+ 8CFDB67920467B390052B399 /* StackFrameRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StackFrameRecognizer.h; path = include/lldb/Target/StackFrameRecognizer.h; sourceTree = "<group>"; };
26BC7F3A10F1B90C00F91463 /* StackID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StackID.cpp; path = source/Target/StackID.cpp; sourceTree = "<group>"; };
26BC7DF710F1B81A00F91463 /* StackID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StackID.h; path = include/lldb/Target/StackID.h; sourceTree = "<group>"; };
- 26BC7E9010F1B85900F91463 /* State.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = State.cpp; path = source/Core/State.cpp; sourceTree = "<group>"; };
- 26BC7D7710F1B77400F91463 /* State.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = State.h; path = include/lldb/Core/State.h; sourceTree = "<group>"; };
+ 26BC7E9010F1B85900F91463 /* State.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = State.cpp; path = source/Utility/State.cpp; sourceTree = "<group>"; };
+ 26BC7D7710F1B77400F91463 /* State.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = State.h; path = include/lldb/Utility/State.h; sourceTree = "<group>"; };
9A3D43E21F3237D500EB767C /* StateTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StateTest.cpp; sourceTree = "<group>"; };
492DB7E81EC662D100B9E9AF /* Status.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Status.cpp; path = source/Utility/Status.cpp; sourceTree = "<group>"; };
492DB7E61EC662B100B9E9AF /* Status.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Status.h; path = include/lldb/Utility/Status.h; sourceTree = "<group>"; };
@@ -2893,7 +2952,7 @@
2660D9F611922A1300958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = source/Utility/StringExtractor.cpp; sourceTree = "<group>"; };
26A375831D59486000D6CBDB /* StringExtractor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringExtractor.h; path = include/lldb/Utility/StringExtractor.h; sourceTree = "<group>"; };
2676A093119C93C8008A98EF /* StringExtractorGDBRemote.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractorGDBRemote.cpp; path = source/Utility/StringExtractorGDBRemote.cpp; sourceTree = "<group>"; };
- 2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractorGDBRemote.h; path = source/Utility/StringExtractorGDBRemote.h; sourceTree = "<group>"; };
+ 2676A094119C93C8008A98EF /* StringExtractorGDBRemote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractorGDBRemote.h; path = include/lldb/Utility/StringExtractorGDBRemote.h; sourceTree = "<group>"; };
2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringExtractorTest.cpp; sourceTree = "<group>"; };
94380B8119940B0A00BFE4A8 /* StringLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringLexer.cpp; path = source/Utility/StringLexer.cpp; sourceTree = "<group>"; };
94380B8019940B0300BFE4A8 /* StringLexer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = StringLexer.h; path = include/lldb/Utility/StringLexer.h; sourceTree = "<group>"; };
@@ -2917,6 +2976,8 @@
26BC7C6110F1B6E900F91463 /* SymbolContextScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolContextScope.h; path = include/lldb/Symbol/SymbolContextScope.h; sourceTree = "<group>"; };
26BC7F1D10F1B8EC00F91463 /* SymbolFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFile.cpp; path = source/Symbol/SymbolFile.cpp; sourceTree = "<group>"; };
26BC7C6210F1B6E900F91463 /* SymbolFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolFile.h; path = include/lldb/Symbol/SymbolFile.h; sourceTree = "<group>"; };
+ AF97744621E9947B006876A7 /* SymbolFileBreakpad.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFileBreakpad.cpp; path = source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp; sourceTree = SOURCE_ROOT; };
+ AF97744521E9947B006876A7 /* SymbolFileBreakpad.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SymbolFileBreakpad.h; path = source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h; sourceTree = SOURCE_ROOT; };
260C89D910F57C5600BB2B04 /* SymbolFileDWARF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARF.cpp; sourceTree = "<group>"; };
260C89DA10F57C5600BB2B04 /* SymbolFileDWARF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARF.h; sourceTree = "<group>"; };
260C89DB10F57C5600BB2B04 /* SymbolFileDWARFDebugMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARFDebugMap.cpp; sourceTree = "<group>"; };
@@ -2928,6 +2989,8 @@
4C7D481C1F509963005314B4 /* SymbolFileDWARFDwp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFileDWARFDwp.cpp; sourceTree = "<group>"; };
4C7D481E1F509964005314B4 /* SymbolFileDWARFDwp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SymbolFileDWARFDwp.h; sourceTree = "<group>"; };
9A20570A1F3B81F300F6C293 /* SymbolFileDWARFTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFileDWARFTests.cpp; path = DWARF/SymbolFileDWARFTests.cpp; sourceTree = "<group>"; };
+ AFD966B7217140B6006714AC /* SymbolFileNativePDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFileNativePDB.cpp; path = source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp; sourceTree = SOURCE_ROOT; };
+ AFD966C0217140C8006714AC /* SymbolFileNativePDB.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SymbolFileNativePDB.h; path = source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h; sourceTree = SOURCE_ROOT; };
AF6335E01C87B21E00F7D554 /* SymbolFilePDB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SymbolFilePDB.cpp; path = PDB/SymbolFilePDB.cpp; sourceTree = "<group>"; };
AF6335E11C87B21E00F7D554 /* SymbolFilePDB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SymbolFilePDB.h; path = PDB/SymbolFilePDB.h; sourceTree = "<group>"; };
23CB15141D66CF8700EDDDE1 /* SymbolFilePDBTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SymbolFilePDBTests.cpp; sourceTree = "<group>"; };
@@ -2973,6 +3036,7 @@
268DA873130095ED00C9483A /* Terminal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Terminal.cpp; sourceTree = "<group>"; };
268DA871130095D000C9483A /* Terminal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Terminal.h; path = include/lldb/Host/Terminal.h; sourceTree = "<group>"; };
4CEC86A3204738C5009B37B1 /* TestArm64InstEmulation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestArm64InstEmulation.cpp; path = UnwindAssembly/ARM64/TestArm64InstEmulation.cpp; sourceTree = "<group>"; };
+ AF7F97662141FA3800795BC0 /* TestArmv7Disassembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TestArmv7Disassembly.cpp; path = unittests/Disassembler/TestArmv7Disassembly.cpp; sourceTree = SOURCE_ROOT; };
23CB150C1D66CF5600EDDDE1 /* TestClangASTContext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestClangASTContext.cpp; sourceTree = "<group>"; };
9A20572B1F3B8E6200F6C293 /* TestCompletion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestCompletion.cpp; sourceTree = "<group>"; };
9A2057131F3B860D00F6C293 /* TestDWARFCallFrameInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TestDWARFCallFrameInfo.cpp; sourceTree = "<group>"; };
@@ -3079,6 +3143,8 @@
2579065B1BD0488100178368 /* UDPSocket.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UDPSocket.cpp; sourceTree = "<group>"; };
49CA96EA1E6AAC6600C03FEE /* UUID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UUID.cpp; path = source/Utility/UUID.cpp; sourceTree = "<group>"; };
49CA96F51E6AAC8E00C03FEE /* UUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UUID.h; path = include/lldb/Utility/UUID.h; sourceTree = "<group>"; };
+ AF0578C2217FA80700CF9D80 /* UdtRecordCompleter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UdtRecordCompleter.cpp; path = source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp; sourceTree = SOURCE_ROOT; };
+ AF0578C1217FA80700CF9D80 /* UdtRecordCompleter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UdtRecordCompleter.h; path = source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h; sourceTree = SOURCE_ROOT; };
268A813F115B19D000F645B0 /* UniqueCStringMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UniqueCStringMap.h; path = include/lldb/Core/UniqueCStringMap.h; sourceTree = "<group>"; };
26B8B42312EEC52A00A831B2 /* UniqueDWARFASTType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UniqueDWARFASTType.cpp; sourceTree = "<group>"; };
26B8B42212EEC52A00A831B2 /* UniqueDWARFASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniqueDWARFASTType.h; sourceTree = "<group>"; };
@@ -3116,6 +3182,9 @@
9A3D43C41F3150D200EB767C /* VASprintfTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VASprintfTest.cpp; sourceTree = "<group>"; };
AFC2DCEF1E6E2FD200283714 /* VMRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VMRange.cpp; path = source/Utility/VMRange.cpp; sourceTree = "<group>"; };
AFC2DCF11E6E2FDA00283714 /* VMRange.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = VMRange.h; path = include/lldb/Utility/VMRange.h; sourceTree = "<group>"; };
+ 2660386E211CA90D00329572 /* VSCode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VSCode.cpp; path = "tools/lldb-vscode/VSCode.cpp"; sourceTree = "<group>"; };
+ 2660386F211CA90D00329572 /* VSCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VSCode.h; path = "tools/lldb-vscode/VSCode.h"; sourceTree = "<group>"; };
+ 26F7619C211CDD700044F6EA /* VSCodeForward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VSCodeForward.h; path = "tools/lldb-vscode/VSCodeForward.h"; sourceTree = "<group>"; };
26BC7E9910F1B85900F91463 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = source/Core/Value.cpp; sourceTree = "<group>"; };
26BC7D8110F1B77400F91463 /* Value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Value.h; path = include/lldb/Core/Value.h; sourceTree = "<group>"; };
26BC7E9A10F1B85900F91463 /* ValueObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObject.cpp; path = source/Core/ValueObject.cpp; sourceTree = "<group>"; };
@@ -3198,6 +3267,7 @@
2326CF471BDD67C100A5CEAC /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = ../../../../../../usr/lib/libncurses.dylib; sourceTree = "<group>"; };
239481851C59EBDD00DF7168 /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = ../../../../../usr/lib/libncurses.dylib; sourceTree = "<group>"; };
2670F8111862B44A006B332C /* libncurses.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libncurses.dylib; path = /usr/lib/libncurses.dylib; sourceTree = "<absolute>"; };
+ 26792621211CA41E00EE1D10 /* libncurses.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libncurses.tbd; path = usr/lib/libncurses.tbd; sourceTree = SDKROOT; };
26F5C37410F3F61B009D5894 /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = "<absolute>"; };
2326CF4E1BDD687800A5CEAC /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = ../../../../../../usr/lib/libpanel.dylib; sourceTree = "<group>"; };
260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = "<absolute>"; };
@@ -3231,11 +3301,15 @@
E769331D1A94D18100C73337 /* lldb-server.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-server.cpp"; path = "tools/lldb-server/lldb-server.cpp"; sourceTree = "<group>"; };
26BC7C2910F1B3BC00F91463 /* lldb-types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-types.h"; path = "include/lldb/lldb-types.h"; sourceTree = "<group>"; };
94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = "<group>"; };
+ 2679260C211CA3AC00EE1D10 /* lldb-vscode */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "lldb-vscode"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 26792618211CA3E100EE1D10 /* lldb-vscode-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "lldb-vscode-Info.plist"; path = "tools/lldb-vscode/lldb-vscode-Info.plist"; sourceTree = "<group>"; };
+ 26792619211CA3E100EE1D10 /* lldb-vscode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "lldb-vscode.cpp"; path = "tools/lldb-vscode/lldb-vscode.cpp"; sourceTree = "<group>"; };
23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-x86-register-enums.h"; path = "Utility/lldb-x86-register-enums.h"; sourceTree = "<group>"; };
AF90106315AB7C5700FF120D /* lldb.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = lldb.1; path = docs/lldb.1; sourceTree = "<group>"; };
26BC7E7410F1B85900F91463 /* lldb.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lldb.cpp; path = source/lldb.cpp; sourceTree = "<group>"; };
2669605E1199F4230075C61A /* lldb.swig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lldb.swig; sourceTree = "<group>"; };
94E367CC140C4EC4001C7A5A /* modify-python-lldb.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = "modify-python-lldb.py"; sourceTree = "<group>"; };
+ 26792616211CA3E100EE1D10 /* package.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = package.json; path = "tools/lldb-vscode/package.json"; sourceTree = "<group>"; };
9A48A3A7124AAA5A00922451 /* python-extensions.swig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "python-extensions.swig"; sourceTree = "<group>"; };
944DC3481774C99000D7D884 /* python-swigsafecast.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-swigsafecast.swig"; sourceTree = "<group>"; };
94E367CE140C4EEA001C7A5A /* python-typemaps.swig */ = {isa = PBXFileReference; lastKnownFileType = text; path = "python-typemaps.swig"; sourceTree = "<group>"; };
@@ -3303,6 +3377,15 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 26792609211CA3AC00EE1D10 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 26792623211CA42300EE1D10 /* LLDB.framework in Frameworks */,
+ 26792622211CA41E00EE1D10 /* libncurses.tbd in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
2689FFC713353D7A00698AC0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -3418,6 +3501,7 @@
942829C01A89835300521B30 /* lldb-argdumper */,
239504D41BDD451400963CEA /* lldb-gtest */,
23CB15561D66DA9300EDDDE1 /* lldb-gtest */,
+ 2679260C211CA3AC00EE1D10 /* lldb-vscode */,
);
name = Products;
sourceTree = "<group>";
@@ -3439,6 +3523,7 @@
23E2E52C1D903806006F38BB /* Breakpoint */,
23CB14E51D66CBEB00EDDDE1 /* Core */,
9A2057421F3B904C00F6C293 /* debugserver */,
+ AF7F97652141FA2100795BC0 /* Disassembler */,
2326CF501BDD68CA00A5CEAC /* Editline */,
AEC6FF9D1BE97035007882C1 /* Expression */,
239504C21BDD3FD600963CEA /* gtest_common.h */,
@@ -3498,24 +3583,29 @@
2321F9421BDD343A00BA9A93 /* Utility */ = {
isa = PBXGroup;
children = (
- 58EAC73D2106A0740029571E /* StreamTeeTest.cpp */,
+ 23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */,
7F94D7172040A13A006EE3EA /* CleanUpTest.cpp */,
23E2E5161D903689006F38BB /* ArchSpecTest.cpp */,
9A3D43C81F3150D200EB767C /* ConstStringTest.cpp */,
+ AFA1B62B219E0ED900A8AB7E /* DataExtractorTest.cpp */,
23CB14FD1D66CD2400EDDDE1 /* FileSpecTest.cpp */,
+ 8C3BD99F1EF5D1B50016C343 /* JSONTest.cpp */,
+ 9A3D43E31F3237D500EB767C /* ListenerTest.cpp */,
9A3D43C71F3150D200EB767C /* LogTest.cpp */,
9A3D43CB1F3150D200EB767C /* NameMatchesTest.cpp */,
+ 23CB14E91D66CC0E00EDDDE1 /* ScalarTest.cpp */,
+ 9A3D43E21F3237D500EB767C /* StateTest.cpp */,
9A3D43C61F3150D200EB767C /* StatusTest.cpp */,
+ 58EAC73D2106A0740029571E /* StreamTeeTest.cpp */,
+ 2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */,
9A3D43CA1F3150D200EB767C /* StructuredDataTest.cpp */,
9A3D43C91F3150D200EB767C /* TildeExpressionResolverTest.cpp */,
9A3D43CC1F3150D200EB767C /* TimeoutTest.cpp */,
9A3D43C51F3150D200EB767C /* TimerTest.cpp */,
+ 2321F9461BDD346100BA9A93 /* UriParserTest.cpp */,
9A3D43C41F3150D200EB767C /* VASprintfTest.cpp */,
2321F9431BDD346100BA9A93 /* CMakeLists.txt */,
23CB15041D66CD9200EDDDE1 /* Inputs */,
- 2321F9441BDD346100BA9A93 /* StringExtractorTest.cpp */,
- 8C3BD99F1EF5D1B50016C343 /* JSONTest.cpp */,
- 2321F9461BDD346100BA9A93 /* UriParserTest.cpp */,
);
path = Utility;
sourceTree = "<group>";
@@ -3651,6 +3741,7 @@
23CB14E21D66CA2200EDDDE1 /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 26792621211CA41E00EE1D10 /* libncurses.tbd */,
23CB14E31D66CA2200EDDDE1 /* libxml2.2.dylib */,
);
name = Frameworks;
@@ -3659,14 +3750,11 @@
23CB14E51D66CBEB00EDDDE1 /* Core */ = {
isa = PBXGroup;
children = (
+ 23CB14E71D66CC0E00EDDDE1 /* CMakeLists.txt */,
+ 58A080B12112AB2200D5580F /* HighlighterTest.cpp */,
4F29D3CD21010F84003B549A /* MangledTest.cpp */,
- 9A3D43E31F3237D500EB767C /* ListenerTest.cpp */,
- 9A3D43E21F3237D500EB767C /* StateTest.cpp */,
+ 4FBC04F3211A0F0F0015A814 /* RichManglingContextTest.cpp */,
9A3D43E11F3237D500EB767C /* StreamCallbackTest.cpp */,
- 23CB14E71D66CC0E00EDDDE1 /* CMakeLists.txt */,
- 23CB14E61D66CC0E00EDDDE1 /* BroadcasterTest.cpp */,
- 23CB14E81D66CC0E00EDDDE1 /* DataExtractorTest.cpp */,
- 23CB14E91D66CC0E00EDDDE1 /* ScalarTest.cpp */,
);
path = Core;
sourceTree = "<group>";
@@ -3777,6 +3865,10 @@
23E2E5351D9048E7006F38BB /* minidump */ = {
isa = PBXGroup;
children = (
+ 2619C4812107A9A1009CDE81 /* RegisterContextMinidump_ARM.cpp */,
+ 2619C4832107A9A2009CDE81 /* RegisterContextMinidump_ARM.h */,
+ 2619C4802107A9A1009CDE81 /* RegisterContextMinidump_ARM64.cpp */,
+ 2619C4822107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h */,
AFD65C7F1D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.cpp */,
AFD65C801D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h */,
23E2E5361D9048FB006F38BB /* CMakeLists.txt */,
@@ -3888,6 +3980,7 @@
260C898210F57C5600BB2B04 /* ObjectFile */ = {
isa = PBXGroup;
children = (
+ 4C9BF11621C0467700FA4036 /* Breakpad */,
260C898310F57C5600BB2B04 /* ELF */,
26EFC4C718CFAF0D00865D87 /* JIT */,
260C898710F57C5600BB2B04 /* Mach-O */,
@@ -3934,6 +4027,8 @@
260C89B110F57C5600BB2B04 /* SymbolFile */ = {
isa = PBXGroup;
children = (
+ AF97744421E99467006876A7 /* Breakpad */,
+ AFD966B321714099006714AC /* NativePDB */,
AF6335DF1C87B20A00F7D554 /* PDB */,
260C89B210F57C5600BB2B04 /* DWARF */,
260C89DD10F57C5600BB2B04 /* Symtab */,
@@ -3958,12 +4053,6 @@
269DDD451B8FD01A00D0DBD8 /* DWARFASTParser.h */,
269DDD491B8FD1C300D0DBD8 /* DWARFASTParserClang.h */,
269DDD481B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp */,
- AE6897271B94F6DE0018845D /* DWARFASTParserGo.h */,
- AE6897261B94F6DE0018845D /* DWARFASTParserGo.cpp */,
- 6D0F61441C80AACF00A4ECEE /* DWARFASTParserJava.cpp */,
- 6D0F61451C80AACF00A4ECEE /* DWARFASTParserJava.h */,
- 4CC7C6511D5299140076FF94 /* DWARFASTParserOCaml.h */,
- 4CC7C6521D5299140076FF94 /* DWARFASTParserOCaml.cpp */,
260C89B610F57C5600BB2B04 /* DWARFAttribute.h */,
266E829C1B8E542C008FCA06 /* DWARFAttribute.cpp */,
4CD44D4020B777850003557C /* DWARFBaseDIE.cpp */,
@@ -4194,6 +4283,8 @@
26DE205C1161901400A093E2 /* SBFunction.cpp */,
9A3576A7116E9AB700E8ED2F /* SBHostOS.h */,
9A3576A9116E9AC700E8ED2F /* SBHostOS.cpp */,
+ AFB2F2F421B71AE90078DEF1 /* SBInitializerOptions.cpp */,
+ 4C38996C21BA11CA002BAEF4 /* SBInitializerOptions.h */,
9AC7038D117674EB0086C050 /* SBInstruction.h */,
9AC703AE117675410086C050 /* SBInstruction.cpp */,
9AC7038F117675270086C050 /* SBInstructionList.h */,
@@ -4325,6 +4416,16 @@
path = "MacOSX-Kernel";
sourceTree = "<group>";
};
+ 2647B62E21C4364F00A81D15 /* MIPS */ = {
+ isa = PBXGroup;
+ children = (
+ 2647B63021C4366300A81D15 /* ArchitectureMips.cpp */,
+ 2647B62F21C4366200A81D15 /* ArchitectureMips.h */,
+ );
+ name = MIPS;
+ path = "New Group";
+ sourceTree = "<group>";
+ };
264A12F91372522000875C42 /* ARM64 */ = {
isa = PBXGroup;
children = (
@@ -4438,12 +4539,38 @@
266DFE9013FD64D200D0C574 /* OperatingSystem */ = {
isa = PBXGroup;
children = (
- AE8F624519EF3DFC00326B21 /* Go */,
2698699715E6CBD0002415FF /* Python */,
);
path = OperatingSystem;
sourceTree = "<group>";
};
+ 26792615211CA3C100EE1D10 /* lldb-vscode */ = {
+ isa = PBXGroup;
+ children = (
+ 26792617211CA3E100EE1D10 /* CMakeLists.txt */,
+ 26792618211CA3E100EE1D10 /* lldb-vscode-Info.plist */,
+ 26792619211CA3E100EE1D10 /* lldb-vscode.cpp */,
+ 26792616211CA3E100EE1D10 /* package.json */,
+ 2660387D211CA98200329572 /* BreakpointBase.cpp */,
+ 26603872211CA90D00329572 /* BreakpointBase.h */,
+ 26603874211CA90E00329572 /* ExceptionBreakpoint.cpp */,
+ 26603873211CA90E00329572 /* ExceptionBreakpoint.h */,
+ 26603877211CA90E00329572 /* FunctionBreakpoint.cpp */,
+ 26603871211CA90D00329572 /* FunctionBreakpoint.h */,
+ 26603875211CA90E00329572 /* JSONUtils.cpp */,
+ 26603876211CA90E00329572 /* JSONUtils.h */,
+ 26F76199211CBBB30044F6EA /* LLDBUtils.cpp */,
+ 26F7619A211CBBB30044F6EA /* LLDBUtils.h */,
+ 26603870211CA90D00329572 /* SourceBreakpoint.cpp */,
+ 2660386D211CA90C00329572 /* SourceBreakpoint.h */,
+ 26F76198211CB8870044F6EA /* SourceReference.h */,
+ 2660386E211CA90D00329572 /* VSCode.cpp */,
+ 2660386F211CA90D00329572 /* VSCode.h */,
+ 26F7619C211CDD700044F6EA /* VSCodeForward.h */,
+ );
+ name = "lldb-vscode";
+ sourceTree = "<group>";
+ };
267F68461CC02DED0086832B /* SysV-s390x */ = {
isa = PBXGroup;
children = (
@@ -4471,6 +4598,8 @@
264A12FF137252C700875C42 /* ARM64_DWARF_Registers.h */,
AFC2DCE81E6E2F2C00283714 /* Baton.cpp */,
AFC2DCEE1E6E2FA300283714 /* Baton.h */,
+ 2647B63521C4368300A81D15 /* Broadcaster.h */,
+ 2647B63921C436AB00A81D15 /* Broadcaster.cpp */,
264723A511FA076E00DE380C /* CleanUp.h */,
26764C951E48F46F008D3573 /* ConstString.h */,
26764C961E48F482008D3573 /* ConstString.cpp */,
@@ -4483,28 +4612,35 @@
49CA96E81E6AAC6600C03FEE /* DataEncoder.cpp */,
49CA96F41E6AAC8E00C03FEE /* DataExtractor.h */,
49CA96E91E6AAC6600C03FEE /* DataExtractor.cpp */,
- 9481FE6B1B5F2D9200DED357 /* Either.h */,
26BC7DD310F1B7D500F91463 /* Endian.h */,
- AFC2DCE61E6E2ED000283714 /* FastDemangle.cpp */,
- AFC2DCED1E6E2F9800283714 /* FastDemangle.h */,
+ 2647B63321C4367A00A81D15 /* Event.h */,
+ 2647B63B21C436B400A81D15 /* Event.cpp */,
4CBFF0471F579A36004AFA92 /* Flags.h */,
236124A61986B50E004EFC37 /* IOObject.h */,
236124A21986B4E2004EFC37 /* IOObject.cpp */,
4C73152119B7D71700F865A4 /* Iterable.h */,
942829541A89614000521B30 /* JSON.h */,
942829551A89614C00521B30 /* JSON.cpp */,
+ 2647B63721C4369500A81D15 /* Listener.h */,
+ 2647B63D21C436BC00A81D15 /* Listener.cpp */,
943BDEFC1AA7B2DE00789CE8 /* LLDBAssert.h */,
943BDEFD1AA7B2F800789CE8 /* LLDBAssert.cpp */,
3F81691C1ABA242B001DA9DF /* NameMatches.h */,
3F8169181ABA2419001DA9DF /* NameMatches.cpp */,
+ 26C6886D137880B900407EDF /* RegisterValue.h */,
+ 26C6886E137880C400407EDF /* RegisterValue.cpp */,
26764C9C1E48F516008D3573 /* RegularExpression.h */,
26764C9F1E48F528008D3573 /* RegularExpression.cpp */,
- 4CAB257C18EC9DB800BAD33E /* SafeMachO.h */,
+ AFCB1D5E219CD5EA00730AD5 /* Reproducer.cpp */,
+ 26BC7D7410F1B77400F91463 /* Scalar.h */,
+ 26BC7E8D10F1B85900F91463 /* Scalar.cpp */,
26A375841D59487700D6CBDB /* SelectHelper.h */,
26A3757F1D59462700D6CBDB /* SelectHelper.cpp */,
261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */,
4C2FAE2E135E3A70001EDE44 /* SharedCluster.h */,
261B5A5311C3F2AD00AABD0A /* SharingPtr.h */,
+ 26BC7D7710F1B77400F91463 /* State.h */,
+ 26BC7E9010F1B85900F91463 /* State.cpp */,
492DB7E61EC662B100B9E9AF /* Status.h */,
492DB7E81EC662D100B9E9AF /* Status.cpp */,
26764C9B1E48F50C008D3573 /* Stream.h */,
@@ -4526,8 +4662,6 @@
9A35765F116E76B900E8ED2F /* StringList.cpp */,
26F2F8FD1B156678007857DE /* StructuredData.h */,
AFEC3361194A8ABA00FF05C6 /* StructuredData.cpp */,
- 94BA8B6E176F8CA0005A91B5 /* Range.h */,
- 94BA8B6C176F8C9B005A91B5 /* Range.cpp */,
AFF8FF0B1E779D4B003830EF /* TildeExpressionResolver.cpp */,
AFF8FF0D1E779D51003830EF /* TildeExpressionResolver.h */,
26BC7D7E10F1B77400F91463 /* Timer.h */,
@@ -4560,7 +4694,6 @@
children = (
2669415B1A6DC2AB0063BE93 /* CMakeLists.txt */,
2669415E1A6DC2AB0063BE93 /* lldb-Info.plist */,
- 2669415F1A6DC2AB0063BE93 /* Makefile */,
266941601A6DC2AB0063BE93 /* MICmdArgContext.cpp */,
266941611A6DC2AB0063BE93 /* MICmdArgContext.h */,
266941621A6DC2AB0063BE93 /* MICmdArgSet.cpp */,
@@ -4821,6 +4954,8 @@
B28058A0139988B0002D96D0 /* InferiorCallPOSIX.cpp */,
B28058A2139988C6002D96D0 /* InferiorCallPOSIX.h */,
B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */,
+ 2647B64221C43BB000A81D15 /* LinuxProcMaps.cpp */,
+ 2647B64121C43BAF00A81D15 /* LinuxProcMaps.h */,
23059A0519532B96007B8189 /* LinuxSignals.cpp */,
23059A0619532B96007B8189 /* LinuxSignals.h */,
23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */,
@@ -4960,6 +5095,7 @@
26BC7C1010F1B34800F91463 /* Core */ = {
isa = PBXGroup;
children = (
+ 58A080A92112AA9400D5580F /* Highlighter.cpp */,
26BC7D5010F1B77400F91463 /* Address.h */,
26BC7E6910F1B85900F91463 /* Address.cpp */,
26BC7D5110F1B77400F91463 /* AddressRange.h */,
@@ -4970,8 +5106,6 @@
9AC7034211752C720086C050 /* AddressResolverFileLine.cpp */,
9AC7033F11752C590086C050 /* AddressResolverName.h */,
9AC7034411752C790086C050 /* AddressResolverName.cpp */,
- 26BC7D5410F1B77400F91463 /* Broadcaster.h */,
- 26BC7E6D10F1B85900F91463 /* Broadcaster.cpp */,
26BC7D5510F1B77400F91463 /* ClangForward.h */,
26BC7D5610F1B77400F91463 /* Communication.h */,
26BC7E6E10F1B85900F91463 /* Communication.cpp */,
@@ -4985,8 +5119,6 @@
26BC7D5F10F1B77400F91463 /* dwarf.h */,
26D9FDC612F784E60003F2EE /* EmulateInstruction.h */,
26D9FDC812F784FD0003F2EE /* EmulateInstruction.cpp */,
- 26BC7D6110F1B77400F91463 /* Event.h */,
- 26BC7E7910F1B85900F91463 /* Event.cpp */,
26BD407D135D2AC400237D80 /* FileLineResolver.h */,
26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */,
26BC7D6310F1B77400F91463 /* FileSpecList.h */,
@@ -4996,8 +5128,6 @@
260A63161861008E00FECF8E /* IOHandler.h */,
260A63181861009E00FECF8E /* IOHandler.cpp */,
26BC7D6510F1B77400F91463 /* IOStreamMacros.h */,
- 26BC7D6710F1B77400F91463 /* Listener.h */,
- 26BC7E7E10F1B85900F91463 /* Listener.cpp */,
26BC7D6810F1B77400F91463 /* Log.h */,
26BC7E7F10F1B85900F91463 /* Log.cpp */,
3F8160A71AB9F809001DA9DF /* Logging.h */,
@@ -5020,18 +5150,14 @@
26BC7D7110F1B77400F91463 /* PluginManager.h */,
26BC7E8A10F1B85900F91463 /* PluginManager.cpp */,
2626B6AD143E1BEA00EF935C /* RangeMap.h */,
- 26C6886D137880B900407EDF /* RegisterValue.h */,
- 26C6886E137880C400407EDF /* RegisterValue.cpp */,
- 26BC7D7410F1B77400F91463 /* Scalar.h */,
- 26BC7E8D10F1B85900F91463 /* Scalar.cpp */,
+ 4FBC04EE211A06820015A814 /* RichManglingContext.h */,
+ 4FBC04EC211A06200015A814 /* RichManglingContext.cpp */,
26BC7CF910F1B71400F91463 /* SearchFilter.h */,
26BC7E1510F1B83100F91463 /* SearchFilter.cpp */,
26BC7D7510F1B77400F91463 /* Section.h */,
26BC7E8E10F1B85900F91463 /* Section.cpp */,
26BC7D7610F1B77400F91463 /* SourceManager.h */,
26BC7E8F10F1B85900F91463 /* SourceManager.cpp */,
- 26BC7D7710F1B77400F91463 /* State.h */,
- 26BC7E9010F1B85900F91463 /* State.cpp */,
26BC7D7810F1B77400F91463 /* STLUtils.h */,
9A4F35111368A54100823F52 /* StreamAsynchronousIO.h */,
9A4F350F1368A51A00823F52 /* StreamAsynchronousIO.cpp */,
@@ -5083,9 +5209,7 @@
children = (
3032B1B91CAAA400004BE1AB /* ClangUtil.h */,
3032B1B61CAAA3D1004BE1AB /* ClangUtil.cpp */,
- 6D0F61411C80AAAA00A4ECEE /* JavaASTContext.cpp */,
6D0F613C1C80AA8900A4ECEE /* DebugMacros.h */,
- 6D0F613D1C80AA8900A4ECEE /* JavaASTContext.h */,
6D9AB3DE1BB2B76B003F2289 /* TypeMap.h */,
6D9AB3DC1BB2B74E003F2289 /* TypeMap.cpp */,
6D99A3621BBC2F3200979793 /* ArmUnwindInfo.cpp */,
@@ -5120,8 +5244,6 @@
26BC7F1810F1B8EC00F91463 /* Function.cpp */,
269FF07D12494F7D00225026 /* FuncUnwinders.h */,
961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */,
- AEEA340F1ACA08A000AB639D /* GoASTContext.h */,
- AEFFBA7C1AC4835D0087B932 /* GoASTContext.cpp */,
26BC7C5B10F1B6E900F91463 /* LineEntry.h */,
26BC7F1910F1B8EC00F91463 /* LineEntry.cpp */,
26BC7C5C10F1B6E900F91463 /* LineTable.h */,
@@ -5129,7 +5251,6 @@
26BC7C5D10F1B6E900F91463 /* ObjectContainer.h */,
26BC7C5E10F1B6E900F91463 /* ObjectFile.h */,
26BC7F4C10F1BC1A00F91463 /* ObjectFile.cpp */,
- 4CC7C6551D52996C0076FF94 /* OCamlASTContext.cpp */,
26BC7C5F10F1B6E900F91463 /* Symbol.h */,
26BC7F1B10F1B8EC00F91463 /* Symbol.cpp */,
26BC7C6010F1B6E900F91463 /* SymbolContext.h */,
@@ -5165,6 +5286,8 @@
26BC7CEB10F1B70800F91463 /* Breakpoint */ = {
isa = PBXGroup;
children = (
+ 4CCF9F6021430141006CC7EA /* BreakpointResolverScripted.h */,
+ 4CCF9F5E2143012F006CC7EA /* BreakpointResolverScripted.cpp */,
26BC7CEE10F1B71400F91463 /* Breakpoint.h */,
26BC7E0A10F1B83100F91463 /* Breakpoint.cpp */,
26BC7CEF10F1B71400F91463 /* BreakpointID.h */,
@@ -5252,6 +5375,8 @@
26BC7E3910F1B84700F91463 /* CommandObjectQuit.cpp */,
26BC7D2210F1B76300F91463 /* CommandObjectRegister.h */,
26BC7E3B10F1B84700F91463 /* CommandObjectRegister.cpp */,
+ AFCB1D5A219CD5A700730AD5 /* CommandObjectReproducer.cpp */,
+ AFCB1D5B219CD5A700730AD5 /* CommandObjectReproducer.h */,
26BC7D2410F1B76300F91463 /* CommandObjectScript.h */,
26BC7E3D10F1B84700F91463 /* CommandObjectScript.cpp */,
26BC7D2710F1B76300F91463 /* CommandObjectSettings.h */,
@@ -5341,10 +5466,7 @@
3FDFED2119BA6D55009756A7 /* HostNativeThreadBase.h */,
3FDFE57419AFABFD009756A7 /* HostProcess.h */,
3FDFE57519AFABFD009756A7 /* HostThread.h */,
- 267A47F31B14116E0021A5BC /* NativeBreakpoint.h */,
- 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */,
267A47F41B1411750021A5BC /* NativeBreakpointList.h */,
- 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */,
267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */,
232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */,
267A47F61B14118F0021A5BC /* NativeRegisterContext.h */,
@@ -5356,15 +5478,12 @@
A36FF33D17D8E98800244D40 /* OptionParser.h */,
260A39A519647A3A004B4130 /* Pipe.h */,
3F5E8AF31A40D4A500A73232 /* PipeBase.h */,
- 26BC7DD610F1B7D500F91463 /* Predicate.h */,
3FDFED2219BA6D55009756A7 /* ProcessRunLock.h */,
2654A68E1E552D2400DA1013 /* PseudoTerminal.h */,
2654A68C1E552D1500DA1013 /* PseudoTerminal.cpp */,
236124A71986B50E004EFC37 /* Socket.h */,
26D7E45B13D5E2F9007FD12B /* SocketAddress.h */,
26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */,
- 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */,
- 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */,
2689B0A4113EE3CD00A4AEDB /* Symbols.h */,
6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */,
6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */,
@@ -5545,6 +5664,8 @@
26BC7F3810F1B90C00F91463 /* StackFrame.cpp */,
26BC7DF610F1B81A00F91463 /* StackFrameList.h */,
26BC7F3910F1B90C00F91463 /* StackFrameList.cpp */,
+ 8CFDB67920467B390052B399 /* StackFrameRecognizer.h */,
+ 8CF46A6120522A9000423DDF /* StackFrameRecognizer.cpp */,
26BC7DF710F1B81A00F91463 /* StackID.h */,
26BC7F3A10F1B90C00F91463 /* StackID.cpp */,
2615DB841208A9C90021781D /* StopInfo.h */,
@@ -5690,6 +5811,8 @@
AF3A4AD11EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h */,
AF8AD6331BEC28C400150209 /* PlatformRemoteAppleTV.cpp */,
AF8AD6341BEC28C400150209 /* PlatformRemoteAppleTV.h */,
+ AF66324E216EB9C300BB510D /* PlatformRemoteAppleBridge.cpp */,
+ AF66324F216EB9C300BB510D /* PlatformRemoteAppleBridge.h */,
AF8AD6351BEC28C400150209 /* PlatformRemoteAppleWatch.cpp */,
AF8AD6361BEC28C400150209 /* PlatformRemoteAppleWatch.h */,
2675F6FE1332BE690067997B /* PlatformRemoteiOS.cpp */,
@@ -5819,6 +5942,7 @@
isa = PBXGroup;
children = (
E769331B1A94D10E00C73337 /* lldb-server */,
+ 26792615211CA3C100EE1D10 /* lldb-vscode */,
942829BA1A89830900521B30 /* argdumper */,
26579F55126A255E0007C5CB /* darwin-debug */,
265E9BE0115C2B8500D0DCCB /* debugserver */,
@@ -5832,6 +5956,8 @@
26F5C22510F3D956009D5894 /* Driver */ = {
isa = PBXGroup;
children = (
+ DD5F951B21ADE5F000B8265A /* Options.td */,
+ DD5F951A21ADE5BD00B8265A /* Options.inc */,
26F5C27210F3D9E4009D5894 /* lldb-Info.plist */,
26F5C27410F3D9E4009D5894 /* Driver.h */,
26F5C27310F3D9E4009D5894 /* Driver.cpp */,
@@ -6006,7 +6132,6 @@
isa = PBXGroup;
children = (
4984BA0C1B97620B008658D4 /* Clang */,
- AE44FB371BB35A2E0033EB62 /* Go */,
);
name = ExpressionParser;
sourceTree = "<group>";
@@ -6053,32 +6178,22 @@
children = (
4C14CEF72057258D00DEEF94 /* ArchitecturePPC64.h */,
4C14CEF82057258D00DEEF94 /* ArchitecturePPC64.cpp */,
- 4C14CEF92057258D00DEEF94 /* New Group */,
);
path = PPC64;
sourceTree = "<group>";
};
- 4C14CEF92057258D00DEEF94 /* New Group */ = {
+ 4C9BF11621C0467700FA4036 /* Breakpad */ = {
isa = PBXGroup;
children = (
+ 4C9BF11821C0467700FA4036 /* ObjectFileBreakpad.h */,
+ 4C9BF11921C0467700FA4036 /* ObjectFileBreakpad.cpp */,
);
- path = "New Group";
- sourceTree = "<group>";
- };
- 4CC7C64B1D5298AB0076FF94 /* OCaml */ = {
- isa = PBXGroup;
- children = (
- 4CC7C64C1D5298E20076FF94 /* OCamlLanguage.h */,
- 4CC7C64D1D5298E20076FF94 /* OCamlLanguage.cpp */,
- );
- name = OCaml;
+ path = Breakpad;
sourceTree = "<group>";
};
4CCA643A13B40B82003BDF98 /* LanguageRuntime */ = {
isa = PBXGroup;
children = (
- 6D0F61491C80AAF200A4ECEE /* Java */,
- AE44FB3B1BB485730033EB62 /* Go */,
49724D961AD6ECFA0033C538 /* RenderScript */,
4CCA643B13B40B82003BDF98 /* CPlusPlus */,
4CCA644013B40B82003BDF98 /* ObjC */,
@@ -6175,6 +6290,10 @@
2618EE5C1315B29C001D6D71 /* GDBRemoteCommunication.h */,
26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */,
26744EEE1338317700EF765A /* GDBRemoteCommunicationClient.h */,
+ AF8AD943219CD45700614785 /* GDBRemoteCommunicationHistory.cpp */,
+ AF8AD944219CD45700614785 /* GDBRemoteCommunicationHistory.h */,
+ AFCB1D57219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.cpp */,
+ AFCB1D56219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.h */,
26744EEF1338317700EF765A /* GDBRemoteCommunicationServer.cpp */,
26744EF01338317700EF765A /* GDBRemoteCommunicationServer.h */,
2618EE5D1315B29C001D6D71 /* GDBRemoteRegisterContext.cpp */,
@@ -6227,26 +6346,6 @@
path = source/Host/common;
sourceTree = "<group>";
};
- 6D0F61491C80AAF200A4ECEE /* Java */ = {
- isa = PBXGroup;
- children = (
- 6D0F614A1C80AB0400A4ECEE /* JavaLanguageRuntime.cpp */,
- 6D0F614B1C80AB0400A4ECEE /* JavaLanguageRuntime.h */,
- );
- name = Java;
- sourceTree = "<group>";
- };
- 6D0F61501C80AB1400A4ECEE /* Java */ = {
- isa = PBXGroup;
- children = (
- 6D0F61511C80AB3000A4ECEE /* JavaFormatterFunctions.cpp */,
- 6D0F61521C80AB3000A4ECEE /* JavaFormatterFunctions.h */,
- 6D0F61531C80AB3000A4ECEE /* JavaLanguage.cpp */,
- 6D0F61541C80AB3000A4ECEE /* JavaLanguage.h */,
- );
- name = Java;
- sourceTree = "<group>";
- };
6D55B29B1A8CCFF000A70529 /* android */ = {
isa = PBXGroup;
children = (
@@ -6351,9 +6450,12 @@
945261B71B9A11E800BF138D /* LibCxxInitializerList.cpp */,
945261B81B9A11E800BF138D /* LibCxxList.cpp */,
945261B91B9A11E800BF138D /* LibCxxMap.cpp */,
+ E4A63A9020F55D27000D9548 /* LibCxxOptional.cpp */,
AF9FF1F61FAA79FE00474976 /* LibCxxQueue.cpp */,
AF9FF1F41FAA79A400474976 /* LibCxxTuple.cpp */,
945261BA1B9A11E800BF138D /* LibCxxUnorderedMap.cpp */,
+ E414F6ED21388F0200C50BC6 /* LibCxxVariant.h */,
+ E414F6F021388F6B00C50BC6 /* LibCxxVariant.cpp */,
945261BB1B9A11E800BF138D /* LibCxxVector.cpp */,
945261BD1B9A11E800BF138D /* LibStdcpp.h */,
945261BC1B9A11E800BF138D /* LibStdcpp.cpp */,
@@ -6405,12 +6507,11 @@
94B638541B8FABEA004FE1E4 /* Language */ = {
isa = PBXGroup;
children = (
- 6D0F61501C80AB1400A4ECEE /* Java */,
+ 58A080AD2112AAC500D5580F /* ClangHighlighter.h */,
+ 58A080AB2112AABB00D5580F /* ClangHighlighter.cpp */,
94B6385A1B8FB109004FE1E4 /* CPlusPlus */,
- AE44FB431BB4BAC20033EB62 /* Go */,
94B638551B8FAC87004FE1E4 /* ObjC */,
94B638601B8FB7BE004FE1E4 /* ObjCPlusPlus */,
- 4CC7C64B1D5298AB0076FF94 /* OCaml */,
);
name = Language;
sourceTree = "<group>";
@@ -6433,6 +6534,8 @@
94B6385B1B8FB174004FE1E4 /* CPlusPlusLanguage.cpp */,
49F811F01E931B1500F4E163 /* CPlusPlusNameParser.h */,
49F811EF1E931B1500F4E163 /* CPlusPlusNameParser.cpp */,
+ AF395C01219254F200894EC3 /* MSVCUndecoratedNameParser.cpp */,
+ AF395C00219254F200894EC3 /* MSVCUndecoratedNameParser.h */,
);
name = CPlusPlus;
sourceTree = "<group>";
@@ -6578,62 +6681,10 @@
name = debugserver;
sourceTree = "<group>";
};
- AE44FB371BB35A2E0033EB62 /* Go */ = {
- isa = PBXGroup;
- children = (
- AE44FB261BB07DC60033EB62 /* GoAST.h */,
- AE44FB271BB07DC60033EB62 /* GoLexer.h */,
- AE44FB2A1BB07DD80033EB62 /* GoLexer.cpp */,
- AE44FB281BB07DC60033EB62 /* GoParser.h */,
- AE44FB2B1BB07DD80033EB62 /* GoParser.cpp */,
- AE44FB291BB07DC60033EB62 /* GoUserExpression.h */,
- AE44FB2C1BB07DD80033EB62 /* GoUserExpression.cpp */,
- );
- name = Go;
- sourceTree = "<group>";
- };
- AE44FB3B1BB485730033EB62 /* Go */ = {
- isa = PBXGroup;
- children = (
- AE44FB3C1BB4858A0033EB62 /* GoLanguageRuntime.h */,
- AE44FB3D1BB485960033EB62 /* GoLanguageRuntime.cpp */,
- );
- name = Go;
- sourceTree = "<group>";
- };
- AE44FB431BB4BAC20033EB62 /* Go */ = {
- isa = PBXGroup;
- children = (
- AE44FB491BB4BB1B0033EB62 /* Formatters */,
- AE44FB461BB4BB090033EB62 /* GoLanguage.h */,
- AE44FB451BB4BB090033EB62 /* GoLanguage.cpp */,
- );
- name = Go;
- sourceTree = "<group>";
- };
- AE44FB491BB4BB1B0033EB62 /* Formatters */ = {
- isa = PBXGroup;
- children = (
- AE44FB4B1BB4BB540033EB62 /* GoFormatterFunctions.h */,
- AE44FB4A1BB4BB540033EB62 /* GoFormatterFunctions.cpp */,
- );
- name = Formatters;
- sourceTree = "<group>";
- };
- AE8F624519EF3DFC00326B21 /* Go */ = {
- isa = PBXGroup;
- children = (
- AE8F624719EF3E1E00326B21 /* OperatingSystemGo.cpp */,
- AE8F624819EF3E1E00326B21 /* OperatingSystemGo.h */,
- );
- name = Go;
- sourceTree = "<group>";
- };
AEC6FF9D1BE97035007882C1 /* Expression */ = {
isa = PBXGroup;
children = (
23CB14F31D66CC9B00EDDDE1 /* CMakeLists.txt */,
- AEC6FF9F1BE970A2007882C1 /* GoParserTest.cpp */,
);
path = Expression;
sourceTree = "<group>";
@@ -6701,6 +6752,7 @@
AF2E029F1FA2CE8A00A86C34 /* Architecture */ = {
isa = PBXGroup;
children = (
+ 2647B62E21C4364F00A81D15 /* MIPS */,
4C14CEF52057258D00DEEF94 /* PPC64 */,
AF2E02A01FA2CE9900A86C34 /* Arm */,
);
@@ -6747,6 +6799,25 @@
name = "SysV-ppc64";
sourceTree = "<group>";
};
+ AF7F97652141FA2100795BC0 /* Disassembler */ = {
+ isa = PBXGroup;
+ children = (
+ AF7F97662141FA3800795BC0 /* TestArmv7Disassembly.cpp */,
+ );
+ name = Disassembler;
+ path = ../Disassembler;
+ sourceTree = "<group>";
+ };
+ AF97744421E99467006876A7 /* Breakpad */ = {
+ isa = PBXGroup;
+ children = (
+ AF97744621E9947B006876A7 /* SymbolFileBreakpad.cpp */,
+ AF97744521E9947B006876A7 /* SymbolFileBreakpad.h */,
+ );
+ name = Breakpad;
+ path = "New Group";
+ sourceTree = "<group>";
+ };
AFAFD8081E57E19E0017A14F /* Target */ = {
isa = PBXGroup;
children = (
@@ -6757,6 +6828,30 @@
name = Target;
sourceTree = "<group>";
};
+ AFD966B321714099006714AC /* NativePDB */ = {
+ isa = PBXGroup;
+ children = (
+ AFD966B4217140B5006714AC /* CompileUnitIndex.cpp */,
+ AFD966BD217140C8006714AC /* CompileUnitIndex.h */,
+ 4C38996221B9AECC002BAEF4 /* DWARFLocationExpression.cpp */,
+ 4C38996321B9AECC002BAEF4 /* DWARFLocationExpression.h */,
+ AF815DF721C855B400023A34 /* PdbAstBuilder.cpp */,
+ AF815DF821C855B400023A34 /* PdbAstBuilder.h */,
+ AFD966B6217140B6006714AC /* PdbIndex.cpp */,
+ AFD966BF217140C8006714AC /* PdbIndex.h */,
+ AF0F459D219FA1C800C1E612 /* PdbSymUid.cpp */,
+ AFD966BC217140C8006714AC /* PdbSymUid.h */,
+ AFD966B5217140B6006714AC /* PdbUtil.cpp */,
+ AFD966BE217140C8006714AC /* PdbUtil.h */,
+ AFD966B7217140B6006714AC /* SymbolFileNativePDB.cpp */,
+ AFD966C0217140C8006714AC /* SymbolFileNativePDB.h */,
+ AF0578C2217FA80700CF9D80 /* UdtRecordCompleter.cpp */,
+ AF0578C1217FA80700CF9D80 /* UdtRecordCompleter.h */,
+ );
+ name = NativePDB;
+ path = "New Group";
+ sourceTree = "<group>";
+ };
AFDBC36A2046638D00B9C8F2 /* PPC64 */ = {
isa = PBXGroup;
children = (
@@ -6895,6 +6990,7 @@
4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */,
263C493A178B50CF0070F12D /* SBModuleSpec.h in Headers */,
2617447A11685869005ADD65 /* SBType.h in Headers */,
+ 4C38996D21BA11CA002BAEF4 /* SBInitializerOptions.h in Headers */,
9475C18914E5EA08001BFC6D /* SBTypeCategory.h in Headers */,
941BCC7F14E48C4000BB969C /* SBTypeFilter.h in Headers */,
941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */,
@@ -6919,33 +7015,40 @@
files = (
AF8AD6381BEC28C400150209 /* PlatformRemoteAppleTV.h in Headers */,
26EFB61C1BFE8D3E00544801 /* PlatformNetBSD.h in Headers */,
+ 2647B64321C43BB000A81D15 /* LinuxProcMaps.h in Headers */,
AF3A4AD31EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.h in Headers */,
AF9113FE1FBE78EA004320CD /* RegisterContextPOSIXCore_ppc64le.h in Headers */,
AF33B4BF1C1FA441001B28D9 /* NetBSDSignals.h in Headers */,
- AF6335E31C87B21E00F7D554 /* SymbolFilePDB.h in Headers */,
AF6CA6681FBBAF37005A0DC3 /* ArchSpec.h in Headers */,
AF235EB41FBE7858009C5541 /* RegisterInfoPOSIX_ppc64le.h in Headers */,
AF2E02A41FA2CEAF00A86C34 /* ArchitectureArm.h in Headers */,
+ 2619C4872107A9A2009CDE81 /* RegisterContextMinidump_ARM.h in Headers */,
267F685A1CC02EBE0086832B /* RegisterInfos_s390x.h in Headers */,
267F68541CC02E920086832B /* RegisterContextLinux_s390x.h in Headers */,
+ 2619C4862107A9A2009CDE81 /* RegisterContextMinidump_ARM64.h in Headers */,
+ 2647B63421C4367A00A81D15 /* Event.h in Headers */,
AF235EB11FBE77B6009C5541 /* RegisterContextPOSIX_ppc64le.h in Headers */,
267F68501CC02E270086832B /* RegisterContextPOSIXCore_s390x.h in Headers */,
+ 4FBC04EF211A06820015A814 /* RichManglingContext.h in Headers */,
4984BA181B979C08008658D4 /* ExpressionVariable.h in Headers */,
+ 2647B63121C4366300A81D15 /* ArchitectureMips.h in Headers */,
26C7C4841BFFEA7E009BD01F /* WindowsMiniDump.h in Headers */,
30B38A001CAAA6D7009524E3 /* ClangUtil.h in Headers */,
AFD65C821D9B5B2E00D93120 /* RegisterContextMinidump_x86_64.h in Headers */,
+ 2647B63621C4368300A81D15 /* Broadcaster.h in Headers */,
238F2BA11D2C835A001FF92A /* StructuredDataPlugin.h in Headers */,
AF415AE81D949E4400FCE0D4 /* x86AssemblyInspectionEngine.h in Headers */,
AF8AD62F1BEC28A400150209 /* PlatformAppleTVSimulator.h in Headers */,
238F2BA91D2C85FA001FF92A /* StructuredDataDarwinLog.h in Headers */,
AF8AD63A1BEC28C400150209 /* PlatformRemoteAppleWatch.h in Headers */,
257906651BD5AFD000178368 /* Acceptor.h in Headers */,
+ 2647B63821C4369500A81D15 /* Listener.h in Headers */,
238F2BA21D2C835A001FF92A /* SystemRuntime.h in Headers */,
260A63171861008E00FECF8E /* IOHandler.h in Headers */,
267F68581CC02EAE0086832B /* RegisterContextPOSIX_s390x.h in Headers */,
- 6D0F614F1C80AB0C00A4ECEE /* JavaLanguageRuntime.h in Headers */,
AF27AD561D3603EA00CF2833 /* DynamicLoaderDarwin.h in Headers */,
AFCB2BBE1BF577F40018B553 /* PythonExceptionState.h in Headers */,
+ E414F6EE21388F0300C50BC6 /* LibCxxVariant.h in Headers */,
267F684B1CC02DED0086832B /* ABISysV_s390x.h in Headers */,
AF8AD6311BEC28A400150209 /* PlatformAppleWatchSimulator.h in Headers */,
);
@@ -6956,7 +7059,7 @@
/* Begin PBXLegacyTarget section */
2387551E1C24974600CCE8C3 /* lldb-python-test-suite */ = {
isa = PBXLegacyTarget;
- buildArgumentsString = "-u $(SRCROOT)/test/dotest.py --apple-sdk $(PLATFORM_NAME) --executable=$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/lldb -C $(LLDB_PYTHON_TESTSUITE_CC) --arch $(LLDB_PYTHON_TESTSUITE_ARCH) --session-file-format fm --results-formatter lldbsuite.test_event.formatter.xunit.XunitFormatter --build-dir $(BUILD_DIR)/lldb-test-build.noindex --results-file $(BUILD_DIR)/test-results-$(LLDB_PYTHON_TESTSUITE_ARCH).xml --rerun-all-issues --env TERM=vt100 -O--xpass=ignore";
+ buildArgumentsString = "-u $(SRCROOT)/test/dotest.py --apple-sdk $(PLATFORM_NAME) --executable=$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/lldb -C $(LLDB_PYTHON_TESTSUITE_CC) --arch $(LLDB_PYTHON_TESTSUITE_ARCH) --filecheck $(LLVM_BUILD_DIR)/x86_64/bin/FileCheck --session-file-format fm --results-formatter lldbsuite.test_event.formatter.xunit.XunitFormatter --build-dir $(BUILD_DIR)/lldb-test-build.noindex --results-file $(BUILD_DIR)/test-results-$(LLDB_PYTHON_TESTSUITE_ARCH).xml --rerun-all-issues --env TERM=vt100 -O--xpass=ignore";
buildConfigurationList = 238755241C24974600CCE8C3 /* Build configuration list for PBXLegacyTarget "lldb-python-test-suite" */;
buildPhases = (
);
@@ -7067,6 +7170,24 @@
productReference = 26680207115FD0ED008E1FE4 /* LLDB.framework */;
productType = "com.apple.product-type.framework";
};
+ 2679260B211CA3AC00EE1D10 /* lldb-vscode */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 26792614211CA3AD00EE1D10 /* Build configuration list for PBXNativeTarget "lldb-vscode" */;
+ buildPhases = (
+ 26792608211CA3AC00EE1D10 /* Sources */,
+ 26792609211CA3AC00EE1D10 /* Frameworks */,
+ 2679260A211CA3AC00EE1D10 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 26792620211CA40700EE1D10 /* PBXTargetDependency */,
+ );
+ name = "lldb-vscode";
+ productName = "lldb-vscode";
+ productReference = 2679260C211CA3AC00EE1D10 /* lldb-vscode */;
+ productType = "com.apple.product-type.tool";
+ };
2689FFC913353D7A00698AC0 /* lldb-core */ = {
isa = PBXNativeTarget;
buildConfigurationList = 2689FFD813353D7A00698AC0 /* Build configuration list for PBXNativeTarget "lldb-core" */;
@@ -7124,6 +7245,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 26F5C26E10F3D9C5009D5894 /* Build configuration list for PBXNativeTarget "lldb-tool" */;
buildPhases = (
+ DD5F951721ADD0C900B8265A /* Run Tablegen */,
26F5C26710F3D9A4009D5894 /* Sources */,
26F5C26810F3D9A4009D5894 /* Frameworks */,
);
@@ -7171,6 +7293,9 @@
239504D31BDD451400963CEA = {
CreatedOnToolsVersion = 7.1;
};
+ 2679260B211CA3AC00EE1D10 = {
+ CreatedOnToolsVersion = 9.4.1;
+ };
2690CD161A6DC0D000E717C8 = {
CreatedOnToolsVersion = 6.3;
};
@@ -7211,6 +7336,7 @@
2687EAC51508110B00DD8C2E /* install-headers */,
2690CD161A6DC0D000E717C8 /* lldb-mi */,
942829BF1A89835300521B30 /* lldb-argdumper */,
+ 2679260B211CA3AC00EE1D10 /* lldb-vscode */,
);
};
/* End PBXProject section */
@@ -7311,6 +7437,74 @@
files = (
);
inputPaths = (
+ "$(SRCROOT)/scripts/Python/python-wrapper.swig",
+ "$(SRCROOT)/scripts/Python/python-typemaps.swig",
+ "$(SRCROOT)/scripts/Python/python-swigsafecast.swig",
+ "$(SRCROOT)/source/API/SBAddress.cpp",
+ "$(SRCROOT)/source/API/SBAttachInfo.cpp",
+ "$(SRCROOT)/source/API/SBBlock.cpp",
+ "$(SRCROOT)/source/API/SBBreakpoint.cpp",
+ "$(SRCROOT)/source/API/SBBreakpointLocation.cpp",
+ "$(SRCROOT)/source/API/SBBreakpointName.cpp",
+ "$(SRCROOT)/source/API/SBBreakpointOptionCommon.cpp",
+ "$(SRCROOT)/source/API/SBBroadcaster.cpp",
+ "$(SRCROOT)/source/API/SBCommandInterpreter.cpp",
+ "$(SRCROOT)/source/API/SBCommandReturnObject.cpp",
+ "$(SRCROOT)/source/API/SBCompileUnit.cpp",
+ "$(SRCROOT)/source/API/SBData.cpp",
+ "$(SRCROOT)/source/API/SBDebugger.cpp",
+ "$(SRCROOT)/source/API/SBDeclaration.cpp",
+ "$(SRCROOT)/source/API/SBError.cpp",
+ "$(SRCROOT)/source/API/SBEvent.cpp",
+ "$(SRCROOT)/source/API/SBExecutionContext.cpp",
+ "$(SRCROOT)/source/API/SBExpressionOptions.cpp",
+ "$(SRCROOT)/source/API/SBFileSpec.cpp",
+ "$(SRCROOT)/source/API/SBFileSpecList.cpp",
+ "$(SRCROOT)/source/API/SBFrame.cpp",
+ "$(SRCROOT)/source/API/SBFunction.cpp",
+ "$(SRCROOT)/source/API/SBHostOS.cpp",
+ "$(SRCROOT)/source/API/SBInstruction.cpp",
+ "$(SRCROOT)/source/API/SBInstructionList.cpp",
+ "$(SRCROOT)/source/API/SBLanguageRuntime.cpp",
+ "$(SRCROOT)/source/API/SBLaunchInfo.cpp",
+ "$(SRCROOT)/source/API/SBLineEntry.cpp",
+ "$(SRCROOT)/source/API/SBListener.cpp",
+ "$(SRCROOT)/source/API/SBMemoryRegionInfo.cpp",
+ "$(SRCROOT)/source/API/SBMemoryRegionInfoList.cpp",
+ "$(SRCROOT)/source/API/SBModule.cpp",
+ "$(SRCROOT)/source/API/SBModuleSpec.cpp",
+ "$(SRCROOT)/source/API/SBPlatform.cpp",
+ "$(SRCROOT)/source/API/SBProcess.cpp",
+ "$(SRCROOT)/source/API/SBProcessInfo.cpp",
+ "$(SRCROOT)/source/API/SBQueue.cpp",
+ "$(SRCROOT)/source/API/SBQueueItem.cpp",
+ "$(SRCROOT)/source/API/SBSection.cpp",
+ "$(SRCROOT)/source/API/SBSourceManager.cpp",
+ "$(SRCROOT)/source/API/SBStream.cpp",
+ "$(SRCROOT)/source/API/SBStringList.cpp",
+ "$(SRCROOT)/source/API/SBStructuredData.cpp",
+ "$(SRCROOT)/source/API/SBSymbol.cpp",
+ "$(SRCROOT)/source/API/SBSymbolContext.cpp",
+ "$(SRCROOT)/source/API/SBSymbolContextList.cpp",
+ "$(SRCROOT)/source/API/SBTarget.cpp",
+ "$(SRCROOT)/source/API/SBThread.cpp",
+ "$(SRCROOT)/source/API/SBThreadCollection.cpp",
+ "$(SRCROOT)/source/API/SBThreadPlan.cpp",
+ "$(SRCROOT)/source/API/SBTrace.cpp",
+ "$(SRCROOT)/source/API/SBTraceOptions.cpp",
+ "$(SRCROOT)/source/API/SBType.cpp",
+ "$(SRCROOT)/source/API/SBTypeCategory.cpp",
+ "$(SRCROOT)/source/API/SBTypeEnumMember.cpp",
+ "$(SRCROOT)/source/API/SBTypeFilter.cpp",
+ "$(SRCROOT)/source/API/SBTypeFormat.cpp",
+ "$(SRCROOT)/source/API/SBTypeNameSpecifier.cpp",
+ "$(SRCROOT)/source/API/SBTypeSummary.cpp",
+ "$(SRCROOT)/source/API/SBTypeSynthetic.cpp",
+ "$(SRCROOT)/source/API/SBUnixSignals.cpp",
+ "$(SRCROOT)/source/API/SBValue.cpp",
+ "$(SRCROOT)/source/API/SBValueList.cpp",
+ "$(SRCROOT)/source/API/SBVariablesOptions.cpp",
+ "$(SRCROOT)/source/API/SBWatchpoint.cpp",
);
name = "Prepare Swig Bindings";
outputPaths = (
@@ -7333,7 +7527,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "/usr/bin/python $SRCROOT/scripts/Xcode/package-clang-headers.py $TARGET_BUILD_DIR $LLVM_BUILD_DIR/$CURRENT_ARCH\n";
+ shellScript = "/usr/bin/python $SRCROOT/scripts/Xcode/package-clang-headers.py $TARGET_BUILD_DIR $LLVM_BUILD_DIR/x86_64\n";
};
4C3326CA18B2A2B800EB5DD7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
@@ -7369,7 +7563,7 @@
inputPaths = (
"$(BUILT_PRODUCTS_DIR)/lldb.py",
"$(SRCROOT)/source/Interpreter/embedded_interpreter.py",
- "$(OBJECT_FILE_DIR_normal)/$(CURRENT_ARCH)/LLDBWrapPython.o",
+ "$(OBJECT_FILE_DIR_normal)/x86_64/LLDBWrapPython.o",
);
name = "Finish swig wrapper classes (lldb)";
outputPaths = (
@@ -7379,7 +7573,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
- shellScript = "sh $SRCROOT/scripts/finish-swig-wrapper-classes.sh $SRCROOT $TARGET_BUILD_DIR $BUILT_PRODUCTS_DIR \"\"";
+ shellScript = "sh $SRCROOT/scripts/finish-swig-wrapper-classes.sh $SRCROOT $TARGET_BUILD_DIR $BUILT_PRODUCTS_DIR \"\"\n";
};
AF3059151B4B390800E25622 /* Run Script - remove unneeded Resources and Swift dirs from iOS LLDB.framework bundle */ = {
isa = PBXShellScriptBuildPhase;
@@ -7393,9 +7587,29 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = "/bin/sh -x";
- shellScript = "/bin/rm -rf \"$INSTALL_ROOT/System/Library/PrivateFrameworks/LLDB.framework/Resources\" \"$INSTALL_ROOT/System/Library/PrivateFrameworks/LLDB.framework/Swift\"";
+ shellScript = "/bin/rm -rf \"$INSTALL_ROOT/System/Library/PrivateFrameworks/LLDB.framework/Resources\" \"$INSTALL_ROOT/System/Library/PrivateFrameworks/LLDB.framework/Swift\"\n";
showEnvVarsInLog = 0;
};
+ DD5F951721ADD0C900B8265A /* Run Tablegen */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ $SOURCE_DIR/tools/driver/Options.td,
+ );
+ name = "Run Tablegen";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ $BUILT_PRODUCTS_DIR/Options.inc,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "mkdir -p $BUILT_PRODUCTS_DIR/include\n$LLVM_BUILD_DIR/x86_64/bin/llvm-tblgen -I$LLVM_SOURCE_DIR/include -gen-opt-parser-defs $SRCROOT/tools/driver/Options.td -o $BUILT_PRODUCTS_DIR/include/Options.inc\n";
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -7411,7 +7625,6 @@
buildActionMask = 2147483647;
files = (
9A3D43D91F3151C400EB767C /* StatusTest.cpp in Sources */,
- 23CB15331D66DA9300EDDDE1 /* GoParserTest.cpp in Sources */,
23CB15341D66DA9300EDDDE1 /* CPlusPlusLanguageTest.cpp in Sources */,
9A2057381F3B8E7E00F6C293 /* FileSystemTest.cpp in Sources */,
9A2057201F3B8D2500F6C293 /* UnixSignalsTest.cpp in Sources */,
@@ -7424,8 +7637,10 @@
8C3BD9A01EF5D1FF0016C343 /* JSONTest.cpp in Sources */,
23CB15361D66DA9300EDDDE1 /* FileSpecTest.cpp in Sources */,
23E2E5251D90373D006F38BB /* ArchSpecTest.cpp in Sources */,
+ 58A080B32112AB2900D5580F /* HighlighterTest.cpp in Sources */,
9A2057081F3B819100F6C293 /* MemoryRegionInfoTest.cpp in Sources */,
9A20572D1F3B8E6600F6C293 /* TestCompletion.cpp in Sources */,
+ AFA1B62C219E0ED900A8AB7E /* DataExtractorTest.cpp in Sources */,
4C719399207D23E300FDF430 /* TestOptionArgParser.cpp in Sources */,
23CB15371D66DA9300EDDDE1 /* PythonTestSuite.cpp in Sources */,
23E2E5321D903832006F38BB /* BreakpointIDTest.cpp in Sources */,
@@ -7433,7 +7648,6 @@
58EAC73F2106A07B0029571E /* StreamTeeTest.cpp in Sources */,
23CB15381D66DA9300EDDDE1 /* PythonExceptionStateTests.cpp in Sources */,
9A3D43D81F3151C400EB767C /* NameMatchesTest.cpp in Sources */,
- 23CB15391D66DA9300EDDDE1 /* DataExtractorTest.cpp in Sources */,
4CEC86A4204738C5009B37B1 /* TestArm64InstEmulation.cpp in Sources */,
9A3D43ED1F3237F900EB767C /* StateTest.cpp in Sources */,
23CB153A1D66DA9300EDDDE1 /* GDBRemoteClientBaseTest.cpp in Sources */,
@@ -7447,6 +7661,7 @@
9A2057181F3B861400F6C293 /* TestType.cpp in Sources */,
9A2057171F3B861400F6C293 /* TestDWARFCallFrameInfo.cpp in Sources */,
4F29D3CF21010FA3003B549A /* MangledTest.cpp in Sources */,
+ 4FBC04F5211A13770015A814 /* RichManglingContextTest.cpp in Sources */,
9A3D43EC1F3237F900EB767C /* ListenerTest.cpp in Sources */,
9A3D43DC1F3151C400EB767C /* TimeoutTest.cpp in Sources */,
9A3D43D61F3151C400EB767C /* ConstStringTest.cpp in Sources */,
@@ -7466,6 +7681,7 @@
23CB15451D66DA9300EDDDE1 /* SocketAddressTest.cpp in Sources */,
9A3D43DD1F3151C400EB767C /* TimerTest.cpp in Sources */,
23CB15461D66DA9300EDDDE1 /* GDBRemoteTestUtils.cpp in Sources */,
+ AF7F97682141FA4500795BC0 /* TestArmv7Disassembly.cpp in Sources */,
23E2E5271D903782006F38BB /* MinidumpParserTest.cpp in Sources */,
23CB15471D66DA9300EDDDE1 /* EditlineTest.cpp in Sources */,
);
@@ -7513,6 +7729,7 @@
26680336116005EF008E1FE4 /* SBBreakpointLocation.cpp in Sources */,
26680337116005F1008E1FE4 /* SBBreakpoint.cpp in Sources */,
26DE204511618ADA00A093E2 /* SBAddress.cpp in Sources */,
+ AFB2F2F621B71AF30078DEF1 /* SBInitializerOptions.cpp in Sources */,
26DE204711618AED00A093E2 /* SBSymbolContext.cpp in Sources */,
26DE204D11618E7A00A093E2 /* SBModule.cpp in Sources */,
26DE205D1161901400A093E2 /* SBFunction.cpp in Sources */,
@@ -7555,15 +7772,32 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ 26792608211CA3AC00EE1D10 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2679261E211CA3F200EE1D10 /* lldb-vscode.cpp in Sources */,
+ 2660387E211CA98200329572 /* BreakpointBase.cpp in Sources */,
+ 26603879211CA90F00329572 /* SourceBreakpoint.cpp in Sources */,
+ 2660387A211CA90F00329572 /* ExceptionBreakpoint.cpp in Sources */,
+ 2660387B211CA90F00329572 /* JSONUtils.cpp in Sources */,
+ 26F7619B211CBBB30044F6EA /* LLDBUtils.cpp in Sources */,
+ 2660387C211CA90F00329572 /* FunctionBreakpoint.cpp in Sources */,
+ 26603878211CA90F00329572 /* VSCode.cpp in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
2689FFC613353D7A00698AC0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */,
2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */,
+ 4C9BF11B21C0467700FA4036 /* ObjectFileBreakpad.cpp in Sources */,
4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */,
AF415AE71D949E4400FCE0D4 /* x86AssemblyInspectionEngine.cpp in Sources */,
26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */,
+ 4FBC04ED211A06200015A814 /* RichManglingContext.cpp in Sources */,
AEB0E4591BD6E9F800B24093 /* LLVMUserExpression.cpp in Sources */,
2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */,
267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */,
@@ -7578,7 +7812,9 @@
2689FFF913353DB600698AC0 /* BreakpointLocationCollection.cpp in Sources */,
49F811F31E931B2100F4E163 /* CPlusPlusNameParser.cpp in Sources */,
2689FFFB13353DB600698AC0 /* BreakpointLocationList.cpp in Sources */,
+ AFD966B9217140B6006714AC /* PdbUtil.cpp in Sources */,
2689FFFD13353DB600698AC0 /* BreakpointOptions.cpp in Sources */,
+ AF0578C4217FA80700CF9D80 /* UdtRecordCompleter.cpp in Sources */,
2689FFFF13353DB600698AC0 /* BreakpointResolver.cpp in Sources */,
25420ECD1A6490B8009ADBCB /* OptionValueChar.cpp in Sources */,
2689000113353DB600698AC0 /* BreakpointResolverAddress.cpp in Sources */,
@@ -7602,7 +7838,6 @@
2689001113353DB600698AC0 /* Watchpoint.cpp in Sources */,
2689001213353DDE00698AC0 /* CommandObjectApropos.cpp in Sources */,
4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */,
- AE44FB4C1BB4BB540033EB62 /* GoFormatterFunctions.cpp in Sources */,
8C3BD9961EF45DA50016C343 /* MainThreadCheckerRuntime.cpp in Sources */,
23042D121976CA1D00621B2C /* PlatformKalimba.cpp in Sources */,
2689001413353DDE00698AC0 /* CommandObjectBreakpoint.cpp in Sources */,
@@ -7620,6 +7855,8 @@
23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */,
964463EC1A330C0500154ED8 /* CompactUnwindInfo.cpp in Sources */,
94B638531B8F8E6C004FE1E4 /* Language.cpp in Sources */,
+ AF395C03219254F300894EC3 /* MSVCUndecoratedNameParser.cpp in Sources */,
+ AF815DF921C855B400023A34 /* PdbAstBuilder.cpp in Sources */,
2689001D13353DDE00698AC0 /* CommandObjectLog.cpp in Sources */,
262173A318395D4600C52091 /* SectionLoadHistory.cpp in Sources */,
2689001E13353DDE00698AC0 /* CommandObjectMemory.cpp in Sources */,
@@ -7629,18 +7866,17 @@
2689002113353DDE00698AC0 /* CommandObjectQuit.cpp in Sources */,
2689002213353DDE00698AC0 /* CommandObjectRegister.cpp in Sources */,
26BC17AF18C7F4CB00D2196D /* RegisterContextPOSIXCore_x86_64.cpp in Sources */,
+ 2619C4842107A9A2009CDE81 /* RegisterContextMinidump_ARM64.cpp in Sources */,
2689002313353DDE00698AC0 /* CommandObjectScript.cpp in Sources */,
2689002413353DDE00698AC0 /* CommandObjectSettings.cpp in Sources */,
2689002513353DDE00698AC0 /* CommandObjectSource.cpp in Sources */,
267A48011B1411E40021A5BC /* XML.cpp in Sources */,
AF8AD6371BEC28C400150209 /* PlatformRemoteAppleTV.cpp in Sources */,
- 6D0F614E1C80AB0700A4ECEE /* JavaLanguageRuntime.cpp in Sources */,
2666ADC61B3CB675001FAFD3 /* DynamicLoaderHexagonDYLD.cpp in Sources */,
3F8169331ABB7A6D001DA9DF /* SystemLifetimeManager.cpp in Sources */,
AF2E02A31FA2CEAF00A86C34 /* ArchitectureArm.cpp in Sources */,
4959511F1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp in Sources */,
26BC179918C7F2B300D2196D /* JITLoader.cpp in Sources */,
- 4CC7C6571D52997A0076FF94 /* OCamlASTContext.cpp in Sources */,
947CF7761DC7B20D00EF980B /* RegisterContextMinidump_x86_32.cpp in Sources */,
2689002713353DDE00698AC0 /* CommandObjectTarget.cpp in Sources */,
2689002813353DDE00698AC0 /* CommandObjectThread.cpp in Sources */,
@@ -7656,7 +7892,6 @@
2689002D13353E0400698AC0 /* AddressResolverFileLine.cpp in Sources */,
2689002E13353E0400698AC0 /* AddressResolverName.cpp in Sources */,
250D6AE31A9679440049CC70 /* FileSystem.cpp in Sources */,
- 2689003113353E0400698AC0 /* Broadcaster.cpp in Sources */,
49DCF702170E70120092F75E /* Materializer.cpp in Sources */,
2689003213353E0400698AC0 /* Communication.cpp in Sources */,
2689003313353E0400698AC0 /* Connection.cpp in Sources */,
@@ -7671,26 +7906,26 @@
AF77E0A11A033D360096C0EA /* RegisterContextFreeBSD_powerpc.cpp in Sources */,
26764CA01E48F528008D3573 /* RegularExpression.cpp in Sources */,
2689003B13353E0400698AC0 /* EmulateInstruction.cpp in Sources */,
- 2689003D13353E0400698AC0 /* Event.cpp in Sources */,
AFC2DCE91E6E2F2C00283714 /* Baton.cpp in Sources */,
26B75B441AD6E29A001F7A57 /* MipsLinuxSignals.cpp in Sources */,
2689003E13353E0400698AC0 /* FileSpecList.cpp in Sources */,
- 2689004113353E0400698AC0 /* Listener.cpp in Sources */,
269DDD4A1B8FD1C300D0DBD8 /* DWARFASTParserClang.cpp in Sources */,
2689004213353E0400698AC0 /* Log.cpp in Sources */,
2689004313353E0400698AC0 /* Mangled.cpp in Sources */,
2689004413353E0400698AC0 /* Module.cpp in Sources */,
2689004513353E0400698AC0 /* ModuleChild.cpp in Sources */,
+ 2647B63A21C436AC00A81D15 /* Broadcaster.cpp in Sources */,
AF8AD6301BEC28A400150209 /* PlatformAppleWatchSimulator.cpp in Sources */,
266E829D1B8E542C008FCA06 /* DWARFAttribute.cpp in Sources */,
26764C9E1E48F51E008D3573 /* Stream.cpp in Sources */,
2689004613353E0400698AC0 /* ModuleList.cpp in Sources */,
+ AF0F459E219FA1C800C1E612 /* PdbSymUid.cpp in Sources */,
2689004713353E0400698AC0 /* PluginManager.cpp in Sources */,
- AE44FB3E1BB485960033EB62 /* GoLanguageRuntime.cpp in Sources */,
AFF81FAF20D1CC400010F95E /* HostThreadMacOSX.mm in Sources */,
AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */,
AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */,
2689004913353E0400698AC0 /* Scalar.cpp in Sources */,
+ E414F6F121388F6C00C50BC6 /* LibCxxVariant.cpp in Sources */,
263FDE601A79A01500E68013 /* FormatEntity.cpp in Sources */,
AF8AD62E1BEC28A400150209 /* PlatformAppleTVSimulator.cpp in Sources */,
2689004A13353E0400698AC0 /* SearchFilter.cpp in Sources */,
@@ -7704,11 +7939,11 @@
3F81691A1ABA2419001DA9DF /* NameMatches.cpp in Sources */,
94B9E5121BBF20F4000A48DC /* NSString.cpp in Sources */,
AF0E22F018A09FB20009B7D1 /* AppleGetItemInfoHandler.cpp in Sources */,
- AE44FB301BB07EB20033EB62 /* GoUserExpression.cpp in Sources */,
2689004F13353E0400698AC0 /* StreamFile.cpp in Sources */,
2689005113353E0400698AC0 /* StringList.cpp in Sources */,
2689005213353E0400698AC0 /* Timer.cpp in Sources */,
2689005413353E0400698AC0 /* UserSettingsController.cpp in Sources */,
+ 2619C4852107A9A2009CDE81 /* RegisterContextMinidump_ARM.cpp in Sources */,
23059A0719532B96007B8189 /* LinuxSignals.cpp in Sources */,
8CCB017E19BA28A80009FD44 /* ThreadCollection.cpp in Sources */,
9A77AD541E64E2760025CE04 /* RegisterInfoPOSIX_arm.cpp in Sources */,
@@ -7719,8 +7954,8 @@
2689005813353E0400698AC0 /* ValueObjectChild.cpp in Sources */,
E7723D441AC4A7FB002BA082 /* RegisterContextPOSIXCore_arm64.cpp in Sources */,
233B007F1960CB280090E598 /* ProcessLaunchInfo.cpp in Sources */,
- 6D0F61591C80AB3500A4ECEE /* JavaFormatterFunctions.cpp in Sources */,
2689005913353E0400698AC0 /* ValueObjectConstResult.cpp in Sources */,
+ 4CCF9F612143014D006CC7EA /* BreakpointResolverScripted.cpp in Sources */,
2689005A13353E0400698AC0 /* ValueObjectList.cpp in Sources */,
492DB7EB1EC662E200B9E9AF /* Status.cpp in Sources */,
2689005B13353E0400698AC0 /* ValueObjectRegister.cpp in Sources */,
@@ -7753,6 +7988,7 @@
AF2BA6EC1A707E3400C5248A /* UriParser.cpp in Sources */,
2689006D13353E0E00698AC0 /* IRExecutionUnit.cpp in Sources */,
304B2E461CAAA57B007829FE /* ClangUtil.cpp in Sources */,
+ 2647B64421C43BB000A81D15 /* LinuxProcMaps.cpp in Sources */,
2689006E13353E1A00698AC0 /* File.cpp in Sources */,
2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */,
AF6CA6661FBBAF28005A0DC3 /* ArchSpec.cpp in Sources */,
@@ -7766,7 +8002,6 @@
2689007313353E1A00698AC0 /* Symbols.cpp in Sources */,
26474CBC18D0CB2D0073DEBA /* RegisterContextMach_arm.cpp in Sources */,
2689007413353E1A00698AC0 /* Terminal.cpp in Sources */,
- 6D0F61431C80AAAE00A4ECEE /* JavaASTContext.cpp in Sources */,
2689007613353E1A00698AC0 /* CFCBundle.cpp in Sources */,
9A0FDEA71E8EF5110086B2F5 /* RegisterContextLinux_mips.cpp in Sources */,
94BA8B70176F97CE005A91B5 /* CommandHistory.cpp in Sources */,
@@ -7783,7 +8018,6 @@
2689007C13353E1A00698AC0 /* Symbols.cpp in Sources */,
2689007D13353E2200698AC0 /* Args.cpp in Sources */,
2689007F13353E2200698AC0 /* CommandCompletions.cpp in Sources */,
- AE6897281B94F6DE0018845D /* DWARFASTParserGo.cpp in Sources */,
945261C41B9A11FC00BF138D /* LibCxxUnorderedMap.cpp in Sources */,
26CEB5F218762056008F575A /* CommandObjectGUI.cpp in Sources */,
AF3A4AD21EA05C4700B5DEB4 /* PlatformRemoteDarwinDevice.cpp in Sources */,
@@ -7813,7 +8047,6 @@
2689009613353E4200698AC0 /* ObjectContainerBSDArchive.cpp in Sources */,
49CA96FF1E6AACC900C03FEE /* DataExtractor.cpp in Sources */,
2579065D1BD0488100178368 /* UDPSocket.cpp in Sources */,
- AE8F624919EF3E1E00326B21 /* OperatingSystemGo.cpp in Sources */,
26BC179A18C7F2B300D2196D /* JITLoaderList.cpp in Sources */,
23D065901D4A7BEE0008EDE6 /* RenderScriptRuntime.cpp in Sources */,
2689009713353E4200698AC0 /* ObjectContainerUniversalMachO.cpp in Sources */,
@@ -7832,14 +8065,16 @@
AFE228832060699D0042D0C8 /* DWARFUnit.cpp in Sources */,
AEEA34051AC88A7400AB639D /* TypeSystem.cpp in Sources */,
AF1729D6182C907200E0AB97 /* HistoryThread.cpp in Sources */,
+ 2647B63221C4366300A81D15 /* ArchitectureMips.cpp in Sources */,
268900AF13353E5000698AC0 /* UnwindLLDB.cpp in Sources */,
268900B013353E5000698AC0 /* RegisterContextLLDB.cpp in Sources */,
23E2E5451D904913006F38BB /* MinidumpTypes.cpp in Sources */,
AF33B4BE1C1FA441001B28D9 /* NetBSDSignals.cpp in Sources */,
949EEDA31BA76577008C63CF /* Cocoa.cpp in Sources */,
+ AFD966BB217140B6006714AC /* SymbolFileNativePDB.cpp in Sources */,
+ AFCB1D59219CD4FD00730AD5 /* GDBRemoteCommunicationReplayServer.cpp in Sources */,
3FDFE56C19AF9C44009756A7 /* HostProcessPosix.cpp in Sources */,
268900B413353E5000698AC0 /* RegisterContextMacOSXFrameBackchain.cpp in Sources */,
- AE44FB321BB07EBC0033EB62 /* GoParser.cpp in Sources */,
6B74D89B200696BB0074051B /* Environment.cpp in Sources */,
3F8169311ABB7A6D001DA9DF /* SystemInitializer.cpp in Sources */,
949EEDB21BA76731008C63CF /* NSIndexPath.cpp in Sources */,
@@ -7848,13 +8083,16 @@
268900B613353E5000698AC0 /* UnwindMacOSXFrameBackchain.cpp in Sources */,
4CE4EFB41E899A4000A80C06 /* RegisterContextOpenBSD_x86_64.cpp in Sources */,
268900B713353E5F00698AC0 /* DWARFAbbreviationDeclaration.cpp in Sources */,
+ AFD966B8217140B6006714AC /* CompileUnitIndex.cpp in Sources */,
268900B813353E5F00698AC0 /* DWARFCompileUnit.cpp in Sources */,
268900B913353E5F00698AC0 /* DWARFDebugAbbrev.cpp in Sources */,
+ AF8AD945219CD45800614785 /* GDBRemoteCommunicationHistory.cpp in Sources */,
949EEDB31BA76736008C63CF /* NSSet.cpp in Sources */,
268900BA13353E5F00698AC0 /* DWARFDebugAranges.cpp in Sources */,
268900BB13353E5F00698AC0 /* DWARFDebugArangeSet.cpp in Sources */,
268900BC13353E5F00698AC0 /* DWARFDebugInfo.cpp in Sources */,
268900BD13353E5F00698AC0 /* DWARFDebugInfoEntry.cpp in Sources */,
+ AF663250216EB9C300BB510D /* PlatformRemoteAppleBridge.cpp in Sources */,
268900BE13353E5F00698AC0 /* DWARFDebugLine.cpp in Sources */,
268900BF13353E5F00698AC0 /* DWARFDebugMacinfo.cpp in Sources */,
268900C013353E5F00698AC0 /* DWARFDebugMacinfoEntry.cpp in Sources */,
@@ -7889,6 +8127,7 @@
945261C11B9A11FC00BF138D /* LibCxxInitializerList.cpp in Sources */,
268900D313353E6F00698AC0 /* ClangExternalASTSourceCallbacks.cpp in Sources */,
268900D513353E6F00698AC0 /* CompileUnit.cpp in Sources */,
+ AFCB1D5C219CD5A800730AD5 /* CommandObjectReproducer.cpp in Sources */,
268900D613353E6F00698AC0 /* Declaration.cpp in Sources */,
2579065C1BD0488100178368 /* TCPSocket.cpp in Sources */,
268900D713353E6F00698AC0 /* DWARFCallFrameInfo.cpp in Sources */,
@@ -7913,6 +8152,7 @@
945261C51B9A11FC00BF138D /* LibCxxVector.cpp in Sources */,
3FDFED2719BA6D96009756A7 /* HostNativeThreadBase.cpp in Sources */,
268900E313353E6F00698AC0 /* TypeList.cpp in Sources */,
+ 2647B63E21C436BD00A81D15 /* Listener.cpp in Sources */,
268900E413353E6F00698AC0 /* UnwindPlan.cpp in Sources */,
268900E513353E6F00698AC0 /* UnwindTable.cpp in Sources */,
AFF8FF0C1E779D4B003830EF /* TildeExpressionResolver.cpp in Sources */,
@@ -7930,10 +8170,10 @@
268900EB13353E6F00698AC0 /* ExecutionContext.cpp in Sources */,
268900EC13353E6F00698AC0 /* LanguageRuntime.cpp in Sources */,
268900ED13353E6F00698AC0 /* ObjCLanguageRuntime.cpp in Sources */,
- 4CC7C6581D529B950076FF94 /* DWARFASTParserOCaml.cpp in Sources */,
268900EE13353E6F00698AC0 /* PathMappingList.cpp in Sources */,
4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */,
AF2907BF1D3F082400E10654 /* DynamicLoaderMacOS.cpp in Sources */,
+ AFCB1D5F219CD5EA00730AD5 /* Reproducer.cpp in Sources */,
268900EF13353E6F00698AC0 /* Platform.cpp in Sources */,
268900F013353E6F00698AC0 /* Process.cpp in Sources */,
26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */,
@@ -7942,7 +8182,9 @@
268900F213353E6F00698AC0 /* SectionLoadList.cpp in Sources */,
268900F313353E6F00698AC0 /* StackFrame.cpp in Sources */,
268900F413353E6F00698AC0 /* StackFrameList.cpp in Sources */,
+ 8CF46A6220522A9800423DDF /* StackFrameRecognizer.cpp in Sources */,
268900F513353E6F00698AC0 /* StackID.cpp in Sources */,
+ 228B1B672113340200E61C70 /* ClangHighlighter.cpp in Sources */,
268900F613353E6F00698AC0 /* StopInfo.cpp in Sources */,
256CBDB41ADD0EFD00BC6CDC /* RegisterContextPOSIXCore_arm.cpp in Sources */,
267F684F1CC02E270086832B /* RegisterContextPOSIXCore_s390x.cpp in Sources */,
@@ -7956,6 +8198,7 @@
26BF51F31B3C754400016294 /* ABISysV_hexagon.cpp in Sources */,
232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */,
8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.cpp in Sources */,
+ 58A080B42112AB3800D5580F /* Highlighter.cpp in Sources */,
268900FC13353E6F00698AC0 /* ThreadPlanBase.cpp in Sources */,
268900FD13353E6F00698AC0 /* ThreadPlanCallFunction.cpp in Sources */,
23D4007D1C2101F2000C3885 /* DWARFDebugMacro.cpp in Sources */,
@@ -7965,17 +8208,14 @@
268900FF13353E6F00698AC0 /* ThreadPlanShouldStopHere.cpp in Sources */,
2579065F1BD0488D00178368 /* DomainSocket.cpp in Sources */,
2689010013353E6F00698AC0 /* ThreadPlanStepInstruction.cpp in Sources */,
- AFC2DCE71E6E2ED000283714 /* FastDemangle.cpp in Sources */,
232CB61B191E00CD00EF39FC /* NativeThreadProtocol.cpp in Sources */,
4CD44CFB20B37C440003557C /* DWARFIndex.cpp in Sources */,
2689010113353E6F00698AC0 /* ThreadPlanStepOut.cpp in Sources */,
2689010213353E6F00698AC0 /* ThreadPlanStepOverBreakpoint.cpp in Sources */,
3FDFED2919BA6D96009756A7 /* ThreadLauncher.cpp in Sources */,
- 232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */,
4C719395207D235400FDF430 /* OptionArgParser.cpp in Sources */,
942829561A89614C00521B30 /* JSON.cpp in Sources */,
267F68531CC02E920086832B /* RegisterContextLinux_s390x.cpp in Sources */,
- 232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */,
2689010313353E6F00698AC0 /* ThreadPlanStepRange.cpp in Sources */,
2689010413353E6F00698AC0 /* ThreadPlanStepInRange.cpp in Sources */,
2689010513353E6F00698AC0 /* ThreadPlanStepOverRange.cpp in Sources */,
@@ -7995,7 +8235,6 @@
2689010C13353E6F00698AC0 /* UnixSignals.cpp in Sources */,
2689011013353E8200698AC0 /* SharingPtr.cpp in Sources */,
2689011113353E8200698AC0 /* StringExtractor.cpp in Sources */,
- 6D0F615A1C80AB3900A4ECEE /* JavaLanguage.cpp in Sources */,
2689011213353E8200698AC0 /* StringExtractorGDBRemote.cpp in Sources */,
E7723D4C1AC4A944002BA082 /* RegisterContextPOSIX_arm64.cpp in Sources */,
26BC17AB18C7F4CB00D2196D /* ProcessElfCore.cpp in Sources */,
@@ -8020,12 +8259,10 @@
23E2E5441D904913006F38BB /* MinidumpParser.cpp in Sources */,
AF77E0931A033C7F0096C0EA /* ABISysV_ppc64.cpp in Sources */,
26D5E15F135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp in Sources */,
- 6D0F61481C80AAD600A4ECEE /* DWARFASTParserJava.cpp in Sources */,
26D5E163135BB054006EA0A7 /* OptionGroupPlatform.cpp in Sources */,
94CD131A19BA33B400DB7BED /* TypeValidator.cpp in Sources */,
26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */,
230EC45B1D63C3BA008DF59F /* ThreadPlanCallOnFunctionExit.cpp in Sources */,
- AE44FB311BB07EB80033EB62 /* GoLexer.cpp in Sources */,
26A7A035135E6E4200FB369E /* OptionValue.cpp in Sources */,
9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */,
AFDFDFD119E34D3400EAE509 /* ConnectionFileDescriptorPosix.cpp in Sources */,
@@ -8033,7 +8270,6 @@
9A22A163135E30370024DDC3 /* EmulationStateARM.cpp in Sources */,
9A4F35101368A51A00823F52 /* StreamAsynchronousIO.cpp in Sources */,
AF1D88691B575E8D003CB899 /* ValueObjectConstResultCast.cpp in Sources */,
- 4CC7C6501D5298F30076FF94 /* OCamlLanguage.cpp in Sources */,
2692BA15136610C100F9E14D /* UnwindAssemblyInstEmulation.cpp in Sources */,
263E949F13661AEA00E7D1CE /* UnwindAssembly-x86.cpp in Sources */,
AFA585D02107EB7400D7689A /* DumpRegisterValue.cpp in Sources */,
@@ -8045,6 +8281,7 @@
AF26703B1852D01E00B6CC36 /* QueueList.cpp in Sources */,
267C012B136880DF006E963E /* OptionGroupValueObjectDisplay.cpp in Sources */,
49CA96FE1E6AACC900C03FEE /* DataEncoder.cpp in Sources */,
+ E4A63A9120F55D28000D9548 /* LibCxxOptional.cpp in Sources */,
26BCFC521368AE38006DC050 /* OptionGroupFormat.cpp in Sources */,
2654A6901E552ED500DA1013 /* VASprintf.cpp in Sources */,
AF81DEFA1828A23F0042CF19 /* SystemRuntime.cpp in Sources */,
@@ -8062,7 +8299,6 @@
26F006561B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.cpp in Sources */,
26DB3E1C1379E7AD0080DC73 /* ABIMacOSX_i386.cpp in Sources */,
26DB3E1F1379E7AD0080DC73 /* ABISysV_x86_64.cpp in Sources */,
- 232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */,
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */,
2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */,
4C562CC71CC07DF700C52EAC /* PDBASTParser.cpp in Sources */,
@@ -8077,6 +8313,7 @@
9463D4CD13B1798800C230D4 /* CommandObjectType.cpp in Sources */,
49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */,
26ED3D6D13C563810017D45E /* OptionGroupVariable.cpp in Sources */,
+ 2647B63C21C436B400A81D15 /* Event.cpp in Sources */,
2642FBAE13D003B400ED6808 /* CommunicationKDP.cpp in Sources */,
2642FBB013D003B400ED6808 /* ProcessKDP.cpp in Sources */,
23D4007E1C210201000C3885 /* DebugMacros.cpp in Sources */,
@@ -8085,6 +8322,7 @@
2642FBB213D003B400ED6808 /* ProcessKDPLog.cpp in Sources */,
263641191B34AEE200145B2F /* ABISysV_mips64.cpp in Sources */,
26957D9813D381C900670048 /* RegisterContextDarwin_arm.cpp in Sources */,
+ 4C38996421B9AECD002BAEF4 /* DWARFLocationExpression.cpp in Sources */,
26957D9A13D381C900670048 /* RegisterContextDarwin_i386.cpp in Sources */,
26957D9C13D381C900670048 /* RegisterContextDarwin_x86_64.cpp in Sources */,
94CD7D0919A3FBA300908B7C /* AppleObjCClassDescriptorV2.cpp in Sources */,
@@ -8104,6 +8342,7 @@
3FBA69E11B6067120008F44A /* ScriptInterpreterNone.cpp in Sources */,
AF9113FD1FBE78EA004320CD /* RegisterContextPOSIXCore_ppc64le.cpp in Sources */,
266DFE9713FD656E00D0C574 /* OperatingSystem.cpp in Sources */,
+ AF97744721E9947E006876A7 /* SymbolFileBreakpad.cpp in Sources */,
AF8AD6391BEC28C400150209 /* PlatformRemoteAppleWatch.cpp in Sources */,
26954EBE1401EE8B00294D09 /* DynamicRegisterInfo.cpp in Sources */,
6D9AB3DD1BB2B74E003F2289 /* TypeMap.cpp in Sources */,
@@ -8158,7 +8397,6 @@
260CC64C15D0440D002BF2E0 /* OptionValueDictionary.cpp in Sources */,
49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */,
260CC64D15D0440D002BF2E0 /* OptionValueEnumeration.cpp in Sources */,
- AE7F56291B8FE418001377A8 /* GoASTContext.cpp in Sources */,
260CC64E15D0440D002BF2E0 /* OptionValueFileSpec.cpp in Sources */,
AF2BCA6C18C7EFDE005B4526 /* JITLoaderGDB.cpp in Sources */,
267F68571CC02EAE0086832B /* RegisterContextPOSIX_s390x.cpp in Sources */,
@@ -8171,7 +8409,6 @@
6D55B2911A8A806200A70529 /* GDBRemoteCommunicationServerLLGS.cpp in Sources */,
260CC65315D0440D002BF2E0 /* OptionValueUInt64.cpp in Sources */,
260CC65415D0440D002BF2E0 /* OptionValueUUID.cpp in Sources */,
- 94BA8B6D176F8C9B005A91B5 /* Range.cpp in Sources */,
267F684A1CC02DED0086832B /* ABISysV_s390x.cpp in Sources */,
AFDBC36E204663AF00B9C8F2 /* EmulateInstructionPPC64.cpp in Sources */,
26DAED6315D327C200E15819 /* OptionValuePathMappings.cpp in Sources */,
@@ -8188,7 +8425,7 @@
947A1D641616476B0017C8D1 /* CommandObjectPlugin.cpp in Sources */,
2666ADC81B3CB675001FAFD3 /* HexagonDYLDRendezvous.cpp in Sources */,
26A375811D59462700D6CBDB /* SelectHelper.cpp in Sources */,
- AE44FB471BB4BB090033EB62 /* GoLanguage.cpp in Sources */,
+ AFD966BA217140B6006714AC /* PdbIndex.cpp in Sources */,
262ED0081631FA3A00879631 /* OptionGroupString.cpp in Sources */,
94F48F251A01C687005C0EC6 /* StringPrinter.cpp in Sources */,
94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */,
@@ -8346,6 +8583,11 @@
target = 26680206115FD0ED008E1FE4 /* LLDB */;
targetProxy = 266803611160110D008E1FE4 /* PBXContainerItemProxy */;
};
+ 26792620211CA40700EE1D10 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 26680206115FD0ED008E1FE4 /* LLDB */;
+ targetProxy = 2679261F211CA40700EE1D10 /* PBXContainerItemProxy */;
+ };
2687EACB1508115000DD8C2E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2687EAC51508110B00DD8C2E /* install-headers */;
@@ -8479,8 +8721,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "-weak-lcompression";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_COVERAGE_CFLAGS = "$(LLDB_COVERAGE_CFLAGS_$(LLDB_ENABLE_COVERAGE))";
LLDB_COVERAGE_CFLAGS_1 = "-fprofile-instr-generate -fcoverage-mapping";
LLDB_COVERAGE_LDFLAGS = "$(LLDB_COVERAGE_LDFLAGS_$(LLDB_ENABLE_COVERAGE))";
@@ -8490,24 +8731,19 @@
LLDB_ENABLE_COVERAGE = 0;
LLDB_FRAMEWORK_INSTALL_DIR = /Applications/Xcode.app/Contents/SharedFrameworks;
LLDB_TOOLS_INSTALL_DIR = /usr/bin;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
LLVM_BUILD_DIR = "$(SRCROOT)/llvm-build/$(LLVM_CONFIGURATION)";
LLVM_BUILD_DIRTREE = "$(SRCROOT)/llvm-build";
- LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/";
+ LLVM_BUILD_DIR_ARCH = x86_64/;
LLVM_CONFIGURATION = "Release+Asserts";
LLVM_SOURCE_DIR = "$(SRCROOT)/llvm";
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_COVERAGE_CFLAGS)",
"-Wimplicit-fallthrough",
);
OTHER_LDFLAGS = (
- "$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
+ "-lcompression",
"$(LLDB_COVERAGE_LDFLAGS)",
);
PYTHON_FRAMEWORK_PATH = /System/Library/Frameworks/Python.framework/;
@@ -8569,8 +8805,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "-weak-lcompression";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_COVERAGE_CFLAGS = "$(LLDB_COVERAGE_CFLAGS_$(LLDB_ENABLE_COVERAGE))";
LLDB_COVERAGE_CFLAGS_1 = "-fprofile-instr-generate -fcoverage-mapping";
LLDB_COVERAGE_LDFLAGS = "$(LLDB_COVERAGE_LDFLAGS_$(LLDB_ENABLE_COVERAGE))";
@@ -8580,24 +8815,19 @@
LLDB_ENABLE_COVERAGE = 0;
LLDB_FRAMEWORK_INSTALL_DIR = /Applications/Xcode.app/Contents/SharedFrameworks;
LLDB_TOOLS_INSTALL_DIR = /usr/bin;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
LLVM_BUILD_DIR = "$(SRCROOT)/llvm-build/$(LLVM_CONFIGURATION)";
LLVM_BUILD_DIRTREE = "$(SRCROOT)/llvm-build";
- LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/";
+ LLVM_BUILD_DIR_ARCH = x86_64/;
LLVM_CONFIGURATION = "Release+Asserts";
LLVM_SOURCE_DIR = "$(SRCROOT)/llvm";
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_COVERAGE_CFLAGS)",
"-Wimplicit-fallthrough",
);
OTHER_LDFLAGS = (
- "$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
+ "-lcompression",
"$(LLDB_COVERAGE_LDFLAGS)",
);
PYTHON_FRAMEWORK_PATH = /System/Library/Frameworks/Python.framework/;
@@ -8731,8 +8961,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -8773,8 +9001,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -8815,8 +9041,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -8857,8 +9081,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -8899,8 +9121,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -8919,6 +9139,7 @@
"-framework",
ApplicationServices,
"$(LLDB_GTESTS_LDFLAGS)",
+ "$(LLDB_COMPRESSION_LDFLAGS)",
);
PRODUCT_NAME = "lldb-gtest";
};
@@ -8941,8 +9162,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -8961,6 +9180,7 @@
"-framework",
ApplicationServices,
"$(LLDB_GTESTS_LDFLAGS)",
+ "$(LLDB_COMPRESSION_LDFLAGS)",
);
PRODUCT_NAME = "lldb-gtest";
};
@@ -8983,8 +9203,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -9003,6 +9221,7 @@
"-framework",
ApplicationServices,
"$(LLDB_GTESTS_LDFLAGS)",
+ "$(LLDB_COMPRESSION_LDFLAGS)",
);
PRODUCT_NAME = "lldb-gtest";
};
@@ -9025,8 +9244,6 @@
OTHER_CFLAGS = (
"-fno-rtti",
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_GTESTS_CFLAGS)",
"-DGTEST_HAS_RTTI=0",
);
@@ -9045,6 +9262,7 @@
"-framework",
ApplicationServices,
"$(LLDB_GTESTS_LDFLAGS)",
+ "$(LLDB_COMPRESSION_LDFLAGS)",
);
PRODUCT_NAME = "lldb-gtest";
};
@@ -9116,12 +9334,7 @@
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)",
"$(inherited)",
);
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
"-fno-rtti",
@@ -9189,12 +9402,7 @@
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)",
"$(inherited)",
);
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
"-fno-rtti",
@@ -9235,6 +9443,212 @@
};
name = Release;
};
+ 26792610211CA3AD00EE1D10 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CURRENT_PROJECT_VERSION = 360.99.0;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ OTHER_LDFLAGS = (
+ "-sectcreate",
+ __TEXT,
+ __info_plist,
+ "$(PROJECT_DIR)/tools/lldb-vscode/lldb-vscode-Info.plist",
+ "-Wl,-rpath,@loader_path/",
+ "-filelist",
+ "$(LLVM_BUILD_DIR)/archives.txt",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_SOURCE_DIR)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib/Target/ARM";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 26792611211CA3AD00EE1D10 /* DebugClang */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CURRENT_PROJECT_VERSION = 360.99.0;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ OTHER_LDFLAGS = (
+ "-sectcreate",
+ __TEXT,
+ __info_plist,
+ "$(PROJECT_DIR)/tools/lldb-vscode/lldb-vscode-Info.plist",
+ "-Wl,-rpath,@loader_path/",
+ "-filelist",
+ "$(LLVM_BUILD_DIR)/archives.txt",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_SOURCE_DIR)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib/Target/ARM";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = DebugClang;
+ };
+ 26792612211CA3AD00EE1D10 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CURRENT_PROJECT_VERSION = 360.99.0;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ OTHER_LDFLAGS = (
+ "-sectcreate",
+ __TEXT,
+ __info_plist,
+ "$(PROJECT_DIR)/tools/lldb-vscode/lldb-vscode-Info.plist",
+ "-Wl,-rpath,@loader_path/",
+ "-filelist",
+ "$(LLVM_BUILD_DIR)/archives.txt",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_SOURCE_DIR)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib/Target/ARM";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+ 26792613211CA3AD00EE1D10 /* BuildAndIntegration */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ COPY_PHASE_STRIP = YES;
+ CURRENT_PROJECT_VERSION = 360.99.0;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ "OTHER_LDFLAGS[sdk=iphoneos*]" = (
+ "-sectcreate",
+ __TEXT,
+ __info_plist,
+ "$(PROJECT_DIR)/tools/lldb-vscode/lldb-vscode-Info.plist",
+ "-Wl,-rpath,@loader_path/../../../System/Library/PrivateFrameworks",
+ "-filelist",
+ "$(LLVM_BUILD_DIR)/archives.txt",
+ );
+ "OTHER_LDFLAGS[sdk=macosx*]" = (
+ "-sectcreate",
+ __TEXT,
+ __info_plist,
+ "$(PROJECT_DIR)/tools/lldb-vscode/lldb-vscode-Info.plist",
+ "-Wl,-rpath,@loader_path/../../Library/PrivateFrameworks/",
+ "-Wl,-rpath,@loader_path/../../../SharedFrameworks",
+ "-Wl,-rpath,@loader_path/../../System/Library/PrivateFrameworks",
+ "-Wl,-rpath,@loader_path/../../Library/PrivateFrameworks",
+ "-filelist",
+ "$(LLVM_BUILD_DIR)/archives.txt",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ STRIP_INSTALLED_PRODUCT = YES;
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_SOURCE_DIR)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/tools/clang/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib/Target/ARM";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = BuildAndIntegration;
+ };
2687EAC71508110B00DD8C2E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -9318,12 +9732,7 @@
"LLDB_VERSION_STRING=lldb-${CURRENT_PROJECT_VERSION}",
);
HEADER_SEARCH_PATHS = /usr/include/libxml2;
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
MACH_O_TYPE = staticlib;
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
@@ -9375,12 +9784,7 @@
"LLDB_VERSION_STRING=lldb-${CURRENT_PROJECT_VERSION}",
);
HEADER_SEARCH_PATHS = /usr/include/libxml2;
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
MACH_O_TYPE = staticlib;
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
@@ -9432,12 +9836,7 @@
"LLDB_VERSION_STRING=lldb-${CURRENT_PROJECT_VERSION}",
);
HEADER_SEARCH_PATHS = /usr/include/libxml2;
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
MACH_O_TYPE = staticlib;
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
@@ -9511,8 +9910,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "-weak-lcompression";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_COVERAGE_CFLAGS = "$(LLDB_COVERAGE_CFLAGS_$(LLDB_ENABLE_COVERAGE))";
LLDB_COVERAGE_CFLAGS_1 = "-fprofile-instr-generate -fcoverage-mapping";
LLDB_COVERAGE_LDFLAGS = "$(LLDB_COVERAGE_LDFLAGS_$(LLDB_ENABLE_COVERAGE))";
@@ -9524,26 +9922,22 @@
"LLDB_FRAMEWORK_INSTALL_DIR[sdk=iphoneos*]" = /System/Library/PrivateFrameworks;
LLDB_TOOLS_INSTALL_DIR = /Applications/Xcode.app/Contents/Developer/usr/bin;
"LLDB_TOOLS_INSTALL_DIR[sdk=iphoneos*]" = /usr/local/bin;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
LLVM_BUILD_DIR = "$(OBJROOT)/llvm";
LLVM_BUILD_DIRTREE = "$(OBJROOT)/llvm-build";
- LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/";
+ LLVM_BUILD_DIR_ARCH = x86_64/;
LLVM_CONFIGURATION = Release;
LLVM_SOURCE_DIR = "$(SRCROOT)/llvm";
OTHER_CFLAGS = (
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_COVERAGE_CFLAGS)",
"-Wimplicit-fallthrough",
"-DNDEBUG",
);
OTHER_LDFLAGS = (
- "$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
+ "-lcompression",
"$(LLDB_COVERAGE_LDFLAGS)",
);
+ "OTHER_LDFLAGS[sdk=macosx*]" = "";
PYTHON_FRAMEWORK_PATH = /System/Library/Frameworks/Python.framework/;
PYTHON_VERSION_MAJOR = 2;
PYTHON_VERSION_MINOR = 7;
@@ -9569,23 +9963,35 @@
INFOPLIST_FILE = "tools/driver/lldb-Info.plist";
INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
+ OTHER_CFLAGS = (
+ "-Wparentheses",
+ "$(LLDB_COVERAGE_CFLAGS)",
+ "-Wimplicit-fallthrough",
+ "-fno-rtti",
+ "-fno-exceptions",
+ "-DNDEBUG",
+ );
"OTHER_LDFLAGS[sdk=iphoneos*]" = (
"$(inherited)",
"-sectcreate",
__TEXT,
__info_plist,
- "-filelist",
- "$(LLVM_BUILD_DIR)/archives.txt",
"$(PROJECT_DIR)/tools/driver/lldb-Info.plist",
"-Wl,-rpath,@loader_path/../../../System/Library/PrivateFrameworks",
+ "-L$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib",
+ "-lLLVMOption",
+ "-lLLVMSupport",
+ "-lLLVMDemangle",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"$(inherited)",
"-sectcreate",
__TEXT,
__info_plist,
- "-filelist",
- "$(LLVM_BUILD_DIR)/archives.txt",
+ "-L$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib",
+ "-lLLVMOption",
+ "-lLLVMSupport",
+ "-lLLVMDemangle",
"$(PROJECT_DIR)/tools/driver/lldb-Info.plist",
"-Wl,-rpath,@loader_path/../../Library/PrivateFrameworks",
"-Wl,-rpath,@loader_path/../../../SharedFrameworks",
@@ -9627,12 +10033,7 @@
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)",
"$(inherited)",
);
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
"-fno-rtti",
@@ -10133,6 +10534,13 @@
INFOPLIST_FILE = "tools/driver/lldb-Info.plist";
INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
+ OTHER_CFLAGS = (
+ "-Wparentheses",
+ "$(LLDB_COVERAGE_CFLAGS)",
+ "-Wimplicit-fallthrough",
+ "-fno-rtti",
+ "-fno-exceptions",
+ );
OTHER_LDFLAGS = (
"$(inherited)",
"-sectcreate",
@@ -10140,8 +10548,10 @@
__info_plist,
"$(PROJECT_DIR)/tools/driver/lldb-Info.plist",
"-Wl,-rpath,@loader_path",
- "-filelist",
- "$(LLVM_BUILD_DIR)/archives.txt",
+ "-L$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib",
+ "-lLLVMOption",
+ "-lLLVMSupport",
+ "-lLLVMDemangle",
);
PRODUCT_NAME = lldb;
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include";
@@ -10163,6 +10573,13 @@
INFOPLIST_FILE = "tools/driver/lldb-Info.plist";
INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
+ OTHER_CFLAGS = (
+ "-Wparentheses",
+ "$(LLDB_COVERAGE_CFLAGS)",
+ "-Wimplicit-fallthrough",
+ "-fno-rtti",
+ "-fno-exceptions",
+ );
OTHER_LDFLAGS = (
"$(inherited)",
"-sectcreate",
@@ -10170,11 +10587,13 @@
__info_plist,
"$(PROJECT_DIR)/tools/driver/lldb-Info.plist",
"-Wl,-rpath,@loader_path",
- "-filelist",
- "$(LLVM_BUILD_DIR)/archives.txt",
+ "-L$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib",
+ "-lLLVMOption",
+ "-lLLVMSupport",
+ "-lLLVMDemangle",
);
PRODUCT_NAME = lldb;
- USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include";
+ USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include ${LLDB_BUILD_DIR}/include";
VERSIONING_SYSTEM = "apple-generic";
};
name = Release;
@@ -10229,8 +10648,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_VALUE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "-weak-lcompression";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_COVERAGE_CFLAGS = "$(LLDB_COVERAGE_CFLAGS_$(LLDB_ENABLE_COVERAGE))";
LLDB_COVERAGE_CFLAGS_1 = "-fprofile-instr-generate -fcoverage-mapping";
LLDB_COVERAGE_LDFLAGS = "$(LLDB_COVERAGE_LDFLAGS_$(LLDB_ENABLE_COVERAGE))";
@@ -10240,24 +10658,19 @@
LLDB_ENABLE_COVERAGE = 0;
LLDB_FRAMEWORK_INSTALL_DIR = /Applications/Xcode.app/Contents/SharedFrameworks;
LLDB_TOOLS_INSTALL_DIR = /usr/bin;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
LLVM_BUILD_DIR = "$(SRCROOT)/llvm-build/$(LLVM_CONFIGURATION)";
LLVM_BUILD_DIRTREE = "$(SRCROOT)/llvm-build";
- LLVM_BUILD_DIR_ARCH = "$(CURRENT_ARCH)/";
+ LLVM_BUILD_DIR_ARCH = x86_64/;
LLVM_CONFIGURATION = "Debug+Asserts";
LLVM_SOURCE_DIR = "$(SRCROOT)/llvm";
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-Wparentheses",
- "$(LLDB_ZLIB_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_COVERAGE_CFLAGS)",
"-Wimplicit-fallthrough",
);
OTHER_LDFLAGS = (
- "$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
+ "-lcompression",
"$(LLDB_COVERAGE_LDFLAGS)",
);
PYTHON_FRAMEWORK_PATH = /System/Library/Frameworks/Python.framework/;
@@ -10310,6 +10723,13 @@
INFOPLIST_FILE = "tools/driver/lldb-Info.plist";
INSTALL_PATH = "$(LLDB_TOOLS_INSTALL_DIR)";
LIBRARY_SEARCH_PATHS = "$(inherited)";
+ OTHER_CFLAGS = (
+ "-Wparentheses",
+ "$(LLDB_COVERAGE_CFLAGS)",
+ "-Wimplicit-fallthrough",
+ "-fno-rtti",
+ "-fno-exceptions",
+ );
OTHER_LDFLAGS = (
"$(inherited)",
"-sectcreate",
@@ -10317,8 +10737,10 @@
__info_plist,
"$(PROJECT_DIR)/tools/driver/lldb-Info.plist",
"-Wl,-rpath,@loader_path",
- "-filelist",
- "$(LLVM_BUILD_DIR)/archives.txt",
+ "-L$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/lib",
+ "-lLLVMOption",
+ "-lLLVMSupport",
+ "-lLLVMDemangle",
);
PRODUCT_NAME = lldb;
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/include $(SRCROOT)/source $(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)/include";
@@ -10353,12 +10775,7 @@
"$(LLVM_BUILD_DIR)/$(LLVM_BUILD_DIR_ARCH)",
"$(inherited)",
);
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
"-fno-rtti",
@@ -10439,12 +10856,7 @@
"LLDB_VERSION_STRING=lldb-${CURRENT_PROJECT_VERSION}",
);
HEADER_SEARCH_PATHS = /usr/include/libxml2;
- LLDB_COMPRESSION_CFLAGS = "";
- "LLDB_COMPRESSION_CFLAGS[sdk=macosx10.11]" = "-DHAVE_LIBCOMPRESSION=1";
- LLDB_COMPRESSION_LDFLAGS = "";
- "LLDB_COMPRESSION_LDFLAGS[sdk=macosx10.11]" = "-weak-lcompression";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
MACH_O_TYPE = staticlib;
OTHER_CPLUSPLUSFLAGS = (
"-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7",
@@ -10928,6 +11340,17 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = BuildAndIntegration;
};
+ 26792614211CA3AD00EE1D10 /* Build configuration list for PBXNativeTarget "lldb-vscode" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 26792610211CA3AD00EE1D10 /* Debug */,
+ 26792611211CA3AD00EE1D10 /* DebugClang */,
+ 26792612211CA3AD00EE1D10 /* Release */,
+ 26792613211CA3AD00EE1D10 /* BuildAndIntegration */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = BuildAndIntegration;
+ };
2687EAC61508110B00DD8C2E /* Build configuration list for PBXLegacyTarget "install-headers" */ = {
isa = XCConfigurationList;
buildConfigurations = (
diff --git a/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme b/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme
index 82a97dfbe24f..881829e27feb 100644
--- a/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme
+++ b/lldb.xcodeproj/xcshareddata/xcschemes/LLDB.xcscheme
@@ -54,7 +54,6 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
displayScaleIsEnabled = "NO"
displayScale = "1.00"
- enableThreadSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/lldb.xcodeproj/xcshareddata/xcschemes/darwin-debug.xcscheme b/lldb.xcodeproj/xcshareddata/xcschemes/darwin-debug.xcscheme
index 352ef7194155..74864b2078d8 100644
--- a/lldb.xcodeproj/xcshareddata/xcschemes/darwin-debug.xcscheme
+++ b/lldb.xcodeproj/xcshareddata/xcschemes/darwin-debug.xcscheme
@@ -45,7 +45,6 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
displayScaleIsEnabled = "NO"
displayScale = "1.00"
- enableThreadSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/packages/Python/lldbsuite/support/encoded_file.py b/packages/Python/lldbsuite/support/encoded_file.py
index 2c2fef383f7f..5c04cce3b3f9 100644
--- a/packages/Python/lldbsuite/support/encoded_file.py
+++ b/packages/Python/lldbsuite/support/encoded_file.py
@@ -31,7 +31,7 @@ def _encoded_write(old_write, encoding):
# If we were asked to write a `str` (in Py2) or a `bytes` (in Py3) decode it
# as unicode before attempting to write.
if isinstance(s, six.binary_type):
- s = s.decode(encoding)
+ s = s.decode(encoding, "replace")
return old_write(s)
return impl
diff --git a/packages/Python/lldbsuite/test/README-TestSuite b/packages/Python/lldbsuite/test/README-TestSuite
index 92649fc9963c..8ea64c0aa3d5 100644
--- a/packages/Python/lldbsuite/test/README-TestSuite
+++ b/packages/Python/lldbsuite/test/README-TestSuite
@@ -1,7 +1,7 @@
-This README file describes the files and directories related to the Python test
-suite under the current 'test' directory.
+This README file describes the files and directories related -*- rst -*-
+to the Python test suite under the current 'test' directory.
-o dotest.py
+- dotest.py
Provides the test driver for the test suite. To invoke it, cd to the 'test'
directory and issue the './dotest.py' command or './dotest.py -v' for more
@@ -20,7 +20,7 @@ o dotest.py
This runs the test suite, with logging turned on for the lldb as well as
the process.gdb-remote channels and directs the run log to a file.
-o lldbtest.py
+- lldbtest.py
Provides an abstract base class of lldb test case named 'TestBase', which in
turn inherits from Python's unittest.TestCase. The concrete subclass can
@@ -41,7 +41,7 @@ o lldbtest.py
test case on its own. To run the whole test suite, 'dotest.py' is all you
need to do.
-o subdirectories of 'test'
+- subdirectories of 'test'
Most of them predate the introduction of the python test suite and contain
example C/C++/ObjC source files which get compiled into executables which are
@@ -58,7 +58,7 @@ o subdirectories of 'test'
testcase that run a process to a breakpoint and check a local variable. These
are convenient starting points for adding new tests.
-o make directory
+- make directory
Contains Makefile.rules, which can be utilized by test cases to write Makefile
based rules to build binaries for the inferiors.
@@ -95,12 +95,12 @@ o make directory
The exe names for the two test methods are equal to the test method names and
are therefore guaranteed different.
-o plugins directory
+- plugins directory
Contains platform specific plugin to build binaries with dsym/dwarf debugging
info. Other platform specific functionalities may be added in the future.
-o unittest2 directory
+- unittest2 directory
Many new features were added to unittest in Python 2.7, including test
discovery. unittest2 allows you to use these features with earlier versions of
@@ -114,7 +114,7 @@ o unittest2 directory
Later versions of unittest2 include changes in unittest made in Python 3.2 and
onwards after the release of Python 2.7.
-o dotest.pl
+- dotest.pl
In case you wonder, there is also a 'dotest.pl' perl script file. It was
created to visit each Python test case under the specified directory and
@@ -127,47 +127,56 @@ o dotest.pl
Note: dotest.pl has been moved to the attic directory.
-o Profiling dotest.py runs
+- Profiling dotest.py runs
I used the following command line thingy to do the profiling on a SnowLeopard
machine:
-$ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log
+ $ DOTEST_PROFILE=YES DOTEST_SCRIPT_DIR=/Volumes/data/lldb/svn/trunk/test /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/cProfile.py -o my.profile ./dotest.py -v -w 2> ~/Developer/Log/lldbtest.log
After that, I used the pstats.py module to browse the statistics:
-$ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile
-
-o Writing test cases:
-
- We strongly prefer writing test cases using the SB API's rather than the runCmd & expect.
- Unless you are actually testing some feature of the command line, please don't write
- command based tests. For historical reasons there are plenty of examples of tests in the
- test suite that use runCmd where they shouldn't, but don't copy them, copy the plenty that
- do use the SB API's instead.
-
- The reason for this is that our policy is that we will maintain compatibility with the
- SB API's. But we don't make any similar guarantee about the details of command result format.
- If your test is using the command line, it is going to have to check against the command result
- text, and you either end up writing your check pattern by checking as little as possible so
- you won't be exposed to random changes in the text; in which case you can end up missing some
- failure, or you test too much and it means irrelevant changes break your tests.
-
- However, if you use the Python API's it is possible to check all the results you want
- to check in a very explicit way, which makes the tests much more robust.
-
- Even if you are testing that a command-line command does some specific thing, it is still
- better in general to use the SB API's to drive to the point where you want to run the test,
- then use SBInterpreter::HandleCommand to run the command. You get the full result text
- from the command in the command return object, and all the part where you are driving the
- debugger to the point you want to test will be more robust.
-
- The sample_test directory contains a standard and an "inline" test that are good starting
- points for writing a new test.
-
-o Attaching in test cases:
-
- If you need to attach to inferiors in your tests, you must make sure the inferior calls
- lldb_enable_attach(), before the debugger attempts to attach. This function performs any
- platform-specific processing needed to enable attaching to this process (e.g., on Linux, we
- execute prctl(PR_SET_TRACER) syscall to disable protections present in some Linux systems).
+ $ python /System/Library/Frameworks/Python.framework/Versions/Current/lib/python2.6/pstats.py my.profile
+
+- Writing test cases:
+
+ We strongly prefer writing test cases using the SB API's rather than
+ the runCmd & expect. Unless you are actually testing some feature
+ of the command line, please don't write command based tests. For
+ historical reasons there are plenty of examples of tests in the test
+ suite that use runCmd where they shouldn't, but don't copy them,
+ copy the plenty that do use the SB API's instead.
+
+ The reason for this is that our policy is that we will maintain
+ compatibility with the SB API's. But we don't make any similar
+ guarantee about the details of command result format. If your test
+ is using the command line, it is going to have to check against the
+ command result text, and you either end up writing your check
+ pattern by checking as little as possible so you won't be exposed to
+ random changes in the text; in which case you can end up missing
+ some failure, or you test too much and it means irrelevant changes
+ break your tests.
+
+ However, if you use the Python API's it is possible to check all the
+ results you want to check in a very explicit way, which makes the
+ tests much more robust.
+
+ Even if you are testing that a command-line command does some
+ specific thing, it is still better in general to use the SB API's to
+ drive to the point where you want to run the test, then use
+ SBInterpreter::HandleCommand to run the command. You get the full
+ result text from the command in the command return object, and all
+ the part where you are driving the debugger to the point you want to
+ test will be more robust.
+
+ The sample_test directory contains a standard and an "inline" test
+ that are good starting points for writing a new test.
+
+- Attaching in test cases:
+
+ If you need to attach to inferiors in your tests, you must make sure
+ the inferior calls lldb_enable_attach(), before the debugger
+ attempts to attach. This function performs any platform-specific
+ processing needed to enable attaching to this process (e.g., on
+ Linux, we execute prctl(PR_SET_TRACER) syscall to disable
+ protections present in some Linux systems).
diff --git a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
index dd03fcf31e87..d91eec1fd51b 100644
--- a/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
+++ b/packages/Python/lldbsuite/test/api/multithreaded/TestMultithreaded.py
@@ -68,7 +68,7 @@ class SBBreakpointCallbackCase(TestBase):
# clang-cl does not support throw or catch (llvm.org/pr24538)
@skipIfWindows
@expectedFlakeyFreeBSD
- @expectedFailureAll(oslist=["linux"])
+ @skipIf(oslist=["linux"]) # flakey
def test_sb_api_listener_resume(self):
""" Test that a process can be resumed from a non-main thread. """
self.build_and_test(
diff --git a/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py b/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py
index 30510638f096..e9dbe670dc0b 100644
--- a/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py
+++ b/packages/Python/lldbsuite/test/arm/breakpoint-it/TestBreakpointIt.py
@@ -19,6 +19,7 @@ class TestBreakpointIt(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipIf(archs=no_match(["arm"]))
+ @skipIf(archs=["arm64", "arm64e"])
def test_false(self):
self.build()
exe = self.getBuildArtifact("a.out")
@@ -32,6 +33,7 @@ class TestBreakpointIt(TestBase):
"Breakpoint does not get hit")
@skipIf(archs=no_match(["arm"]))
+ @skipIf(archs=["arm64", "arm64e"])
def test_true(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py
deleted file mode 100644
index 8bce4815894d..000000000000
--- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDisassembly.py
+++ /dev/null
@@ -1,165 +0,0 @@
-"""Disassemble lldb's Driver::MainLoop() functions comparing lldb against gdb."""
-
-from __future__ import print_function
-
-
-import os
-import sys
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbbench import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-def is_exe(fpath):
- """Returns true if fpath is an executable."""
- return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
-
-
-class DisassembleDriverMainLoop(BenchBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- """
- Note that lldbtest_config.lldbExec can be specified with the LLDB_EXEC env variable (see
- dotest.py), and gdbExec can be specified with the GDB_EXEC env variable.
- This provides a flexibility in specifying different versions of gdb for
- comparison purposes.
- """
- BenchBase.setUp(self)
- # If env var GDB_EXEC is specified, use it; otherwise, use gdb in your
- # PATH env var.
- if "GDB_EXEC" in os.environ and is_exe(os.environ["GDB_EXEC"]):
- self.gdbExec = os.environ["GDB_EXEC"]
- else:
- self.gdbExec = "gdb"
-
- self.exe = lldbtest_config.lldbExec
- self.function = 'Driver::MainLoop()'
- self.lldb_avg = None
- self.gdb_avg = None
- self.count = 5
-
- @benchmarks_test
- @no_debug_info_test
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_run_lldb_then_gdb(self):
- """Test disassembly on a large function with lldb vs. gdb."""
- print()
- print("lldb path: %s" % lldbtest_config.lldbExec)
- print("gdb path: %s" % self.gdbExec)
-
- print()
- self.run_lldb_disassembly(self.exe, self.function, self.count)
- print("lldb benchmark:", self.stopwatch)
- self.run_gdb_disassembly(self.exe, self.function, self.count)
- print("gdb benchmark:", self.stopwatch)
- print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg))
-
- @benchmarks_test
- @no_debug_info_test
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_run_gdb_then_lldb(self):
- """Test disassembly on a large function with lldb vs. gdb."""
- print()
- print("lldb path: %s" % lldbtest_config.lldbExec)
- print("gdb path: %s" % self.gdbExec)
-
- print()
- self.run_gdb_disassembly(self.exe, self.function, self.count)
- print("gdb benchmark:", self.stopwatch)
- self.run_lldb_disassembly(self.exe, self.function, self.count)
- print("lldb benchmark:", self.stopwatch)
- print("lldb_avg/gdb_avg: %f" % (self.lldb_avg / self.gdb_avg))
-
- def run_lldb_disassembly(self, exe, function, count):
- import pexpect
- # Set self.child_prompt, which is "(lldb) ".
- self.child_prompt = '(lldb) '
- prompt = self.child_prompt
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn(
- '%s %s %s' %
- (lldbtest_config.lldbExec, self.lldbOption, exe))
- child = self.child
-
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- child.expect_exact(prompt)
- child.sendline('breakpoint set -F %s' % function)
- child.expect_exact(prompt)
- child.sendline('run')
- child.expect_exact(prompt)
-
- # Reset the stopwatch now.
- self.stopwatch.reset()
- for i in range(count):
- with self.stopwatch:
- # Disassemble the function.
- child.sendline('disassemble -f')
- child.expect_exact(prompt)
- child.sendline('next')
- child.expect_exact(prompt)
-
- child.sendline('quit')
- try:
- self.child.expect(pexpect.EOF)
- except:
- pass
-
- self.lldb_avg = self.stopwatch.avg()
- if self.TraceOn():
- print("lldb disassembly benchmark:", str(self.stopwatch))
- self.child = None
-
- def run_gdb_disassembly(self, exe, function, count):
- import pexpect
- # Set self.child_prompt, which is "(gdb) ".
- self.child_prompt = '(gdb) '
- prompt = self.child_prompt
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn('%s --nx %s' % (self.gdbExec, exe))
- child = self.child
-
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- child.expect_exact(prompt)
- child.sendline('break %s' % function)
- child.expect_exact(prompt)
- child.sendline('run')
- child.expect_exact(prompt)
-
- # Reset the stopwatch now.
- self.stopwatch.reset()
- for i in range(count):
- with self.stopwatch:
- # Disassemble the function.
- child.sendline('disassemble')
- child.expect_exact(prompt)
- child.sendline('next')
- child.expect_exact(prompt)
-
- child.sendline('quit')
- child.expect_exact('The program is running. Exit anyway?')
- child.sendline('y')
- try:
- self.child.expect(pexpect.EOF)
- except:
- pass
-
- self.gdb_avg = self.stopwatch.avg()
- if self.TraceOn():
- print("gdb disassembly benchmark:", str(self.stopwatch))
- self.child = None
diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py
deleted file mode 100644
index 36f23572648d..000000000000
--- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestDoAttachThenDisassembly.py
+++ /dev/null
@@ -1,70 +0,0 @@
-"""Test lldb's disassemblt speed. This bench deliberately attaches to an lldb
-inferior and traverses the stack for thread0 to arrive at frame with function
-'MainLoop'. It is important to specify an lldb executable as the inferior."""
-
-from __future__ import print_function
-
-
-import os
-import sys
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbbench import *
-from lldbsuite.test.lldbtest import *
-
-
-class AttachThenDisassemblyBench(BenchBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- BenchBase.setUp(self)
- self.exe = lldbtest_config.lldbExec
- self.count = 10
-
- @benchmarks_test
- @no_debug_info_test
- def test_attach_then_disassembly(self):
- """Attach to a spawned lldb process then run disassembly benchmarks."""
- print()
- self.run_lldb_attach_then_disassembly(self.exe, self.count)
- print("lldb disassembly benchmark:", self.stopwatch)
-
- def run_lldb_attach_then_disassembly(self, exe, count):
- target = self.dbg.CreateTarget(exe)
-
- # Spawn a new process and don't display the stdout if not in TraceOn()
- # mode.
- import subprocess
- popen = subprocess.Popen([exe, self.lldbOption], stdout=open(
- os.devnull, 'w') if not self.TraceOn() else None)
- if self.TraceOn():
- print("pid of spawned process: %d" % popen.pid)
-
- # Attach to the launched lldb process.
- listener = lldb.SBListener("my.attach.listener")
- error = lldb.SBError()
- process = target.AttachToProcessWithID(listener, popen.pid, error)
-
- # Set thread0 as the selected thread, followed by the 'MainLoop' frame
- # as the selected frame. Then do disassembly on the function.
- thread0 = process.GetThreadAtIndex(0)
- process.SetSelectedThread(thread0)
- i = 0
- found = False
- for f in thread0:
- # print("frame#%d %s" % (i, f.GetFunctionName()))
- if "MainLoop" in f.GetFunctionName():
- found = True
- thread0.SetSelectedFrame(i)
- if self.TraceOn():
- print("Found frame#%d for function 'MainLoop'" % i)
- break
- i += 1
-
- # Reset the stopwatch now.
- self.stopwatch.reset()
- for i in range(count):
- with self.stopwatch:
- # Disassemble the function.
- self.runCmd("disassemble -f")
diff --git a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py b/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py
deleted file mode 100644
index fd91bb441d9f..000000000000
--- a/packages/Python/lldbsuite/test/benchmarks/disassembly/TestXcode41Vs42GDBDisassembly.py
+++ /dev/null
@@ -1,120 +0,0 @@
-"""Disassemble lldb's Driver::MainLoop() functions comparing Xcode 4.1 vs. 4.2's gdb."""
-
-from __future__ import print_function
-
-
-import os
-import sys
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbbench import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import configuration
-from lldbsuite.test import lldbutil
-
-
-class XCode41Vs42GDBDisassembly(BenchBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- BenchBase.setUp(self)
- self.gdb_41_exe = '/Xcode41/usr/bin/gdb'
- self.gdb_42_exe = '/Developer/usr/bin/gdb'
- self.exe = lldbtest_config.lldbExec
- self.function = 'Driver::MainLoop()'
- self.gdb_41_avg = None
- self.gdb_42_avg = None
- self.count = 5
-
- @benchmarks_test
- @no_debug_info_test
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_run_41_then_42(self):
- """Test disassembly on a large function with 4.1 vs. 4.2's gdb."""
- print()
- self.run_gdb_disassembly(
- self.gdb_41_exe,
- self.exe,
- self.function,
- self.count)
- print("4.1 gdb benchmark:", self.stopwatch)
- self.gdb_41_avg = self.stopwatch.avg()
- self.run_gdb_disassembly(
- self.gdb_42_exe,
- self.exe,
- self.function,
- self.count)
- print("4.2 gdb benchmark:", self.stopwatch)
- self.gdb_42_avg = self.stopwatch.avg()
- print("gdb_42_avg/gdb_41_avg: %f" %
- (self.gdb_42_avg / self.gdb_41_avg))
-
- @benchmarks_test
- @no_debug_info_test
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_run_42_then_41(self):
- """Test disassembly on a large function with 4.1 vs. 4.2's gdb."""
- print()
- self.run_gdb_disassembly(
- self.gdb_42_exe,
- self.exe,
- self.function,
- self.count)
- print("4.2 gdb benchmark:", self.stopwatch)
- self.gdb_42_avg = self.stopwatch.avg()
- self.run_gdb_disassembly(
- self.gdb_41_exe,
- self.exe,
- self.function,
- self.count)
- print("4.1 gdb benchmark:", self.stopwatch)
- self.gdb_41_avg = self.stopwatch.avg()
- print("gdb_42_avg/gdb_41_avg: %f" %
- (self.gdb_42_avg / self.gdb_41_avg))
-
- def run_gdb_disassembly(self, gdb_exe_path, exe, function, count):
- import pexpect
- # Set self.child_prompt, which is "(gdb) ".
- self.child_prompt = '(gdb) '
- prompt = self.child_prompt
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn('%s --nx %s' % (gdb_exe_path, exe))
- child = self.child
-
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- child.expect_exact(prompt)
- child.sendline('break %s' % function)
- child.expect_exact(prompt)
- child.sendline('run')
- child.expect_exact(prompt)
-
- # Reset the stopwatch now.
- self.stopwatch.reset()
- for i in range(count):
- with self.stopwatch:
- # Disassemble the function.
- child.sendline('disassemble')
- child.expect_exact(prompt)
- child.sendline('next')
- child.expect_exact(prompt)
-
- child.sendline('quit')
- child.expect_exact('The program is running. Exit anyway?')
- child.sendline('y')
- try:
- self.child.expect(pexpect.EOF)
- except:
- pass
-
- if self.TraceOn():
- print("gdb disassembly benchmark:", str(self.stopwatch))
- self.child = None
diff --git a/packages/Python/lldbsuite/test/configuration.py b/packages/Python/lldbsuite/test/configuration.py
index 94781050dc4b..a7f4ac7efe2b 100644
--- a/packages/Python/lldbsuite/test/configuration.py
+++ b/packages/Python/lldbsuite/test/configuration.py
@@ -46,6 +46,9 @@ count = 1
arch = None # Must be initialized after option parsing
compiler = None # Must be initialized after option parsing
+# Path to the FileCheck testing tool. Not optional.
+filecheck = None
+
# The arch might dictate some specific CFLAGS to be passed to the toolchain to build
# the inferior programs. The global variable cflags_extras provides a hook to do
# just that.
@@ -110,9 +113,13 @@ lldb_platform_working_dir = None
# The base directory in which the tests are being built.
test_build_dir = None
+# The only directory to scan for tests. If multiple test directories are
+# specified, and an exclusive test subdirectory is specified, the latter option
+# takes precedence.
+exclusive_test_subdir = None
+
# Parallel execution settings
is_inferior_test_runner = False
-multiprocess_test_subdir = None
num_threads = None
no_multiprocess_test_runner = False
test_runner_name = None
@@ -144,3 +151,42 @@ def shouldSkipBecauseOfCategories(test_categories):
return True
return False
+
+
+def get_absolute_path_to_exclusive_test_subdir():
+ """
+ If an exclusive test subdirectory is specified, return its absolute path.
+ Otherwise return None.
+ """
+ test_directory = os.path.dirname(os.path.realpath(__file__))
+
+ if not exclusive_test_subdir:
+ return
+
+ if len(exclusive_test_subdir) > 0:
+ test_subdir = os.path.join(test_directory, exclusive_test_subdir)
+ if os.path.isdir(test_subdir):
+ return test_subdir
+
+ print('specified test subdirectory {} is not a valid directory\n'
+ .format(test_subdir))
+
+
+def get_absolute_path_to_root_test_dir():
+ """
+ If an exclusive test subdirectory is specified, return its absolute path.
+ Otherwise, return the absolute path of the root test directory.
+ """
+ test_subdir = get_absolute_path_to_exclusive_test_subdir()
+ if test_subdir:
+ return test_subdir
+
+ return os.path.dirname(os.path.realpath(__file__))
+
+
+def get_filecheck_path():
+ """
+ Get the path to the FileCheck testing tool.
+ """
+ if filecheck and os.path.lexists(filecheck):
+ return filecheck
diff --git a/packages/Python/lldbsuite/test/decorators.py b/packages/Python/lldbsuite/test/decorators.py
index 8b33cad3d1ba..2458a6f8745e 100644
--- a/packages/Python/lldbsuite/test/decorators.py
+++ b/packages/Python/lldbsuite/test/decorators.py
@@ -74,13 +74,14 @@ def _check_expected_version(comparison, expected, actual):
LooseVersion(expected_str))
+_re_pattern_type = type(re.compile(''))
def _match_decorator_property(expected, actual):
if actual is None or expected is None:
return True
if isinstance(expected, no_match):
return not _match_decorator_property(expected.item, actual)
- elif isinstance(expected, (re._pattern_type,) + six.string_types):
+ elif isinstance(expected, (_re_pattern_type,) + six.string_types):
return re.search(expected, actual) is not None
elif hasattr(expected, "__iter__"):
return any([x is not None and _match_decorator_property(x, actual)
@@ -192,10 +193,10 @@ def _decorateTest(mode,
py_version is None) or _check_expected_version(
py_version[0], py_version[1], sys.version_info)
skip_for_macos_version = (macos_version is None) or (
- _check_expected_version(
+ (platform.mac_ver()[0] != "") and (_check_expected_version(
macos_version[0],
macos_version[1],
- platform.mac_ver()[0]))
+ platform.mac_ver()[0])))
# For the test to be skipped, all specified (e.g. not None) parameters must be True.
# An unspecified parameter means "any", so those are marked skip by default. And we skip
@@ -457,12 +458,6 @@ def expectedFlakey(expected_fn, bugnumber=None):
return expectedFailure_impl
-def expectedFlakeyDsym(bugnumber=None):
- def fn(self):
- return self.getDebugInfo() == "dwarf"
- return expectedFlakey(fn, bugnumber)
-
-
def expectedFlakeyOS(oslist, bugnumber=None, compilers=None):
def fn(self):
return (self.getPlatform() in oslist and
@@ -600,28 +595,6 @@ def skipUnlessDarwin(func):
return skipUnlessPlatform(lldbplatformutil.getDarwinOSTriples())(func)
-def skipUnlessGoInstalled(func):
- """Decorate the item to skip tests when no Go compiler is available."""
-
- def is_go_missing(self):
- compiler = self.getGoCompilerVersion()
- if not compiler:
- return "skipping because go compiler not found"
- match_version = re.search(r"(\d+\.\d+(\.\d+)?)", compiler)
- if not match_version:
- # Couldn't determine version.
- return "skipping because go version could not be parsed out of {}".format(
- compiler)
- else:
- min_strict_version = StrictVersion("1.4.0")
- compiler_strict_version = StrictVersion(match_version.group(1))
- if compiler_strict_version < min_strict_version:
- return "skipping because available version ({}) does not meet minimum required version ({})".format(
- compiler_strict_version, min_strict_version)
- return None
- return skipTestIfFn(is_go_missing)(func)
-
-
def skipIfHostIncompatibleWithRemote(func):
"""Decorate the item to skip tests if binaries built on this host are incompatible."""
@@ -687,6 +660,30 @@ def skipUnlessSupportedTypeAttribute(attr):
return None
return skipTestIfFn(compiler_doesnt_support_struct_attribute)
+def skipUnlessHasCallSiteInfo(func):
+ """Decorate the function to skip testing unless call site info from clang is available."""
+
+ def is_compiler_clang_with_call_site_info(self):
+ compiler_path = self.getCompiler()
+ compiler = os.path.basename(compiler_path)
+ if not compiler.startswith("clang"):
+ return "Test requires clang as compiler"
+
+ f = tempfile.NamedTemporaryFile()
+ cmd = "echo 'int main() {}' | " \
+ "%s -g -glldb -O1 -S -emit-llvm -x c -o %s -" % (compiler_path, f.name)
+ if os.popen(cmd).close() is not None:
+ return "Compiler can't compile with call site info enabled"
+
+ with open(f.name, 'r') as ir_output_file:
+ buf = ir_output_file.read()
+
+ if 'DIFlagAllCallsDescribed' not in buf:
+ return "Compiler did not introduce DIFlagAllCallsDescribed IR flag"
+
+ return None
+ return skipTestIfFn(is_compiler_clang_with_call_site_info)(func)
+
def skipUnlessThreadSanitizer(func):
"""Decorate the item to skip test unless Clang -fsanitize=thread is supported."""
@@ -810,3 +807,10 @@ def skipUnlessFeature(feature):
except subprocess.CalledProcessError:
return "%s is not supported on this system." % feature
return skipTestIfFn(is_feature_enabled)
+
+def skipIfSanitized(func):
+ """Skip this test if the environment is set up to run LLDB itself under ASAN."""
+ def is_sanitized():
+ return (('DYLD_INSERT_LIBRARIES' in os.environ) and
+ 'libclang_rt.asan' in os.environ['DYLD_INSERT_LIBRARIES'])
+ return skipTestIfFn(is_sanitized)(func)
diff --git a/packages/Python/lldbsuite/test/dosep.py b/packages/Python/lldbsuite/test/dosep.py
index 616fbf381edf..21010c28a78c 100644
--- a/packages/Python/lldbsuite/test/dosep.py
+++ b/packages/Python/lldbsuite/test/dosep.py
@@ -1558,7 +1558,7 @@ def rerun_tests(test_subdir, tests_for_rerun, dotest_argv, session_dir,
print("\nTest rerun complete\n")
-def main(num_threads, test_subdir, test_runner_name, results_formatter):
+def main(num_threads, test_runner_name, results_formatter):
"""Run dotest.py in inferior mode in parallel.
@param num_threads the parsed value of the num-threads command line
@@ -1600,16 +1600,7 @@ def main(num_threads, test_subdir, test_runner_name, results_formatter):
session_dir = os.path.join(os.getcwd(), dotest_options.s)
- # The root directory was specified on the command line
- test_directory = os.path.dirname(os.path.realpath(__file__))
- if test_subdir and len(test_subdir) > 0:
- test_subdir = os.path.join(test_directory, test_subdir)
- if not os.path.isdir(test_subdir):
- print(
- 'specified test subdirectory {} is not a valid directory\n'
- .format(test_subdir))
- else:
- test_subdir = test_directory
+ test_subdir = configuration.get_absolute_path_to_root_test_dir()
# clean core files in test tree from previous runs (Linux)
cores = find('core.*', test_subdir)
@@ -1698,7 +1689,7 @@ def main(num_threads, test_subdir, test_runner_name, results_formatter):
# move core files into session dir
cores = find('core.*', test_subdir)
for core in cores:
- dst = core.replace(test_directory, "")[1:]
+ dst = core.replace(test_subdir, "")[1:]
dst = dst.replace(os.path.sep, "-")
os.rename(core, os.path.join(session_dir, dst))
diff --git a/packages/Python/lldbsuite/test/dotest.py b/packages/Python/lldbsuite/test/dotest.py
index d28c5ef069b7..644f63576c06 100644
--- a/packages/Python/lldbsuite/test/dotest.py
+++ b/packages/Python/lldbsuite/test/dotest.py
@@ -307,6 +307,24 @@ def parseOptionsAndInitTestdirs():
os.environ['DSYMUTIL'] = seven.get_command_output(
'xcrun -find -toolchain default dsymutil')
+ if args.filecheck:
+ # The lldb-dotest script produced by the CMake build passes in a path
+ # to a working FileCheck binary. So does one specific Xcode project
+ # target. However, when invoking dotest.py directly, a valid --filecheck
+ # option needs to be given.
+ configuration.filecheck = os.path.abspath(args.filecheck)
+ else:
+ outputPaths = get_llvm_bin_dirs()
+ for outputPath in outputPaths:
+ candidatePath = os.path.join(outputPath, 'FileCheck')
+ if is_exe(candidatePath):
+ configuration.filecheck = candidatePath
+ break
+
+ if not configuration.get_filecheck_path():
+ logging.warning('No valid FileCheck executable; some tests may fail...')
+ logging.warning('(Double-check the --filecheck argument to dotest.py)')
+
if args.channels:
lldbtest_config.channels = args.channels
@@ -439,7 +457,7 @@ def parseOptionsAndInitTestdirs():
configuration.num_threads = args.num_threads
if args.test_subdir:
- configuration.multiprocess_test_subdir = args.test_subdir
+ configuration.exclusive_test_subdir = args.test_subdir
if args.test_runner_name:
configuration.test_runner_name = args.test_runner_name
@@ -616,6 +634,31 @@ def getOutputPaths(lldbRootDirectory):
return result
+def get_llvm_bin_dirs():
+ """
+ Returns an array of paths that may have the llvm/clang/etc binaries
+ in them, relative to this current file.
+ Returns an empty array if none are found.
+ """
+ result = []
+
+ lldb_root_path = os.path.join(
+ os.path.dirname(__file__), "..", "..", "..", "..")
+ paths_to_try = [
+ "llvm-build/Release+Asserts/x86_64/bin",
+ "llvm-build/Debug+Asserts/x86_64/bin",
+ "llvm-build/Release/x86_64/bin",
+ "llvm-build/Debug/x86_64/bin",
+ "llvm-build/Ninja-DebugAssert/llvm-macosx-x86_64/bin",
+ "llvm-build/Ninja-ReleaseAssert/llvm-macosx-x86_64/bin",
+ "llvm-build/Ninja-RelWithDebInfoAssert/llvm-macosx-x86_64/bin",
+ ]
+ for p in paths_to_try:
+ path = os.path.join(lldb_root_path, p)
+ if os.path.exists(path):
+ result.append(path)
+
+ return result
def setupSysPath():
"""
@@ -646,6 +689,7 @@ def setupSysPath():
pluginPath = os.path.join(scriptPath, 'plugins')
toolsLLDBMIPath = os.path.join(scriptPath, 'tools', 'lldb-mi')
+ toolsLLDBVSCode = os.path.join(scriptPath, 'tools', 'lldb-vscode')
toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
# Insert script dir, plugin dir, lldb-mi dir and lldb-server dir to the
@@ -654,6 +698,9 @@ def setupSysPath():
# Adding test/tools/lldb-mi to the path makes it easy
sys.path.insert(0, toolsLLDBMIPath)
# to "import lldbmi_testcase" from the MI tests
+ # Adding test/tools/lldb-vscode to the path makes it easy to
+ # "import lldb_vscode_testcase" from the VSCode tests
+ sys.path.insert(0, toolsLLDBVSCode)
# Adding test/tools/lldb-server to the path makes it easy
sys.path.insert(0, toolsLLDBServerPath)
# to "import lldbgdbserverutils" from the lldb-server tests
@@ -723,6 +770,15 @@ def setupSysPath():
"The 'lldb-mi' executable cannot be located. The lldb-mi tests can not be run as a result.")
configuration.skipCategories.append("lldb-mi")
+ lldbVSCodeExec = os.path.join(lldbDir, "lldb-vscode")
+ if is_exe(lldbVSCodeExec):
+ os.environ["LLDBVSCODE_EXEC"] = lldbVSCodeExec
+ else:
+ if not configuration.shouldSkipBecauseOfCategories(["lldb-vscode"]):
+ print(
+ "The 'lldb-vscode' executable cannot be located. The lldb-vscode tests can not be run as a result.")
+ configuration.skipCategories.append("lldb-vscode")
+
lldbPythonDir = None # The directory that contains 'lldb/__init__.py'
if not configuration.lldbFrameworkPath and os.path.exists(os.path.join(lldbLibDir, "LLDB.framework")):
configuration.lldbFrameworkPath = os.path.join(lldbLibDir, "LLDB.framework")
@@ -882,6 +938,7 @@ def visit_file(dir, name):
unittest2.defaultTestLoader.loadTestsFromName(base))
+# TODO: This should be replaced with a call to find_test_files_in_dir_tree.
def visit(prefix, dir, names):
"""Visitor function for os.path.walk(path, visit, arg)."""
@@ -1004,14 +1061,15 @@ def getMyCommandLine():
def checkDsymForUUIDIsNotOn():
cmd = ["defaults", "read", "com.apple.DebugSymbols"]
- pipe = subprocess.Popen(
+ process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
- cmd_output = pipe.stdout.read()
- if cmd_output and "DBGFileMappedPaths = " in cmd_output:
+ cmd_output = process.stdout.read()
+ output_str = cmd_output.decode("utf-8")
+ if "DBGFileMappedPaths = " in output_str:
print("%s =>" % ' '.join(cmd))
- print(cmd_output)
+ print(output_str)
print(
"Disable automatic lookup and caching of dSYMs before running the test suite!")
print("Exiting...")
@@ -1159,7 +1217,6 @@ def run_suite():
from . import dosep
dosep.main(
configuration.num_threads,
- configuration.multiprocess_test_subdir,
configuration.test_runner_name,
configuration.results_formatter_object)
raise Exception("should never get here")
@@ -1254,10 +1311,15 @@ def run_suite():
# Don't do lldb-server (llgs) tests on anything except Linux.
configuration.dont_do_llgs_test = not ("linux" in target_platform)
- #
- # Walk through the testdirs while collecting tests.
- #
- for testdir in configuration.testdirs:
+ # Collect tests from the specified testing directories. If a test
+ # subdirectory filter is explicitly specified, limit the search to that
+ # subdirectory.
+ exclusive_test_subdir = configuration.get_absolute_path_to_exclusive_test_subdir()
+ if exclusive_test_subdir:
+ dirs_to_search = [exclusive_test_subdir]
+ else:
+ dirs_to_search = configuration.testdirs
+ for testdir in dirs_to_search:
for (dirpath, dirnames, filenames) in os.walk(testdir):
visit('Test', dirpath, filenames)
diff --git a/packages/Python/lldbsuite/test/dotest_args.py b/packages/Python/lldbsuite/test/dotest_args.py
index 58190d8c75ee..225ccf1181cc 100644
--- a/packages/Python/lldbsuite/test/dotest_args.py
+++ b/packages/Python/lldbsuite/test/dotest_args.py
@@ -85,6 +85,8 @@ def create_parser():
group.add_argument('--dsymutil', metavar='dsymutil', dest='dsymutil', help=textwrap.dedent('Specify which dsymutil to use.'))
+ group.add_argument('--filecheck', metavar='filecheck', dest='filecheck', help=textwrap.dedent('Specify which FileCheck binary to use.'))
+
# Test filtering options
group = parser.add_argument_group('Test filtering options')
group.add_argument(
diff --git a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py
index 6a8fb5db5439..1108b1215329 100644
--- a/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py
+++ b/packages/Python/lldbsuite/test/expression_command/anonymous-struct/TestCallUserAnonTypedef.py
@@ -23,7 +23,6 @@ class TestExprLookupAnonStructTypedef(TestBase):
# Find the breakpoint
self.line = line_number('main.cpp', '// lldb testsuite break')
- @expectedFailureAll(oslist=["windows"])
@expectedFailureAll(
oslist=['linux'],
archs=['arm'],
diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py
new file mode 100644
index 000000000000..87787f3479a2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallBuiltinFunction.py
@@ -0,0 +1,53 @@
+"""
+Tests calling builtin functions using expression evaluation.
+"""
+
+from __future__ import print_function
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ExprCommandCallBuiltinFunction(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ # Builtins are expanded by Clang, so debug info shouldn't matter.
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ # Find the line number to break for main.c.
+ self.line = line_number(
+ 'main.cpp',
+ '// Please test these expressions while stopped at this line:')
+
+ def test(self):
+ self.build()
+
+ # Set breakpoint in main and run exe
+ self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
+ lldbutil.run_break_set_by_file_and_line(
+ self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+
+ # Test different builtin functions.
+
+ interp.HandleCommand("expr __builtin_isinf(0.0f)", result)
+ self.assertEqual(result.GetOutput(), "(int) $0 = 0\n")
+
+ interp.HandleCommand("expr __builtin_isnormal(0.0f)", result)
+ self.assertEqual(result.GetOutput(), "(int) $1 = 0\n")
+
+ interp.HandleCommand("expr __builtin_constant_p(1)", result)
+ self.assertEqual(result.GetOutput(), "(int) $2 = 1\n")
+
+ interp.HandleCommand("expr __builtin_abs(-14)", result)
+ self.assertEqual(result.GetOutput(), "(int) $3 = 14\n")
diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py
index 63511779a927..d832983bdb64 100644
--- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py
+++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallStopAndContinue.py
@@ -6,7 +6,6 @@ from __future__ import print_function
import lldb
-from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
@@ -24,10 +23,6 @@ class ExprCommandCallStopContinueTestCase(TestBase):
'// Please test these expressions while stopped at this line:')
self.func_line = line_number('main.cpp', '{5, "five"}')
- @expectedFlakeyDarwin("llvm.org/pr20274")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test(self):
"""Test gathering result from interrupted function call."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py
index ff3bd99ced99..0eb7086b6160 100644
--- a/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py
+++ b/packages/Python/lldbsuite/test/expression_command/call-function/TestCallUserDefinedFunction.py
@@ -28,10 +28,6 @@ class ExprCommandCallUserDefinedFunction(TestBase):
'main.cpp',
'// Please test these expressions while stopped at this line:')
- @expectedFlakeyDsym("llvm.org/pr20274")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test(self):
"""Test return values of user defined function calls."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py
index b328ece6d39c..a9679b7dd368 100644
--- a/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py
+++ b/packages/Python/lldbsuite/test/expression_command/char/TestExprsChar.py
@@ -41,7 +41,6 @@ class ExprCharTestCase(TestBase):
self.assertTrue(value.GetError().Success())
self.assertEqual(value.GetValueAsSigned(0), 3)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_default_char(self):
self.do_test()
@@ -52,7 +51,6 @@ class ExprCharTestCase(TestBase):
"powerpc64le",
"s390x"],
bugnumber="llvm.org/pr23069")
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_signed_char(self):
self.do_test(dictionary={'CFLAGS_EXTRAS': '-fsigned-char'})
@@ -64,7 +62,6 @@ class ExprCharTestCase(TestBase):
'armv7',
'armv7k'],
bugnumber="llvm.org/pr23069, <rdar://problem/28721938>")
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
@expectedFailureAll(triple='mips*', bugnumber="llvm.org/pr23069")
def test_unsigned_char(self):
self.do_test(dictionary={'CFLAGS_EXTRAS': '-funsigned-char'})
diff --git a/packages/Python/lldbsuite/test/expression_command/completion/.categories b/packages/Python/lldbsuite/test/expression_command/completion/.categories
new file mode 100644
index 000000000000..3a3f4df6416b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/completion/.categories
@@ -0,0 +1 @@
+cmdline
diff --git a/packages/Python/lldbsuite/test/expression_command/completion/Makefile b/packages/Python/lldbsuite/test/expression_command/completion/Makefile
new file mode 100644
index 000000000000..6fc26a9193f0
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/completion/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp other.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py b/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py
new file mode 100644
index 000000000000..536b9e0abcdd
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py
@@ -0,0 +1,257 @@
+"""
+Test the lldb command line completion mechanism for the 'expr' command.
+"""
+
+from __future__ import print_function
+
+import random
+import os
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbplatform
+from lldbsuite.test import lldbutil
+
+class CommandLineExprCompletionTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_expr_completion(self):
+ self.build()
+ self.main_source = "main.cpp"
+ self.main_source_spec = lldb.SBFileSpec(self.main_source)
+ self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+
+ # Try the completion before we have a context to complete on.
+ self.assume_no_completions('expr some_expr')
+ self.assume_no_completions('expr ')
+ self.assume_no_completions('expr f')
+
+
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ '// Break here', self.main_source_spec)
+
+ # Completing member functions
+ self.complete_exactly('expr some_expr.FooNoArgs',
+ 'expr some_expr.FooNoArgsBar()')
+ self.complete_exactly('expr some_expr.FooWithArgs',
+ 'expr some_expr.FooWithArgsBar(')
+ self.complete_exactly('expr some_expr.FooWithMultipleArgs',
+ 'expr some_expr.FooWithMultipleArgsBar(')
+ self.complete_exactly('expr some_expr.FooUnderscore',
+ 'expr some_expr.FooUnderscoreBar_()')
+ self.complete_exactly('expr some_expr.FooNumbers',
+ 'expr some_expr.FooNumbersBar1()')
+ self.complete_exactly('expr some_expr.StaticMemberMethod',
+ 'expr some_expr.StaticMemberMethodBar()')
+
+ # Completing static functions
+ self.complete_exactly('expr Expr::StaticMemberMethod',
+ 'expr Expr::StaticMemberMethodBar()')
+
+ # Completing member variables
+ self.complete_exactly('expr some_expr.MemberVariab',
+ 'expr some_expr.MemberVariableBar')
+
+ # Multiple completions
+ self.completions_contain('expr some_expr.',
+ ['some_expr.FooNumbersBar1()',
+ 'some_expr.FooUnderscoreBar_()',
+ 'some_expr.FooWithArgsBar(',
+ 'some_expr.MemberVariableBar'])
+
+ self.completions_contain('expr some_expr.Foo',
+ ['some_expr.FooNumbersBar1()',
+ 'some_expr.FooUnderscoreBar_()',
+ 'some_expr.FooWithArgsBar('])
+
+ self.completions_contain('expr ',
+ ['static_cast',
+ 'reinterpret_cast',
+ 'dynamic_cast'])
+
+ self.completions_contain('expr 1 + ',
+ ['static_cast',
+ 'reinterpret_cast',
+ 'dynamic_cast'])
+
+ # Completion expr without spaces
+ # This is a bit awkward looking for the user, but that's how
+ # the completion API works at the moment.
+ self.completions_contain('expr 1+',
+ ['1+some_expr', "1+static_cast"])
+
+ # Test with spaces
+ self.complete_exactly('expr some_expr .FooNoArgs',
+ 'expr some_expr .FooNoArgsBar()')
+ self.complete_exactly('expr some_expr .FooNoArgs',
+ 'expr some_expr .FooNoArgsBar()')
+ self.complete_exactly('expr some_expr .FooNoArgs',
+ 'expr some_expr .FooNoArgsBar()')
+ self.complete_exactly('expr some_expr. FooNoArgs',
+ 'expr some_expr. FooNoArgsBar()')
+ self.complete_exactly('expr some_expr . FooNoArgs',
+ 'expr some_expr . FooNoArgsBar()')
+ self.complete_exactly('expr Expr :: StaticMemberMethod',
+ 'expr Expr :: StaticMemberMethodBar()')
+ self.complete_exactly('expr Expr ::StaticMemberMethod',
+ 'expr Expr ::StaticMemberMethodBar()')
+ self.complete_exactly('expr Expr:: StaticMemberMethod',
+ 'expr Expr:: StaticMemberMethodBar()')
+
+ # Test that string literals don't break our parsing logic.
+ self.complete_exactly('expr const char *cstr = "some_e"; char c = *cst',
+ 'expr const char *cstr = "some_e"; char c = *cstr')
+ self.complete_exactly('expr const char *cstr = "some_e" ; char c = *cst',
+ 'expr const char *cstr = "some_e" ; char c = *cstr')
+ # Requesting completions inside an incomplete string doesn't provide any
+ # completions.
+ self.complete_exactly('expr const char *cstr = "some_e',
+ 'expr const char *cstr = "some_e')
+
+ # Completing inside double dash should do nothing
+ self.assume_no_completions('expr -i0 -- some_expr.', 10)
+ self.assume_no_completions('expr -i0 -- some_expr.', 11)
+
+ # Test with expr arguments
+ self.complete_exactly('expr -i0 -- some_expr .FooNoArgs',
+ 'expr -i0 -- some_expr .FooNoArgsBar()')
+ self.complete_exactly('expr -i0 -- some_expr .FooNoArgs',
+ 'expr -i0 -- some_expr .FooNoArgsBar()')
+
+ # Addrof and deref
+ self.complete_exactly('expr (*(&some_expr)).FooNoArgs',
+ 'expr (*(&some_expr)).FooNoArgsBar()')
+ self.complete_exactly('expr (*(&some_expr)) .FooNoArgs',
+ 'expr (*(&some_expr)) .FooNoArgsBar()')
+ self.complete_exactly('expr (* (&some_expr)) .FooNoArgs',
+ 'expr (* (&some_expr)) .FooNoArgsBar()')
+ self.complete_exactly('expr (* (& some_expr)) .FooNoArgs',
+ 'expr (* (& some_expr)) .FooNoArgsBar()')
+
+ # Addrof and deref (part 2)
+ self.complete_exactly('expr (&some_expr)->FooNoArgs',
+ 'expr (&some_expr)->FooNoArgsBar()')
+ self.complete_exactly('expr (&some_expr) ->FooNoArgs',
+ 'expr (&some_expr) ->FooNoArgsBar()')
+ self.complete_exactly('expr (&some_expr) -> FooNoArgs',
+ 'expr (&some_expr) -> FooNoArgsBar()')
+ self.complete_exactly('expr (&some_expr)-> FooNoArgs',
+ 'expr (&some_expr)-> FooNoArgsBar()')
+
+ # Builtin arg
+ self.complete_exactly('expr static_ca',
+ 'expr static_cast')
+
+ # From other files
+ self.complete_exactly('expr fwd_decl_ptr->Hidden',
+ 'expr fwd_decl_ptr->HiddenMember')
+
+
+ # Types
+ self.complete_exactly('expr LongClassNa',
+ 'expr LongClassName')
+ self.complete_exactly('expr LongNamespaceName::NestedCla',
+ 'expr LongNamespaceName::NestedClass')
+
+ # Namespaces
+ self.complete_exactly('expr LongNamespaceNa',
+ 'expr LongNamespaceName::')
+
+ # Multiple arguments
+ self.complete_exactly('expr &some_expr + &some_e',
+ 'expr &some_expr + &some_expr')
+ self.complete_exactly('expr SomeLongVarNameWithCapitals + SomeLongVarName',
+ 'expr SomeLongVarNameWithCapitals + SomeLongVarNameWithCapitals')
+ self.complete_exactly('expr SomeIntVar + SomeIntV',
+ 'expr SomeIntVar + SomeIntVar')
+
+ # Multiple statements
+ self.complete_exactly('expr long LocalVariable = 0; LocalVaria',
+ 'expr long LocalVariable = 0; LocalVariable')
+
+ # Custom Decls
+ self.complete_exactly('expr auto l = [](int LeftHandSide, int bx){ return LeftHandS',
+ 'expr auto l = [](int LeftHandSide, int bx){ return LeftHandSide')
+ self.complete_exactly('expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.Mem',
+ 'expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.MemberName')
+
+ # Completing function call arguments
+ self.complete_exactly('expr some_expr.FooWithArgsBar(some_exp',
+ 'expr some_expr.FooWithArgsBar(some_expr')
+ self.complete_exactly('expr some_expr.FooWithArgsBar(SomeIntV',
+ 'expr some_expr.FooWithArgsBar(SomeIntVar')
+ self.complete_exactly('expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVa',
+ 'expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVar')
+
+ # Function return values
+ self.complete_exactly('expr some_expr.Self().FooNoArgs',
+ 'expr some_expr.Self().FooNoArgsBar()')
+ self.complete_exactly('expr some_expr.Self() .FooNoArgs',
+ 'expr some_expr.Self() .FooNoArgsBar()')
+ self.complete_exactly('expr some_expr.Self(). FooNoArgs',
+ 'expr some_expr.Self(). FooNoArgsBar()')
+
+ def test_expr_completion_with_descriptions(self):
+ self.build()
+ self.main_source = "main.cpp"
+ self.main_source_spec = lldb.SBFileSpec(self.main_source)
+ self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ '// Break here', self.main_source_spec)
+
+ self.check_completion_with_desc("expr ", [
+ # VarDecls have their type as description.
+ ["some_expr", "Expr &"],
+ # builtin types have no description.
+ ["int", ""],
+ ["float", ""]
+ ])
+ self.check_completion_with_desc("expr some_expr.", [
+ # Functions have their signature as description.
+ ["some_expr.Self()", "Expr &Self()"],
+ ["some_expr.operator=(", "inline Expr &operator=(const Expr &)"],
+ ["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"],
+ ["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"],
+ ["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"],
+ ["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"],
+ ["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"],
+ ["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"],
+ ["some_expr.~Expr()", "inline ~Expr()"],
+ # FieldDecls have their type as description.
+ ["some_expr.MemberVariableBar", "int"],
+ ])
+
+ def assume_no_completions(self, str_input, cursor_pos = None):
+ interp = self.dbg.GetCommandInterpreter()
+ match_strings = lldb.SBStringList()
+ if cursor_pos is None:
+ cursor_pos = len(str_input)
+ num_matches = interp.HandleCompletion(str_input, cursor_pos, 0, -1, match_strings)
+
+ available_completions = []
+ for m in match_strings:
+ available_completions.append(m)
+
+ self.assertEquals(num_matches, 0, "Got matches, but didn't expect any: " + str(available_completions))
+
+ def completions_contain(self, str_input, items):
+ interp = self.dbg.GetCommandInterpreter()
+ match_strings = lldb.SBStringList()
+ num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
+ common_match = match_strings.GetStringAtIndex(0)
+
+ for item in items:
+ found = False
+ for m in match_strings:
+ if m == item:
+ found = True
+ if not found:
+ # Transform match_strings to a python list with strings
+ available_completions = []
+ for m in match_strings:
+ available_completions.append(m)
+ self.assertTrue(found, "Couldn't find completion " + item + " in completions " + str(available_completions))
diff --git a/packages/Python/lldbsuite/test/expression_command/completion/main.cpp b/packages/Python/lldbsuite/test/expression_command/completion/main.cpp
new file mode 100644
index 000000000000..908bebbebff5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/completion/main.cpp
@@ -0,0 +1,35 @@
+namespace LongNamespaceName { class NestedClass { long m; }; }
+
+// Defined in other.cpp, we only have a forward declaration here.
+struct ForwardDecl;
+extern ForwardDecl fwd_decl;
+
+class LongClassName { long i ; };
+
+class Expr {
+public:
+ int FooNoArgsBar() { return 1; }
+ int FooWithArgsBar(int i) { return i; }
+ int FooWithMultipleArgsBar(int i, int j) { return i + j; }
+ int FooUnderscoreBar_() { return 4; }
+ int FooNumbersBar1() { return 8; }
+ int MemberVariableBar = 0;
+ Expr &Self() { return *this; }
+ static int StaticMemberMethodBar() { return 82; }
+};
+
+int main()
+{
+ LongClassName a;
+ LongNamespaceName::NestedClass NestedFoo;
+ long SomeLongVarNameWithCapitals = 44;
+ int SomeIntVar = 33;
+ Expr some_expr;
+ some_expr.FooNoArgsBar();
+ some_expr.FooWithArgsBar(1);
+ some_expr.FooUnderscoreBar_();
+ some_expr.FooNumbersBar1();
+ Expr::StaticMemberMethodBar();
+ ForwardDecl *fwd_decl_ptr = &fwd_decl;
+ return 0; // Break here
+}
diff --git a/packages/Python/lldbsuite/test/expression_command/completion/other.cpp b/packages/Python/lldbsuite/test/expression_command/completion/other.cpp
new file mode 100644
index 000000000000..1f8a488639b9
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/completion/other.cpp
@@ -0,0 +1,4 @@
+struct ForwardDecl {
+ long HiddenMemberName;
+};
+ForwardDecl fwd_decl;
diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile
new file mode 100644
index 000000000000..50d4ab65a6ec
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS += -std=c99
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py
new file mode 100644
index 000000000000..05c67902a3ab
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/TestAllowJIT.py
@@ -0,0 +1,90 @@
+"""
+Test that --allow-jit=false does disallow JITting:
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import re
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+
+class TestAllowJIT(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ # If your test case doesn't stress debug info, the
+ # set this to true. That way it won't be run once for
+ # each debug info format.
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_allow_jit_expr_command(self):
+ """Test the --allow-jit command line flag"""
+ self.build()
+ self.main_source_file = lldb.SBFileSpec("main.c")
+ self.expr_cmd_test()
+
+ def test_allow_jit_options(self):
+ """Test the SetAllowJIT SBExpressionOption setting"""
+ self.build()
+ self.main_source_file = lldb.SBFileSpec("main.c")
+ self.expr_options_test()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def expr_cmd_test(self):
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ "Set a breakpoint here", self.main_source_file)
+
+ frame = thread.GetFrameAtIndex(0)
+
+ # First make sure we can call the function with
+ interp = self.dbg.GetCommandInterpreter()
+ self.expect("expr --allow-jit 1 -- call_me(10)",
+ substrs = ["(int) $", "= 18"])
+ # Now make sure it fails with the "can't IR interpret message" if allow-jit is false:
+ self.expect("expr --allow-jit 0 -- call_me(10)",
+ error=True,
+ substrs = ["Can't run the expression locally"])
+
+ def expr_options_test(self):
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ "Set a breakpoint here", self.main_source_file)
+
+ frame = thread.GetFrameAtIndex(0)
+
+ # First make sure we can call the function with the default option set.
+ options = lldb.SBExpressionOptions()
+ # Check that the default is to allow JIT:
+ self.assertEqual(options.GetAllowJIT(), True, "Default is true")
+
+ # Now use the options:
+ result = frame.EvaluateExpression("call_me(10)", options)
+ self.assertTrue(result.GetError().Success(), "expression succeeded")
+ self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.")
+
+ # Now disallow JIT and make sure it fails:
+ options.SetAllowJIT(False)
+ # Check that we got the right value:
+ self.assertEqual(options.GetAllowJIT(), False, "Got False after setting to False")
+
+ # Again use it and ensure we fail:
+ result = frame.EvaluateExpression("call_me(10)", options)
+ self.assertTrue(result.GetError().Fail(), "expression failed with no JIT")
+ self.assertTrue("Can't run the expression locally" in result.GetError().GetCString(), "Got right error")
+
+ # Finally set the allow JIT value back to true and make sure that works:
+ options.SetAllowJIT(True)
+ self.assertEqual(options.GetAllowJIT(), True, "Set back to True correctly")
+
+ # And again, make sure this works:
+ result = frame.EvaluateExpression("call_me(10)", options)
+ self.assertTrue(result.GetError().Success(), "expression succeeded")
+ self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.")
+
diff --git a/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c
new file mode 100644
index 000000000000..ebd8ae11a73a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/dont_allow_jit/main.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+
+int
+call_me(int input)
+{
+ return printf("I was called: %d.\n", input);
+}
+
+int
+main()
+{
+ int test_var = 10;
+ printf ("Set a breakpoint here: %d.\n", test_var);
+ return call_me(100);
+}
diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py
index f14b02bbd7c4..ee5c4a0ee1df 100644
--- a/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py
+++ b/packages/Python/lldbsuite/test/expression_command/formatters/TestFormatters.py
@@ -57,14 +57,21 @@ class ExprFormattersTestCase(TestBase):
self.runCmd("frame variable foo1.b --show-types")
self.runCmd("frame variable foo1.b.b_ref --show-types")
- self.expect(
- "expression --show-types -- *(new foo(47))",
- substrs=[
- '(int) a = 47',
- '(bar) b = {',
- '(int) i = 94',
- '(baz) b = {',
- '(int) k = 99'])
+ self.filecheck("expression --show-types -- *(new foo(47))", __file__,
+ '-check-prefix=EXPR-TYPES-NEW-FOO')
+ # EXPR-TYPES-NEW-FOO: (foo) ${{.*}} = {
+ # EXPR-TYPES-NEW-FOO-NEXT: (int) a = 47
+ # EXPR-TYPES-NEW-FOO-NEXT: (int *) a_ptr = 0x
+ # EXPR-TYPES-NEW-FOO-NEXT: (bar) b = {
+ # EXPR-TYPES-NEW-FOO-NEXT: (int) i = 94
+ # EXPR-TYPES-NEW-FOO-NEXT: (int *) i_ptr = 0x
+ # EXPR-TYPES-NEW-FOO-NEXT: (baz) b = {
+ # EXPR-TYPES-NEW-FOO-NEXT: (int) h = 97
+ # EXPR-TYPES-NEW-FOO-NEXT: (int) k = 99
+ # EXPR-TYPES-NEW-FOO-NEXT: }
+ # EXPR-TYPES-NEW-FOO-NEXT: (baz &) b_ref = 0x
+ # EXPR-TYPES-NEW-FOO-NEXT: }
+ # EXPR-TYPES-NEW-FOO-NEXT: }
self.runCmd("type summary add -F formatters.foo_SummaryProvider foo")
@@ -80,68 +87,49 @@ class ExprFormattersTestCase(TestBase):
self.expect("expression foo1.a_ptr",
substrs=['(int *) $', '= 0x', ' -> 13'])
- self.expect(
- "expression foo1",
- substrs=[
- '(foo) $',
- ' a = 12',
- 'a_ptr = ',
- ' -> 13',
- 'i = 24',
- 'i_ptr = ',
- ' -> 25'])
-
- self.expect(
- "expression --ptr-depth=1 -- new foo(47)",
- substrs=[
- '(foo *) $',
- 'a = 47',
- 'a_ptr = ',
- ' -> 48',
- 'i = 94',
- 'i_ptr = ',
- ' -> 95'])
-
- self.expect(
- "expression foo2",
- substrs=[
- '(foo) $',
- 'a = 121',
- 'a_ptr = ',
- ' -> 122',
- 'i = 242',
- 'i_ptr = ',
- ' -> 243'])
+ self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1')
+ # EXPR-FOO1: (foo) $
+ # EXPR-FOO1-SAME: a = 12
+ # EXPR-FOO1-SAME: a_ptr = {{[0-9]+}} -> 13
+ # EXPR-FOO1-SAME: i = 24
+ # EXPR-FOO1-SAME: i_ptr = {{[0-9]+}} -> 25
+ # EXPR-FOO1-SAME: b_ref = {{[0-9]+}}
+ # EXPR-FOO1-SAME: h = 27
+ # EXPR-FOO1-SAME: k = 29
+
+ self.filecheck("expression --ptr-depth=1 -- new foo(47)", __file__,
+ '-check-prefix=EXPR-PTR-DEPTH1')
+ # EXPR-PTR-DEPTH1: (foo *) $
+ # EXPR-PTR-DEPTH1-SAME: a = 47
+ # EXPR-PTR-DEPTH1-SAME: a_ptr = {{[0-9]+}} -> 48
+ # EXPR-PTR-DEPTH1-SAME: i = 94
+ # EXPR-PTR-DEPTH1-SAME: i_ptr = {{[0-9]+}} -> 95
+
+ self.filecheck("expression foo2", __file__, '-check-prefix=EXPR-FOO2')
+ # EXPR-FOO2: (foo) $
+ # EXPR-FOO2-SAME: a = 121
+ # EXPR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122
+ # EXPR-FOO2-SAME: i = 242
+ # EXPR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243
+ # EXPR-FOO2-SAME: h = 245
+ # EXPR-FOO2-SAME: k = 247
object_name = self.res.GetOutput()
object_name = object_name[7:]
object_name = object_name[0:object_name.find(' =')]
- self.expect(
- "frame variable foo2",
- substrs=[
- '(foo)',
- 'foo2',
- 'a = 121',
- 'a_ptr = ',
- ' -> 122',
- 'i = 242',
- 'i_ptr = ',
- ' -> 243'])
-
- self.expect(
- "expression $" +
- object_name,
- substrs=[
- '(foo) $',
- 'a = 121',
- 'a_ptr = ',
- ' -> 122',
- 'i = 242',
- 'i_ptr = ',
- ' -> 243',
- 'h = 245',
- 'k = 247'])
+ self.filecheck("frame variable foo2", __file__, '-check-prefix=VAR-FOO2')
+ # VAR-FOO2: (foo) foo2
+ # VAR-FOO2-SAME: a = 121
+ # VAR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122
+ # VAR-FOO2-SAME: i = 242
+ # VAR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243
+ # VAR-FOO2-SAME: h = 245
+ # VAR-FOO2-SAME: k = 247
+
+ # The object is the same as foo2, so use the EXPR-FOO2 checks.
+ self.filecheck("expression $" + object_name, __file__,
+ '-check-prefix=EXPR-FOO2')
self.runCmd("type summary delete foo")
self.runCmd(
diff --git a/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp b/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp
index 4c3b180f3709..1b8ce48041f9 100644
--- a/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp
+++ b/packages/Python/lldbsuite/test/expression_command/formatters/main.cpp
@@ -45,4 +45,4 @@ int main(int argc, char** argv)
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py b/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py
deleted file mode 100644
index 7f639a462201..000000000000
--- a/packages/Python/lldbsuite/test/expression_command/multiline/TestMultilineExpressions.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""Test multiline expressions."""
-
-from __future__ import print_function
-
-import os
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class MultilineExpressionsTestCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
- NO_DEBUG_INFO_TESTCASE = True
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line number to break on inside main.cpp.
- self.line = line_number('main.c', 'break')
-
- @skipIfRemote
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_with_run_commands(self):
- """Test that multiline expressions work correctly"""
- self.build()
- import pexpect
- exe = self.getBuildArtifact("a.out")
- prompt = "(lldb) "
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn(
- '%s %s %s' %
- (lldbtest_config.lldbExec, self.lldbOption, exe))
- child = self.child
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- # Set the breakpoint, run the inferior, when it breaks, issue print on
- # the various convenience variables.
- child.expect_exact(prompt)
- child.sendline('breakpoint set -f main.c -l %d' % self.line)
- child.expect_exact(prompt)
- child.sendline('run')
- child.expect_exact("stop reason = breakpoint 1.1")
- child.expect_exact(prompt)
- child.sendline('expr')
- child.expect_exact('1:')
-
- child.sendline('2+')
- child.expect_exact('2:')
-
- child.sendline('3')
- child.expect_exact('3:')
-
- child.sendline('')
- child.expect_exact(prompt)
- self.expect(child.before, exe=False,
- patterns=['= 5'])
-
- @skipIfRemote
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_empty_list(self):
- """Test printing an empty list of expressions"""
- import pexpect
- prompt = "(lldb) "
-
- # So that the child gets torn down after the test
- self.child = pexpect.spawn(
- "%s %s" %
- (lldbtest_config.lldbExec, self.lldbOption))
- child = self.child
-
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- # We expect a prompt, then send "print" to start a list of expressions,
- # then an empty line. We expect a prompt back.
- child.expect_exact(prompt)
- child.sendline("print")
- child.expect_exact('1:')
- child.sendline("")
- child.expect_exact(prompt)
diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/main.c b/packages/Python/lldbsuite/test/expression_command/multiline/main.c
deleted file mode 100644
index da16b1e7846f..000000000000
--- a/packages/Python/lldbsuite/test/expression_command/multiline/main.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(int argc, char const *argv[]) {
- printf("Hello world.\n"); // break here
- return 0;
-}
diff --git a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py
index 1dbafc36a82a..13bc3b7ce2ac 100644
--- a/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py
+++ b/packages/Python/lldbsuite/test/expression_command/options/TestExprOptions.py
@@ -14,6 +14,7 @@ import os
import time
import lldb
import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
@@ -63,3 +64,30 @@ class ExprOptionsTestCase(TestBase):
val = frame.EvaluateExpression('foo != nullptr', options)
self.assertTrue(val.IsValid())
self.assertFalse(val.GetError().Success())
+
+ @skipIfDarwin
+ def test_expr_options_lang(self):
+ """These expression language options should work as expected."""
+ self.build()
+
+ # Set debugger into synchronous mode
+ self.dbg.SetAsync(False)
+
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, '// breakpoint_in_main', self.main_source_spec)
+
+ frame = thread.GetFrameAtIndex(0)
+ options = lldb.SBExpressionOptions()
+
+ # Make sure we can retrieve `id` variable if language is set to C++11:
+ options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11)
+ val = frame.EvaluateExpression('id == 0', options)
+ self.assertTrue(val.IsValid())
+ self.assertTrue(val.GetError().Success())
+ self.DebugSBValue(val)
+
+ # Make sure we can't retrieve `id` variable if language is set to ObjC:
+ options.SetLanguage(lldb.eLanguageTypeObjC)
+ val = frame.EvaluateExpression('id == 0', options)
+ self.assertTrue(val.IsValid())
+ self.assertFalse(val.GetError().Success())
diff --git a/packages/Python/lldbsuite/test/expression_command/options/main.cpp b/packages/Python/lldbsuite/test/expression_command/options/main.cpp
index ecd9a90f6626..0d30c79bd229 100644
--- a/packages/Python/lldbsuite/test/expression_command/options/main.cpp
+++ b/packages/Python/lldbsuite/test/expression_command/options/main.cpp
@@ -1,11 +1,13 @@
extern "C" int foo(void);
static int static_value = 0;
+static int id = 1234;
int
bar()
{
static_value++;
- return static_value;
+ id++;
+ return static_value + id;
}
int main (int argc, char const *argv[])
diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py
index f4ee1b0fb625..8630d6f41b34 100644
--- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py
+++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestNestedPersistentTypes.py
@@ -17,7 +17,6 @@ class NestedPersistentTypesTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_persistent_types(self):
"""Test that nested persistent types work."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py
index f56cb11a80d8..403d24246a9d 100644
--- a/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py
+++ b/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py
@@ -17,7 +17,6 @@ class PersistenttypesTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_persistent_types(self):
"""Test that lldb persistent types works correctly."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py b/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py
index dd3d06fd672f..6d019c7415fc 100644
--- a/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py
+++ b/packages/Python/lldbsuite/test/expression_command/pr35310/TestExprsBug35310.py
@@ -16,7 +16,6 @@ class ExprBug35310(TestBase):
self.main_source = "main.cpp"
self.main_source_spec = lldb.SBFileSpec(self.main_source)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_issue35310(self):
"""Test invoking functions with non-standard linkage names.
diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile b/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile
new file mode 100644
index 000000000000..83b24da17b4d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+CXXFLAGS += -std=c++11
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py b/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py
new file mode 100644
index 000000000000..028047fc46bf
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/TestScopedEnumType.py
@@ -0,0 +1,44 @@
+from __future__ import print_function
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ScopedEnumType(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test(self):
+ self.build()
+
+ self.main_source = "main.cpp"
+ self.main_source_spec = lldb.SBFileSpec(self.main_source)
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ '// Set break point at this line.', self.main_source_spec)
+ frame = thread.GetFrameAtIndex(0)
+
+ self.expect("expr f == Foo::FooBar",
+ substrs=['(bool) $0 = true'])
+
+ value = frame.EvaluateExpression("f == Foo::FooBar")
+ self.assertTrue(value.IsValid())
+ self.assertTrue(value.GetError().Success())
+ self.assertEqual(value.GetValueAsUnsigned(), 1)
+
+ value = frame.EvaluateExpression("b == BarBar")
+ self.assertTrue(value.IsValid())
+ self.assertTrue(value.GetError().Success())
+ self.assertEqual(value.GetValueAsUnsigned(), 1)
+
+ ## b is not a Foo
+ value = frame.EvaluateExpression("b == Foo::FooBar")
+ self.assertTrue(value.IsValid())
+ self.assertFalse(value.GetError().Success())
+
+ ## integral is not implicitly convertible to a scoped enum
+ value = frame.EvaluateExpression("1 == Foo::FooBar")
+ self.assertTrue(value.IsValid())
+ self.assertFalse(value.GetError().Success())
diff --git a/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp b/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp
new file mode 100644
index 000000000000..b0d67d23dc5e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/radar_43822994/main.cpp
@@ -0,0 +1,16 @@
+enum class Foo {
+ FooBar = 42
+};
+
+enum Bar {
+ BarBar = 3,
+ BarBarBar = 42
+};
+
+int main(int argc, const char **argv) {
+ Foo f = Foo::FooBar;
+ Bar b = BarBar;
+ bool b1 = f == Foo::FooBar;
+ bool b2 = b == BarBar;
+ return 0; // Set break point at this line.
+}
diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py
index c44cb6fc39da..dc8ee77fd6fb 100644
--- a/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py
+++ b/packages/Python/lldbsuite/test/expression_command/radar_9531204/TestPrintfAfterUp.py
@@ -18,7 +18,6 @@ class Radar9531204TestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
# rdar://problem/9531204
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_expr_commands(self):
"""The evaluating printf(...) after break stop and then up a stack frame."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py
index dfef8735071b..d18720ccf3f1 100644
--- a/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py
+++ b/packages/Python/lldbsuite/test/expression_command/radar_9673664/TestExprHelpExamples.py
@@ -24,7 +24,6 @@ class Radar9673644TestCase(TestBase):
self.main_source = "main.c"
self.line = line_number(self.main_source, '// Set breakpoint here.')
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_expr_commands(self):
"""The following expression commands should just work."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile
new file mode 100644
index 000000000000..f5a47fcc46cc
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Makefile
@@ -0,0 +1,3 @@
+LEVEL = ../../make
+C_SOURCES := main.c
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py
new file mode 100644
index 000000000000..c8308c16011e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/Test128BitsInteger.py
@@ -0,0 +1,4 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals())
diff --git a/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c b/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c
new file mode 100644
index 000000000000..156dbf04a1b7
--- /dev/null
+++ b/packages/Python/lldbsuite/test/expression_command/rdar44436068/main.c
@@ -0,0 +1,8 @@
+int main(void)
+{
+ __int128_t n = 1;
+ n = n + n;
+ return n; //%self.expect("p n", substrs=['(__int128_t) $0 = 2'])
+ //%self.expect("p n + 6", substrs=['(__int128) $1 = 8'])
+ //%self.expect("p n + n", substrs=['(__int128) $2 = 4'])
+}
diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py
index 3af7d808e128..deae7feb3ac1 100644
--- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py
+++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs.py
@@ -102,7 +102,6 @@ class BasicExprCommandsTestCase(TestBase):
# (const char *) $8 = 0x... "/Volumes/data/lldb/svn/trunk/test/expression_command/test/a.out"
@add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_evaluate_expression_python(self):
"""Test SBFrame.EvaluateExpression() API for evaluating an expression."""
self.build()
@@ -203,7 +202,6 @@ class BasicExprCommandsTestCase(TestBase):
# rdar://problem/8686536
# CommandInterpreter::HandleCommand is stripping \'s from input for
# WantsRawCommand commands
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_expr_commands_can_handle_quotes(self):
"""Throw some expression commands with quotes at lldb."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py
index f5ec4f027866..88412e6b7c82 100644
--- a/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py
+++ b/packages/Python/lldbsuite/test/expression_command/test/TestExprs2.py
@@ -24,9 +24,6 @@ class ExprCommands2TestCase(TestBase):
'main.cpp',
'// Please test many expressions while stopped at this line:')
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_more_expr_commands(self):
"""Test some more expression commands."""
self.build()
@@ -60,9 +57,7 @@ class ExprCommands2TestCase(TestBase):
# (int) $5 = 6
@skipIfLinux
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
def test_expr_symbols(self):
"""Test symbols."""
self.build()
diff --git a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py
index c942427a8e66..108de8867d50 100644
--- a/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py
+++ b/packages/Python/lldbsuite/test/expression_command/unwind_expression/TestUnwindExpression.py
@@ -55,7 +55,6 @@ class UnwindFromExpressionTest(TestBase):
@add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"])
def test_unwind_expression(self):
"""Test unwinding from an expression."""
self.build_and_run_to_bkpt()
diff --git a/packages/Python/lldbsuite/test/functionalities/asan/Makefile b/packages/Python/lldbsuite/test/functionalities/asan/Makefile
index 26654a023ed1..dc8d682f831a 100644
--- a/packages/Python/lldbsuite/test/functionalities/asan/Makefile
+++ b/packages/Python/lldbsuite/test/functionalities/asan/Makefile
@@ -1,6 +1,6 @@
LEVEL = ../../make
C_SOURCES := main.c
-CFLAGS_EXTRAS := -fsanitize=address -g
+CFLAGS_EXTRAS := -fsanitize=address -g -gcolumn-info
include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py
index d7c511021863..ca070fa97dfa 100644
--- a/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py
+++ b/packages/Python/lldbsuite/test/functionalities/asan/TestReportData.py
@@ -37,6 +37,7 @@ class AsanTestReportDataCase(TestBase):
self.line_free = line_number('main.c', '// free line')
self.line_breakpoint = line_number('main.c', '// break line')
self.line_crash = line_number('main.c', '// BOOM line')
+ self.col_crash = 16
def asan_tests(self):
exe = self.getBuildArtifact("a.out")
@@ -63,7 +64,7 @@ class AsanTestReportDataCase(TestBase):
lldb.eStopReasonInstrumentation)
self.expect("bt", "The backtrace should show the crashing line",
- substrs=['main.c:%d' % self.line_crash])
+ substrs=['main.c:%d:%d' % (self.line_crash, self.col_crash)])
self.expect(
"thread info -s",
diff --git a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py
index ad87796766c3..754acade015a 100644
--- a/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py
+++ b/packages/Python/lldbsuite/test/functionalities/attach_resume/TestAttachResume.py
@@ -21,7 +21,7 @@ class AttachResumeTestCase(TestBase):
@skipIfRemote
@expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr19310')
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
+ @skipIfWindows # llvm.org/pr24778, llvm.org/pr21753
def test_attach_continue_interrupt_detach(self):
"""Test attach/continue/interrupt/detach"""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile
new file mode 100644
index 000000000000..6c22351dc3b5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS += -std=c99 -gcolumn-info
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
new file mode 100644
index 000000000000..07032cc0380c
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/TestBreakpointByLineAndColumn.py
@@ -0,0 +1,48 @@
+"""
+Test setting a breakpoint by line and column.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import re
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class BreakpointByLineAndColumnTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info
+ @skipIf(compiler="gcc", compiler_version=['<', '7.1'])
+ def testBreakpointByLineAndColumn(self):
+ self.build()
+ main_c = lldb.SBFileSpec("main.c")
+ _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self,
+ main_c, 20, 50)
+ self.expect("fr v did_call", substrs='1')
+ in_then = False
+ for i in range(breakpoint.GetNumLocations()):
+ b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry()
+ self.assertEqual(b_loc.GetLine(), 20)
+ in_then |= b_loc.GetColumn() == 50
+ self.assertTrue(in_then)
+
+ ## Skip gcc version less 7.1 since it doesn't support -gcolumn-info
+ @skipIf(compiler="gcc", compiler_version=['<', '7.1'])
+ def testBreakpointByLine(self):
+ self.build()
+ main_c = lldb.SBFileSpec("main.c")
+ _, _, _, breakpoint = lldbutil.run_to_line_breakpoint(self, main_c, 20)
+ self.expect("fr v did_call", substrs='0')
+ in_condition = False
+ for i in range(breakpoint.GetNumLocations()):
+ b_loc = breakpoint.GetLocationAtIndex(i).GetAddress().GetLineEntry()
+ self.assertEqual(b_loc.GetLine(), 20)
+ in_condition |= b_loc.GetColumn() < 30
+ self.assertTrue(in_condition)
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c
new file mode 100644
index 000000000000..921bc382023f
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_by_line_and_column/main.c
@@ -0,0 +1,23 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int square(int x)
+{
+ return x * x;
+}
+
+int main (int argc, char const *argv[])
+{
+ int did_call = 0;
+
+ // Line 20. v Column 50.
+ if(square(argc+1) != 0) { did_call = 1; return square(argc); }
+ // ^
+ return square(0);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
index 7a2dc61b1b69..8143fa96433f 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py
@@ -25,7 +25,6 @@ class BreakpointCommandTestCase(TestBase):
self.build()
self.breakpoint_command_sequence()
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
def test_script_parameters(self):
"""Test a sequence of breakpoint command add, list, and delete."""
self.build()
@@ -45,7 +44,6 @@ class BreakpointCommandTestCase(TestBase):
self.addTearDownHook(
lambda: self.runCmd("settings clear auto-confirm"))
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
def test_delete_all_breakpoints(self):
"""Test that deleting all breakpoints works."""
self.build()
@@ -133,9 +131,9 @@ class BreakpointCommandTestCase(TestBase):
patterns=[
"1: file = '.*main.c', line = %d, exact_match = 0, locations = 1" %
self.line,
- "1.1: .+at main.c:%d, .+unresolved, hit count = 0" %
+ "1.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %
self.line,
- "2.1: .+at main.c:%d, .+unresolved, hit count = 0" %
+ "2.1: .+at main.c:%d:?[0-9]*, .+unresolved, hit count = 0" %
self.line])
self.expect("breakpoint command list 1", "Breakpoint 1 command ok",
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
index eb4bac7e6e66..e3bf4c27f31e 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_ignore_count/TestBreakpointIgnoreCount.py
@@ -18,12 +18,14 @@ class BreakpointIgnoreCountTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ @skipIfWindows # This test will hang on windows llvm.org/pr21753
def test_with_run_command(self):
"""Exercise breakpoint ignore count with 'breakpoint set -i <count>'."""
self.build()
self.breakpoint_ignore_count()
@add_test_categories(['pyapi'])
+ @skipIfWindows # This test will hang on windows llvm.org/pr21753
def test_with_python_api(self):
"""Use Python APIs to set breakpoint ignore count."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py
index 16d5bc75473c..b8281e9c85bd 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/TestMoveNearest.py
@@ -18,6 +18,8 @@ class TestMoveNearest(TestBase):
# Find the line number to break inside main().
self.line1 = line_number('foo.h', '// !BR1')
self.line2 = line_number('foo.h', '// !BR2')
+ self.line_between = line_number('main.cpp', "// BR_Between")
+ print("BR_Between found at", self.line_between)
self.line_main = line_number('main.cpp', '// !BR_main')
def test(self):
@@ -61,3 +63,7 @@ class TestMoveNearest(TestBase):
# "return .."
lldbutil.run_break_set_by_file_and_line(self, 'main.cpp',
self.line_main+2, extra_options="-m 1")
+
+ # Make sure we don't put move the breakpoint if it is set between two functions:
+ lldbutil.run_break_set_by_file_and_line(self, 'main.cpp',
+ self.line_between, extra_options="-m 1", num_expected_locations=0)
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp
index c9295a5c7d3c..76a22a5420fe 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/move_nearest/main.cpp
@@ -1,7 +1,7 @@
#include "foo.h"
int call_foo2() { return foo2(); }
-
+// BR_Between
int
main() // !BR_main
{
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile
new file mode 100644
index 000000000000..7934cd5db427
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/Makefile
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+ifneq (,$(findstring icc,$(CC)))
+ CFLAGS += -debug inline-debug-info
+endif
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py
new file mode 100644
index 000000000000..cda15fee84b8
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/TestRequireHWBreakpoints.py
@@ -0,0 +1,106 @@
+"""
+Test require hardware breakpoints.
+"""
+
+from __future__ import print_function
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class BreakpointLocationsTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test_breakpoint(self):
+ """Test regular breakpoints when hardware breakpoints are required."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ breakpoint = target.BreakpointCreateByLocation("main.c", 1)
+ self.assertTrue(breakpoint.IsHardware())
+
+ @skipIfWindows
+ def test_step_range(self):
+ """Test stepping when hardware breakpoints are required."""
+ self.build()
+
+ _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+ self, lldb.SBFileSpec("main.c"), 1)
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ # Ensure we fail in the interpreter.
+ self.expect("thread step-in")
+ self.expect("thread step-in", error=True)
+
+ # Ensure we fail when stepping through the API.
+ error = lldb.SBError()
+ thread.StepInto('', 4, error)
+ self.assertTrue(error.Fail())
+ self.assertTrue("Could not create hardware breakpoint for thread plan"
+ in error.GetCString())
+
+ @skipIfWindows
+ def test_step_out(self):
+ """Test stepping out when hardware breakpoints are required."""
+ self.build()
+
+ _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+ self, lldb.SBFileSpec("main.c"), 1)
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ # Ensure this fails in the command interpreter.
+ self.expect("thread step-out", error=True)
+
+ # Ensure we fail when stepping through the API.
+ error = lldb.SBError()
+ thread.StepOut(error)
+ self.assertTrue(error.Fail())
+ self.assertTrue("Could not create hardware breakpoint for thread plan"
+ in error.GetCString())
+
+ @skipIfWindows
+ def test_step_over(self):
+ """Test stepping over when hardware breakpoints are required."""
+ self.build()
+
+ _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+ self, lldb.SBFileSpec("main.c"), 7)
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ # Step over doesn't fail immediately but fails later on.
+ self.expect("thread step-over")
+ self.expect(
+ "process status",
+ substrs=[
+ 'step over failed',
+ 'Could not create hardware breakpoint for thread plan'
+ ])
+
+ @skipIfWindows
+ def test_step_until(self):
+ """Test stepping until when hardware breakpoints are required."""
+ self.build()
+
+ _, _, thread, _ = lldbutil.run_to_line_breakpoint(
+ self, lldb.SBFileSpec("main.c"), 7)
+
+ self.runCmd("settings set target.require-hardware-breakpoint true")
+
+ self.expect("thread until 5", error=True)
+
+ # Ensure we fail when stepping through the API.
+ error = thread.StepOverUntil(lldb.SBFrame(), lldb.SBFileSpec(), 5)
+ self.assertTrue(error.Fail())
+ self.assertTrue("Could not create hardware breakpoint for thread plan"
+ in error.GetCString())
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c
new file mode 100644
index 000000000000..7d49a57d4c7b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/require_hw_breakpoints/main.c
@@ -0,0 +1,9 @@
+int break_on_me() {
+ int i = 10;
+ i++;
+ return i;
+}
+
+int main() {
+ return break_on_me();
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile
new file mode 100644
index 000000000000..6067ee45e984
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+CFLAGS_EXTRAS += -std=c99
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
new file mode 100644
index 000000000000..0eb9033e754b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
@@ -0,0 +1,199 @@
+"""
+Test setting breakpoints using a scripted resolver
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import re
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+
+class TestScriptedResolver(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
+ def test_scripted_resolver(self):
+ """Use a scripted resolver to set a by symbol name breakpoint"""
+ self.build()
+ self.do_test()
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
+ def test_search_depths(self):
+ """ Make sure we are called at the right depths depending on what we return
+ from __get_depth__"""
+ self.build()
+ self.do_test_depths()
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24528")
+ def test_command_line(self):
+ """ Make sure we are called at the right depths depending on what we return
+ from __get_depth__"""
+ self.build()
+ self.do_test_cli()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def make_target_and_import(self):
+ target = lldbutil.run_to_breakpoint_make_target(self)
+ interp = self.dbg.GetCommandInterpreter()
+ error = lldb.SBError()
+
+ script_name = os.path.join(self.getSourceDir(), "resolver.py")
+ source_name = os.path.join(self.getSourceDir(), "main.c")
+
+ command = "command script import " + script_name
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand(command, result)
+ self.assertTrue(result.Succeeded(), "com scr imp failed: %s"%(result.GetError()))
+ return target
+
+ def make_extra_args(self):
+ json_string = '{"symbol":"break_on_me", "test1": "value1"}'
+ json_stream = lldb.SBStream()
+ json_stream.Print(json_string)
+ extra_args = lldb.SBStructuredData()
+ error = extra_args.SetFromJSON(json_stream)
+ self.assertTrue(error.Success(), "Error making SBStructuredData: %s"%(error.GetCString()))
+ return extra_args
+
+ def do_test(self):
+ """This reads in a python file and sets a breakpoint using it."""
+
+ target = self.make_target_and_import()
+ extra_args = self.make_extra_args()
+
+ file_list = lldb.SBFileSpecList()
+ module_list = lldb.SBFileSpecList()
+
+ # Make breakpoints with this resolver using different filters, first ones that will take:
+ right = []
+ # one with no file or module spec - this one should fire:
+ right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list))
+
+ # one with the right source file and no module - should also fire:
+ file_list.Append(lldb.SBFileSpec("main.c"))
+ right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list))
+ # Make sure the help text shows up in the "break list" output:
+ self.expect("break list", substrs=["I am a python breakpoint resolver"], msg="Help is listed in break list")
+
+ # one with the right source file and right module - should also fire:
+ module_list.Append(lldb.SBFileSpec("a.out"))
+ right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list))
+
+ # And one with no source file but the right module:
+ file_list.Clear()
+ right.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list))
+
+ # Make sure these all got locations:
+ for i in range (0, len(right)):
+ self.assertTrue(right[i].GetNumLocations() >= 1, "Breakpoint %d has no locations."%(i))
+
+ # Now some ones that won't take:
+
+ module_list.Clear()
+ file_list.Clear()
+ wrong = []
+
+ # one with the wrong module - should not fire:
+ module_list.Append(lldb.SBFileSpec("noSuchModule"))
+ wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list))
+
+ # one with the wrong file - also should not fire:
+ file_list.Clear()
+ module_list.Clear()
+ file_list.Append(lldb.SBFileSpec("noFileOfThisName.xxx"))
+ wrong.append(target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list))
+
+ # Now make sure the CU level iteration obeys the file filters:
+ file_list.Clear()
+ module_list.Clear()
+ file_list.Append(lldb.SBFileSpec("no_such_file.xxx"))
+ wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list))
+
+ # And the Module filters:
+ file_list.Clear()
+ module_list.Clear()
+ module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib"))
+ wrong.append(target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list))
+
+ # Now make sure the Function level iteration obeys the file filters:
+ file_list.Clear()
+ module_list.Clear()
+ file_list.Append(lldb.SBFileSpec("no_such_file.xxx"))
+ wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list))
+
+ # And the Module filters:
+ file_list.Clear()
+ module_list.Clear()
+ module_list.Append(lldb.SBFileSpec("NoSuchModule.dylib"))
+ wrong.append(target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list))
+
+ # Make sure these didn't get locations:
+ for i in range(0, len(wrong)):
+ self.assertEqual(wrong[i].GetNumLocations(), 0, "Breakpoint %d has locations."%(i))
+
+ # Now run to main and ensure we hit the breakpoints we should have:
+
+ lldbutil.run_to_breakpoint_do_run(self, target, right[0])
+
+ # Test the hit counts:
+ for i in range(0, len(right)):
+ self.assertEqual(right[i].GetHitCount(), 1, "Breakpoint %d has the wrong hit count"%(i))
+
+ for i in range(0, len(wrong)):
+ self.assertEqual(wrong[i].GetHitCount(), 0, "Breakpoint %d has the wrong hit count"%(i))
+
+ def do_test_depths(self):
+ """This test uses a class variable in resolver.Resolver which gets set to 1 if we saw
+ compile unit and 2 if we only saw modules. If the search depth is module, you get passed just
+ the modules with no comp_unit. If the depth is comp_unit you get comp_units. So we can use
+ this to test that our callback gets called at the right depth."""
+
+ target = self.make_target_and_import()
+ extra_args = self.make_extra_args()
+
+ file_list = lldb.SBFileSpecList()
+ module_list = lldb.SBFileSpecList()
+ module_list.Append(lldb.SBFileSpec("a.out"))
+
+ # Make a breakpoint that has no __get_depth__, check that that is converted to eSearchDepthModule:
+ bkpt = target.BreakpointCreateFromScript("resolver.Resolver", extra_args, module_list, file_list)
+ self.assertTrue(bkpt.GetNumLocations() > 0, "Resolver got no locations.")
+ self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules")
+
+ # Make a breakpoint that asks for modules, check that we didn't get any files:
+ bkpt = target.BreakpointCreateFromScript("resolver.ResolverModuleDepth", extra_args, module_list, file_list)
+ self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverModuleDepth got no locations.")
+ self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules")
+
+ # Make a breakpoint that asks for compile units, check that we didn't get any files:
+ bkpt = target.BreakpointCreateFromScript("resolver.ResolverCUDepth", extra_args, module_list, file_list)
+ self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverCUDepth got no locations.")
+ self.expect("script print resolver.Resolver.got_files", substrs=["1"], msg="Was passed compile units")
+
+ # Make a breakpoint that returns a bad value - we should convert that to "modules" so check that:
+ bkpt = target.BreakpointCreateFromScript("resolver.ResolverBadDepth", extra_args, module_list, file_list)
+ self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverBadDepth got no locations.")
+ self.expect("script print resolver.Resolver.got_files", substrs=["2"], msg="Was only passed modules")
+
+ # Make a breakpoint that searches at function depth:
+ bkpt = target.BreakpointCreateFromScript("resolver.ResolverFuncDepth", extra_args, module_list, file_list)
+ self.assertTrue(bkpt.GetNumLocations() > 0, "ResolverFuncDepth got no locations.")
+ self.expect("script print resolver.Resolver.got_files", substrs=["3"], msg="Was only passed modules")
+ self.expect("script print resolver.Resolver.func_list", substrs=["break_on_me", "main", "test_func"], msg="Saw all the functions")
+
+ def do_test_cli(self):
+ target = self.make_target_and_import()
+
+ lldbutil.run_break_set_by_script(self, "resolver.Resolver", extra_options="-k symbol -v break_on_me")
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c
new file mode 100644
index 000000000000..b91ccfc1b43e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/main.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+int
+test_func()
+{
+ return printf("I am a test function.");
+}
+
+void
+break_on_me()
+{
+ printf("I was called.\n");
+}
+
+int
+main()
+{
+ break_on_me();
+ test_func();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py
new file mode 100644
index 000000000000..61f5f2df20ac
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/scripted_bkpt/resolver.py
@@ -0,0 +1,54 @@
+import lldb
+
+class Resolver:
+ got_files = 0
+ func_list = []
+
+ def __init__(self, bkpt, extra_args, dict):
+ self.bkpt = bkpt
+ self.extra_args = extra_args
+ Resolver.func_list = []
+ Resolver.got_files = 0
+
+ def __callback__(self, sym_ctx):
+ sym_name = "not_a_real_function_name"
+ sym_item = self.extra_args.GetValueForKey("symbol")
+ if sym_item.IsValid():
+ sym_name = sym_item.GetStringValue(1000)
+
+ if sym_ctx.compile_unit.IsValid():
+ Resolver.got_files = 1
+ else:
+ Resolver.got_files = 2
+
+ if sym_ctx.function.IsValid():
+ Resolver.got_files = 3
+ func_name = sym_ctx.function.GetName()
+ Resolver.func_list.append(func_name)
+ if sym_name == func_name:
+ self.bkpt.AddLocation(sym_ctx.function.GetStartAddress())
+ return
+
+ if sym_ctx.module.IsValid():
+ sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode)
+ if sym.IsValid():
+ self.bkpt.AddLocation(sym.GetStartAddress())
+
+ def get_short_help(self):
+ return "I am a python breakpoint resolver"
+
+class ResolverModuleDepth(Resolver):
+ def __get_depth__ (self):
+ return lldb.eSearchDepthModule
+
+class ResolverCUDepth(Resolver):
+ def __get_depth__ (self):
+ return lldb.eSearchDepthCompUnit
+
+class ResolverFuncDepth(Resolver):
+ def __get_depth__ (self):
+ return lldb.eSearchDepthFunction
+
+class ResolverBadDepth(Resolver):
+ def __get_depth__ (self):
+ return lldb.kLastSearchDepthKind + 1
diff --git a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
index c615278e8d48..943998a421be 100644
--- a/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
+++ b/packages/Python/lldbsuite/test/functionalities/breakpoint/serialize/TestBreakpointSerialization.py
@@ -180,7 +180,8 @@ class BreakpointSerialization(TestBase):
# actually have locations.
source_bps = lldb.SBBreakpointList(self.orig_target)
- bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+ bkpt = self.orig_target.BreakpointCreateByLocation(
+ lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
bkpt.SetEnabled(False)
bkpt.SetOneShot(True)
bkpt.SetThreadID(10)
@@ -226,7 +227,8 @@ class BreakpointSerialization(TestBase):
all_bps = lldb.SBBreakpointList(self.orig_target)
source_bps = lldb.SBBreakpointList(self.orig_target)
- bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+ bkpt = self.orig_target.BreakpointCreateByLocation(
+ lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
bkpt.SetEnabled(False)
bkpt.SetOneShot(True)
bkpt.SetThreadID(10)
@@ -260,7 +262,8 @@ class BreakpointSerialization(TestBase):
self.check_equivalence(all_bps)
def do_check_names(self):
- bkpt = self.orig_target.BreakpointCreateByLocation("blubby.c", 666)
+ bkpt = self.orig_target.BreakpointCreateByLocation(
+ lldb.SBFileSpec("blubby.c"), 666, 333, 0, lldb.SBFileSpecList())
good_bkpt_name = "GoodBreakpoint"
write_bps = lldb.SBBreakpointList(self.orig_target)
bkpt.AddName(good_bkpt_name)
diff --git a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py
index c6ad75f014ee..c1595cf25515 100644
--- a/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py
+++ b/packages/Python/lldbsuite/test/functionalities/command_script_immediate_output/TestCommandScriptImmediateOutput.py
@@ -28,6 +28,7 @@ class CommandScriptImmediateOutputTestCase (PExpectTest):
oslist=["windows"],
bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
@expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139")
+ @skipIfDarwin
def test_command_script_immediate_output_console(self):
"""Test that LLDB correctly allows scripted commands to set immediate output to the console."""
self.launch(timeout=10)
@@ -50,6 +51,7 @@ class CommandScriptImmediateOutputTestCase (PExpectTest):
oslist=["windows"],
bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
@expectedFailureAll(oslist=["freebsd"], bugnumber="llvm.org/pr26139")
+ @skipIfDarwin
def test_command_script_immediate_output_file(self):
"""Test that LLDB correctly allows scripted commands to set immediate output to a file."""
self.launch(timeout=10)
diff --git a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py
index 5d4fcf64511b..c073425a93fb 100644
--- a/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py
+++ b/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py
@@ -43,7 +43,6 @@ class CommandLineCompletionTestCase(TestBase):
self.build()
self.main_source = "main.cpp"
self.main_source_spec = lldb.SBFileSpec(self.main_source)
- self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
'// Break here', self.main_source_spec)
@@ -177,8 +176,8 @@ class CommandLineCompletionTestCase(TestBase):
@skipIfFreeBSD # timing out on the FreeBSD buildbot
def test_settings_s_dash(self):
- """Test that 'settings set -' completes to 'settings set -g'."""
- self.complete_from_to('settings set -', 'settings set -g')
+ """Test that 'settings set --g' completes to 'settings set --global'."""
+ self.complete_from_to('settings set --g', 'settings set --global')
@skipIfFreeBSD # timing out on the FreeBSD buildbot
def test_settings_clear_th(self):
@@ -275,6 +274,22 @@ class CommandLineCompletionTestCase(TestBase):
self.complete_from_to("watchpoint set variable foo --watch w", "watchpoint set variable foo --watch write")
self.complete_from_to('watchpoint set variable foo -w read_', 'watchpoint set variable foo -w read_write')
+ def test_completion_description_commands(self):
+ """Test descriptions of top-level command completions"""
+ self.check_completion_with_desc("", [
+ ["command", "Commands for managing custom LLDB commands."],
+ ["bugreport", "Commands for creating domain-specific bug reports."]
+ ])
+
+ self.check_completion_with_desc("pl", [
+ ["platform", "Commands to manage and create platforms."],
+ ["plugin", "Commands for managing LLDB plugins."]
+ ])
+
+ # Just check that this doesn't crash.
+ self.check_completion_with_desc("comman", [])
+ self.check_completion_with_desc("non-existent-command", [])
+
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
def test_symbol_name(self):
self.build()
@@ -282,39 +297,3 @@ class CommandLineCompletionTestCase(TestBase):
self.complete_from_to('breakpoint set -n Fo',
'breakpoint set -n Foo::Bar(int,\\ int)',
turn_off_re_match=True)
-
- def complete_from_to(self, str_input, patterns, turn_off_re_match=False):
- """Test that the completion mechanism completes str_input to patterns,
- where patterns could be a pattern-string or a list of pattern-strings"""
- # Patterns should not be None in order to proceed.
- self.assertFalse(patterns is None)
- # And should be either a string or list of strings. Check for list type
- # below, if not, make a list out of the singleton string. If patterns
- # is not a string or not a list of strings, there'll be runtime errors
- # later on.
- if not isinstance(patterns, list):
- patterns = [patterns]
-
- interp = self.dbg.GetCommandInterpreter()
- match_strings = lldb.SBStringList()
- num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
- common_match = match_strings.GetStringAtIndex(0)
- if num_matches == 0:
- compare_string = str_input
- else:
- if common_match != None and len(common_match) > 0:
- compare_string = str_input + common_match
- else:
- compare_string = ""
- for idx in range(1, num_matches+1):
- compare_string += match_strings.GetStringAtIndex(idx) + "\n"
-
- for p in patterns:
- if turn_off_re_match:
- self.expect(
- compare_string, msg=COMPLETION_MSG(
- str_input, p, match_strings), exe=False, substrs=[p])
- else:
- self.expect(
- compare_string, msg=COMPLETION_MSG(
- str_input, p, match_strings), exe=False, patterns=[p])
diff --git a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py
index 904fb4c90372..7b123950c23d 100644
--- a/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py
+++ b/packages/Python/lldbsuite/test/functionalities/conditional_break/TestConditionalBreak.py
@@ -34,9 +34,6 @@ class ConditionalBreakTestCase(TestBase):
self.build()
self.simulate_conditional_break_by_user()
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr26265: args in frames other than #0 are not evaluated correctly")
def do_conditional_break(self):
"""Exercise some thread and frame APIs to break if c() is called by a()."""
exe = self.getBuildArtifact("a.out")
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
index 9749061f42d5..4b9de961724b 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-cpp/TestDataFormatterCpp.py
@@ -23,9 +23,6 @@ class CppDataFormatterTestCase(TestBase):
# Find the line number to break at.
self.line = line_number('main.cpp', '// Set break point at this line.')
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24462: Data formatters have problems on Windows")
@skipIf(debug_info="gmodules",
bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")
def test_with_run_command(self):
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp
index aaccb6329acf..1c98f3db24c8 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-script/main.cpp
@@ -50,4 +50,4 @@ int main (int argc, const char * argv[])
int dummy = 1;
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp
index 82ffb2c20d47..665c9fe75d1c 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-skip-summary/main.cpp
@@ -54,4 +54,4 @@ int main()
DeepData_2 data2;
return 0; // Set break point at this line.
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py
index 13b38cbfa702..54e9c346df31 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-smart-array/TestDataFormatterSmartArray.py
@@ -17,9 +17,6 @@ class SmartArrayDataFormatterTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24462, Data formatters have problems on Windows")
def test_with_run_command(self):
"""Test data formatter commands."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py
index 81a76cc65d63..e44ea61d120f 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/TestLibCxxFunction.py
@@ -40,13 +40,17 @@ class LibCxxFunctionTestCase(TestBase):
substrs=['stopped',
'stop reason = breakpoint'])
- f1 = self.get_variable('f1')
- f2 = self.get_variable('f2')
+ self.expect("frame variable f1",
+ substrs=['f1 = Function = foo(int, int)'])
- if self.TraceOn():
- print(f1)
- if self.TraceOn():
- print(f2)
+ self.expect("frame variable f2",
+ substrs=['f2 = Lambda in File main.cpp at Line 27'])
- self.assertTrue(f1.GetValueAsUnsigned(0) != 0, 'f1 has a valid value')
- self.assertTrue(f2.GetValueAsUnsigned(0) != 0, 'f2 has a valid value')
+ self.expect("frame variable f3",
+ substrs=['f3 = Lambda in File main.cpp at Line 31'])
+
+ self.expect("frame variable f4",
+ substrs=['f4 = Function in File main.cpp at Line 17'])
+
+ self.expect("frame variable f5",
+ substrs=['f5 = Function = Bar::add_num(int) const'])
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp
index cfe689b29b01..541fdaca2afa 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp
@@ -13,13 +13,28 @@ int foo(int x, int y) {
return x + y - 1;
}
-int main ()
+struct Bar {
+ int operator()() {
+ return 66 ;
+ }
+ int add_num(int i) const { return i + 3 ; }
+} ;
+
+int main (int argc, char *argv[])
{
int acc = 42;
std::function<int (int,int)> f1 = foo;
std::function<int (int)> f2 = [acc,f1] (int x) -> int {
return x+f1(acc,x);
};
- return f1(acc,acc) + f2(acc); // Set break point at this line.
-}
+ auto f = [](int x, int y) { return x + y; };
+ auto g = [](int x, int y) { return x * y; } ;
+ std::function<int (int,int)> f3 = argc %2 ? f : g ;
+
+ Bar bar1 ;
+ std::function<int ()> f4( bar1 ) ;
+ std::function<int (const Bar&, int)> f5 = &Bar::add_num;
+
+ return f1(acc,acc) + f2(acc) + f3(acc+1,acc+2) + f4() + f5(bar1, 10); // Set break point at this line.
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py
index 90a7e119fb84..86248d1cac24 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/TestDataFormatterLibcxxList.py
@@ -190,6 +190,7 @@ class LibcxxListDataFormatterTestCase(TestBase):
self.runCmd("n") # This gets us past the printf
self.runCmd("n")
+ self.runCmd("n")
# check access-by-index
self.expect("frame variable text_list[0]",
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp
index 6247ca8b2412..da6eca985d20 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/map/main.cpp
@@ -74,4 +74,4 @@ int main()
ss.clear();
thefoo_rw(1); // Set break point at this line.
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp
index e8385994125d..27bdc0a57729 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp
@@ -74,4 +74,4 @@ int main()
ss.clear();
thefoo_rw(1); // Set break point at this line.
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile
new file mode 100644
index 000000000000..19d6fc3e3c25
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../../../../make
+
+CXX_SOURCES := main.cpp
+
+USE_LIBCPP := 1
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -std=c++17 -fno-exceptions
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py
new file mode 100644
index 000000000000..7826305931da
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/TestDataFormatterLibcxxOptional.py
@@ -0,0 +1,75 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LibcxxOptionalDataFormatterTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @add_test_categories(["libc++"])
+ ## We are skipping clang version less that 5.0 since this test requires -std=c++17
+ @skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0'])
+ ## We are skipping gcc version less that 5.1 since this test requires -std=c++17
+ @skipIf(compiler="gcc", compiler_version=['<', '5.1'])
+
+ def test_with_run_command(self):
+ """Test that that file and class static variables display correctly."""
+ self.build()
+ self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
+
+ bkpt = self.target().FindBreakpointByID(
+ lldbutil.run_break_set_by_source_regexp(
+ self, "break here"))
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped',
+ 'stop reason = breakpoint'])
+
+ self.runCmd( "frame variable has_optional" )
+
+ output = self.res.GetOutput()
+
+ ## The variable has_optional tells us if the test program
+ ## detected we have a sufficient libc++ version to support optional
+ ## false means we do not and therefore should skip the test
+ if output.find("(bool) has_optional = false") != -1 :
+ self.skipTest( "Optional not supported" )
+
+ lldbutil.continue_to_breakpoint(self.process(), bkpt)
+
+ self.expect("frame variable number_not_engaged",
+ substrs=['Has Value=false'])
+
+ self.expect("frame variable number_engaged",
+ substrs=['Has Value=true',
+ 'Value = 42',
+ '}'])
+
+ self.expect("frame var numbers",
+ substrs=['(optional_int_vect) numbers = Has Value=true {',
+ 'Value = size=4 {',
+ '[0] = 1',
+ '[1] = 2',
+ '[2] = 3',
+ '[3] = 4',
+ '}',
+ '}'])
+
+ self.expect("frame var ostring",
+ substrs=['(optional_string) ostring = Has Value=true {',
+ 'Value = "hello"',
+ '}'])
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp
new file mode 100644
index 000000000000..16bb98c61056
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/optional/main.cpp
@@ -0,0 +1,42 @@
+#include <cstdio>
+#include <string>
+#include <vector>
+
+// If we have libc++ 4.0 or greater we should have <optional>
+// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html
+#if _LIBCPP_VERSION >= 4000
+#include <optional>
+#define HAVE_OPTIONAL 1
+#else
+#define HAVE_OPTIONAL 0
+#endif
+
+
+int main()
+{
+ bool has_optional = HAVE_OPTIONAL ;
+
+ printf( "%d\n", has_optional ) ; // break here
+
+#if HAVE_OPTIONAL == 1
+ using int_vect = std::vector<int> ;
+ using optional_int = std::optional<int> ;
+ using optional_int_vect = std::optional<int_vect> ;
+ using optional_string = std::optional<std::string> ;
+
+ optional_int number_not_engaged ;
+ optional_int number_engaged = 42 ;
+
+ printf( "%d\n", *number_engaged) ;
+
+ optional_int_vect numbers{{1,2,3,4}} ;
+
+ printf( "%d %d\n", numbers.value()[0], numbers.value()[1] ) ;
+
+ optional_string ostring = "hello" ;
+
+ printf( "%s\n", ostring->c_str() ) ;
+#endif
+
+ return 0; // break here
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile
index 1f609a41d908..937b47ea06b0 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/Makefile
@@ -4,4 +4,4 @@ CXX_SOURCES := main.cpp
USE_LIBCPP := 1
include $(LEVEL)/Makefile.rules
-CXXFLAGS += -O0
+CXXFLAGS += -std=c++11 -O0
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
index 4574a044488c..63164f78e00e 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/TestDataFormatterLibcxxString.py
@@ -68,7 +68,9 @@ class LibcxxStringDataFormatterTestCase(TestBase):
'(%s::string) q = "hello world"'%ns,
'(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns,
'(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns,
- '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns])
+ '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns,
+ '(%s::u16string) u16_string = u"ß水氶"'%ns,
+ '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns])
self.runCmd("n")
@@ -98,4 +100,6 @@ class LibcxxStringDataFormatterTestCase(TestBase):
'(%s::string) q = "hello world"'%ns,
'(%s::string) Q = "quite a long std::strin with lots of info inside it"'%ns,
'(%s::string) IHaveEmbeddedZeros = "a\\0b\\0c\\0d"'%ns,
- '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns])
+ '(%s::wstring) IHaveEmbeddedZerosToo = L"hello world!\\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監"'%ns,
+ '(%s::u16string) u16_string = u"ß水氶"'%ns,
+ '(%s::u32string) u32_string = U"🍄🍅🍆🍌"'%ns])
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp
index 9ca0da39cfc8..838a4c71be1a 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/string/main.cpp
@@ -10,6 +10,8 @@ int main()
std::string TheVeryLongOne("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890someText1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
std::string IHaveEmbeddedZeros("a\0b\0c\0d",7);
std::wstring IHaveEmbeddedZerosToo(L"hello world!\0てざ ル゜䋨ミ㠧槊 きゅへ狦穤襩 じゃ馩リョ 䤦監", 38);
+ std::u16string u16_string(u"ß水氶");
+ std::u32string u32_string(U"🍄🍅🍆🍌");
S.assign(L"!!!!!"); // Set break point at this line.
return 0;
}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile
new file mode 100644
index 000000000000..a6ea665ef63c
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../../../../make
+
+CXX_SOURCES := main.cpp
+
+USE_LIBCPP := 1
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -std=c++17
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py
new file mode 100644
index 000000000000..e1f6961b465d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/TestDataFormatterLibcxxVariant.py
@@ -0,0 +1,83 @@
+"""
+Test lldb data formatter subsystem.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class LibcxxVariantDataFormatterTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @add_test_categories(["libc++"])
+ ## We are skipping clang version less that 5.0 since this test requires -std=c++17
+ @skipIf(oslist=no_match(["macosx"]), compiler="clang", compiler_version=['<', '5.0'])
+ ## We are skipping gcc version less that 5.1 since this test requires -std=c++17
+ @skipIf(compiler="gcc", compiler_version=['<', '5.1'])
+ ## std::get is unavailable for std::variant before macOS 10.14
+ @skipIf(macos_version=["<", "10.14"])
+
+ def test_with_run_command(self):
+ """Test that that file and class static variables display correctly."""
+ self.build()
+
+ (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here',
+ lldb.SBFileSpec("main.cpp", False))
+
+ self.runCmd( "frame variable has_variant" )
+
+ output = self.res.GetOutput()
+
+ ## The variable has_variant tells us if the test program
+ ## detected we have a sufficient libc++ version to support variant
+ ## false means we do not and therefore should skip the test
+ if output.find("(bool) has_variant = false") != -1 :
+ self.skipTest( "std::variant not supported" )
+
+ lldbutil.continue_to_breakpoint(self.process, bkpt)
+
+ self.expect("frame variable v1",
+ substrs=['v1 = Active Type = int {',
+ 'Value = 12',
+ '}'])
+
+ self.expect("frame variable v1_ref",
+ substrs=['v1_ref = Active Type = int : {',
+ 'Value = 12',
+ '}'])
+
+ self.expect("frame variable v_v1",
+ substrs=['v_v1 = Active Type = std::__1::variant<int, double, char> {',
+ 'Value = Active Type = int {',
+ 'Value = 12',
+ '}',
+ '}'])
+
+ lldbutil.continue_to_breakpoint(self.process, bkpt)
+
+ self.expect("frame variable v1",
+ substrs=['v1 = Active Type = double {',
+ 'Value = 2',
+ '}'])
+
+ lldbutil.continue_to_breakpoint(self.process, bkpt)
+
+ self.expect("frame variable v2",
+ substrs=['v2 = Active Type = double {',
+ 'Value = 2',
+ '}'])
+
+ self.expect("frame variable v3",
+ substrs=['v3 = Active Type = char {',
+ 'Value = \'A\'',
+ '}'])
+
+ self.expect("frame variable v_no_value",
+ substrs=['v_no_value = No Value'])
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp
new file mode 100644
index 000000000000..c0bc4ae12c1a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/variant/main.cpp
@@ -0,0 +1,60 @@
+#include <cstdio>
+#include <string>
+#include <vector>
+
+// If we have libc++ 4.0 or greater we should have <variant>
+// According to libc++ C++1z status page https://libcxx.llvm.org/cxx1z_status.html
+#if _LIBCPP_VERSION >= 4000
+#include <variant>
+#define HAVE_VARIANT 1
+#else
+#define HAVE_VARIANT 0
+#endif
+
+struct S {
+ operator int() { throw 42; }
+} ;
+
+
+int main()
+{
+ bool has_variant = HAVE_VARIANT ;
+
+ printf( "%d\n", has_variant ) ; // break here
+
+#if HAVE_VARIANT == 1
+ std::variant<int, double, char> v1;
+ std::variant<int, double, char> &v1_ref = v1;
+ std::variant<int, double, char> v2;
+ std::variant<int, double, char> v3;
+ std::variant<std::variant<int,double,char>> v_v1 ;
+ std::variant<int, double, char> v_no_value;
+
+ v1 = 12; // v contains int
+ v_v1 = v1 ;
+ int i = std::get<int>(v1);
+ printf( "%d\n", i ); // break here
+
+ v2 = 2.0 ;
+ double d = std::get<double>(v2) ;
+ printf( "%f\n", d );
+
+ v3 = 'A' ;
+ char c = std::get<char>(v3) ;
+ printf( "%d\n", c );
+
+ // Checking v1 above and here to make sure we done maintain the incorrect
+ // state when we change its value.
+ v1 = 2.0;
+ d = std::get<double>(v1) ;
+ printf( "%f\n", d ); // break here
+
+ try {
+ v_no_value.emplace<0>(S());
+ } catch( ... ) {}
+
+ printf( "%zu\n", v_no_value.index() ) ;
+#endif
+
+ return 0; // break here
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py
index 237e27fe1f31..06d3cda61be2 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libcxx/vector/TestDataFormatterLibcxxVector.py
@@ -51,8 +51,6 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
substrs=['1234'])
@add_test_categories(["libc++"])
- @skipIf(debug_info="gmodules",
- bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")
def test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
self.build()
@@ -180,8 +178,6 @@ class LibcxxVectorDataFormatterTestCase(TestBase):
substrs=['vector has 0 items'])
@add_test_categories(["libc++"])
- @skipIf(debug_info="gmodules",
- bugnumber="https://bugs.llvm.org/show_bug.cgi?id=36048")
def test_ref_and_ptr(self):
"""Test that that file and class static variables display correctly."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp
index d7b046c5bff8..7ddffd19012e 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/main.cpp
@@ -35,4 +35,4 @@ int main()
svter svI = sv.begin();
return 0; // Set break point at this line.
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp
index 568c35efe072..d5e5b212782d 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/main.cpp
@@ -52,4 +52,4 @@ int main()
ss.clear();// Set break point at this line.
return 0;// Set break point at this line.
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp
index 4a9b4fc7d0db..f6e56cf12456 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/main.cpp
@@ -9,4 +9,4 @@ int main()
std::string Q("quite a long std::strin with lots of info inside it");
S.assign(L"!!!!!"); // Set break point at this line.
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
index 5d05418a8b49..f782a2a8baea 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/unique_ptr/TestDataFormatterStdUniquePtr.py
@@ -66,6 +66,7 @@ class StdUniquePtrDataFormatterTestCase(TestBase):
@skipIfWindows # libstdcpp not ported to Windows
@skipIfDarwin # doesn't compile on Darwin
@skipIfwatchOS # libstdcpp not ported to watchos
+ @add_test_categories(["libstdcxx"])
def test_recursive_unique_ptr(self):
# Tests that LLDB can handle when we have a loop in the unique_ptr
# reference chain and that it correctly handles the different options
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py
index 08768a61bd9d..138b32802951 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/data-formatter-synthval/TestDataFormatterSynthVal.py
@@ -24,9 +24,6 @@ class DataFormatterSynthValueTestCase(TestBase):
self.line = line_number('main.cpp', 'break here')
@skipIfFreeBSD # llvm.org/pr20545 bogus output confuses buildbot parser
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24462, Data formatters have problems on Windows")
def test_with_run_command(self):
"""Test using Python synthetic children provider to provide a value."""
self.build()
@@ -107,7 +104,7 @@ class DataFormatterSynthValueTestCase(TestBase):
# check that an aptly defined synthetic provider does not affect
# one-lining
self.expect(
- "expression struct S { myInt theInt{12}; }; S()",
+ "expression struct Struct { myInt theInt{12}; }; Struct()",
substrs=['(theInt = 12)'])
# check that we can use a synthetic value in a summary
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp
index fec7907e0031..90571b59f81e 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/synthcapping/main.cpp
@@ -59,4 +59,4 @@ int main()
256*256*256*'D');
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp
index 649c1e09a6a5..5b43102c268c 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/typedef_array/main.cpp
@@ -9,6 +9,11 @@
typedef int Foo;
int main() {
+ // CHECK: (Foo [3]) array = {
+ // CHECK-NEXT: (Foo) [0] = 1
+ // CHECK-NEXT: (Foo) [1] = 2
+ // CHECK-NEXT: (Foo) [2] = 3
+ // CHECK-NEXT: }
Foo array[3] = {1,2,3};
- return 0; //% self.expect("frame variable array --show-types --", substrs = ['(Foo [3]) array = {','(Foo) [0] = 1','(Foo) [1] = 2','(Foo) [2] = 3'])
+ return 0; //% self.filecheck("frame variable array --show-types --", 'main.cpp')
}
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py
index d3c04afe91eb..670edad37f9e 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/TestDataFormatterVarScriptFormatting.py
@@ -14,7 +14,7 @@ from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-class PythonSynthDataFormatterTestCase(TestBase):
+class DataFormatterVarScriptFormatting(TestBase):
mydir = TestBase.compute_mydir(__file__)
diff --git a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp
index 4dc94af3566c..e9a36f911964 100644
--- a/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp
+++ b/packages/Python/lldbsuite/test/functionalities/data-formatter/varscript_formatting/main.cpp
@@ -5,4 +5,4 @@ int main() {
something<int> x;
something<void*> y;
return 0; // Set breakpoint here.
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile b/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile
index 8a7102e347af..8a7102e347af 100644
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/Makefile
+++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/Makefile
diff --git a/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py b/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py
new file mode 100644
index 000000000000..1eeaeeffa87b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/TestDeletedExecutable.py
@@ -0,0 +1,31 @@
+"""
+Test process attach/resume.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestDeletedExecutable(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipIfWindows # cannot delete a running executable
+ @expectedFailureAll(oslist=["linux"]) # determining the architecture of the process fails
+ def test(self):
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ popen = self.spawnSubprocess(exe)
+ self.addTearDownHook(self.cleanupSubprocesses)
+ os.remove(exe)
+
+ self.runCmd("process attach -p " + str(popen.pid))
+ self.runCmd("kill")
diff --git a/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp b/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp
new file mode 100644
index 000000000000..ad5d18732eac
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/deleted-executable/main.cpp
@@ -0,0 +1,9 @@
+#include <chrono>
+#include <thread>
+
+int main(int argc, char const *argv[])
+{
+ lldb_enable_attach();
+
+ std::this_thread::sleep_for(std::chrono::seconds(30));
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py
index 52f9daf6bd45..91b858b4665a 100644
--- a/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py
+++ b/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py
@@ -18,9 +18,6 @@ class DisassemblyTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
NO_DEBUG_INFO_TESTCASE = True
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="function names print fully demangled instead of name-only")
def test(self):
self.build()
target, _, _, bkpt = lldbutil.run_to_source_breakpoint(self,
diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py
deleted file mode 100644
index 0f130b3ecbab..000000000000
--- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/TestConvenienceVariables.py
+++ /dev/null
@@ -1,108 +0,0 @@
-"""Test convenience variables when you drop in from lldb prompt into an embedded interpreter."""
-
-from __future__ import print_function
-
-
-import os
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class ConvenienceVariablesCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line number to break on inside main.cpp.
- self.line = line_number('main.c', 'Hello world.')
-
- @skipIfFreeBSD # llvm.org/pr17228
- @skipIfRemote
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_with_run_commands(self):
- """Test convenience variables lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame."""
- self.build()
- import pexpect
- exe = self.getBuildArtifact("a.out")
- prompt = "(lldb) "
- python_prompt = ">>> "
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn(
- '%s %s %s' %
- (lldbtest_config.lldbExec, self.lldbOption, exe))
- child = self.child
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- # Set the breakpoint, run the inferior, when it breaks, issue print on
- # the various convenience variables.
- child.expect_exact(prompt)
- child.sendline('breakpoint set -f main.c -l %d' % self.line)
- child.expect_exact(prompt)
- child.sendline('run')
- child.expect_exact("stop reason = breakpoint 1.1")
- child.expect_exact(prompt)
- child.sendline('script')
- child.expect_exact(python_prompt)
-
- # Set a flag so that we know during teardown time, we need to exit the
- # Python interpreter, then the lldb interpreter.
- self.child_in_script_interpreter = True
-
- child.sendline('print(lldb.debugger)')
- child.expect_exact(python_prompt)
- self.expect(child.before, exe=False,
- patterns=['Debugger \(instance: .*, id: \d\)'])
-
- child.sendline('print(lldb.target)')
- child.expect_exact(python_prompt)
- self.expect(child.before, exe=False,
- substrs=['a.out'])
-
- child.sendline('print(lldb.process)')
- child.expect_exact(python_prompt)
- self.expect(child.before, exe=False, patterns=[
- 'SBProcess: pid = \d+, state = stopped, threads = \d, executable = a.out'])
-
- child.sendline('print(lldb.thread.GetStopDescription(100))')
- child.expect_exact(python_prompt)
- self.expect(
- child.before,
- exe=False,
- patterns=[
- 'breakpoint 1\.1'])
-
- child.sendline('lldb.frame.GetLineEntry().GetLine()')
- child.expect_exact(python_prompt)
- line_number = "%d"%(self.line)
- self.expect(
- child.before,
- exe=False,
- substrs=[
- line_number])
-
- child.sendline('lldb.frame.GetLineEntry().GetFileSpec().GetFilename()')
- child.expect_exact(python_prompt)
- line_number = "%d"%(self.line)
- self.expect(
- child.before,
- exe=False,
- substrs=[
- "main.c"])
-
- child.sendline('lldb.frame.GetFunctionName()')
- child.expect_exact(python_prompt)
- line_number = "%d"%(self.line)
- self.expect(
- child.before,
- exe=False,
- substrs=[
- "main"])
diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c b/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c
deleted file mode 100644
index 277aa54a4eea..000000000000
--- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/main.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <stdio.h>
-
-int main(int argc, char const *argv[]) {
- printf("Hello world.\n");
- return 0;
-}
diff --git a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py
index 8126a7ec750c..2cec254acc0c 100644
--- a/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py
+++ b/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py
@@ -31,12 +31,14 @@ class ExecTestCase(TestBase):
@skipUnlessDarwin
@expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532")
@expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems
+ @skipIfSanitized # rdar://problem/43756823
def test_hitting_exec (self):
self.do_test(False)
@skipUnlessDarwin
@expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532")
@expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems
+ @skipIfSanitized # rdar://problem/43756823
def test_skipping_exec (self):
self.do_test(True)
@@ -61,6 +63,8 @@ class ExecTestCase(TestBase):
None, None, self.get_process_working_directory())
self.assertTrue(process, PROCESS_IS_VALID)
+ if self.TraceOn():
+ self.runCmd("settings show target.process.stop-on-exec", check=False)
if skip_exec:
self.dbg.HandleCommand("settings set target.process.stop-on-exec false")
def cleanup():
@@ -94,6 +98,8 @@ class ExecTestCase(TestBase):
process.Continue()
if not skip_exec:
+ self.assertFalse(process.GetState() == lldb.eStateExited,
+ "Process should not have exited!")
self.assertTrue(process.GetState() == lldb.eStateStopped,
"Process should be stopped at __dyld_start")
diff --git a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile
index 0d70f2595019..0d70f2595019 100644
--- a/packages/Python/lldbsuite/test/expression_command/multiline/Makefile
+++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/Makefile
diff --git a/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py
new file mode 100644
index 000000000000..56abc19f4f30
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/TestExprEntryBP.py
@@ -0,0 +1,34 @@
+"""
+Tests expressions evaluation when the breakpoint on module's entry is set.
+"""
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+class ExprEntryBPTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_expr_entry_bp(self):
+ """Tests expressions evaluation when the breakpoint on module's entry is set."""
+ self.build()
+ self.main_source_file = lldb.SBFileSpec("main.c")
+
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file)
+
+ self.assertEqual(1, bkpt.GetNumLocations())
+ entry = bkpt.GetLocationAtIndex(0).GetAddress().GetModule().GetObjectFileEntryPointAddress()
+ self.assertTrue(entry.IsValid(), "Can't get a module entry point")
+
+ entry_bp = target.BreakpointCreateBySBAddress(entry)
+ self.assertTrue(entry_bp.IsValid(), "Can't set a breakpoint on the module entry point")
+
+ result = target.EvaluateExpression("sum(7, 1)")
+ self.assertTrue(result.IsValid(), "Can't evaluate expression")
+ self.assertEqual(8, result.GetValueAsSigned())
+
+ def setUp(self):
+ TestBase.setUp(self)
diff --git a/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c
new file mode 100644
index 000000000000..168fc9c8ccbf
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/expr-entry-bp/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+int sum(int x, int y) {
+ return x + y;
+}
+
+int main() {
+ printf("Set a breakpoint here.\n");
+ return sum(-1, 1);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile
new file mode 100644
index 000000000000..45f00b3e9861
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/Makefile
@@ -0,0 +1,10 @@
+LEVEL = ../../make
+
+OBJC_SOURCES := main.m
+
+CFLAGS_EXTRAS += -g0 # No debug info.
+MAKE_DSYM := NO
+
+include $(LEVEL)/Makefile.rules
+
+LDFLAGS += -framework Foundation
diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py
new file mode 100644
index 000000000000..1162157bad57
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/TestFrameRecognizer.py
@@ -0,0 +1,117 @@
+# encoding: utf-8
+"""
+Test lldb's frame recognizers.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+import recognizer
+
+class FrameRecognizerTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipUnlessDarwin
+ def test_frame_recognizer_1(self):
+ self.build()
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ self.runCmd("command script import " + os.path.join(self.getSourceDir(), "recognizer.py"))
+
+ self.expect("frame recognizer list",
+ substrs=['no matching results found.'])
+
+ self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo")
+
+ self.expect("frame recognizer list",
+ substrs=['0: recognizer.MyFrameRecognizer, module a.out, function foo'])
+
+ self.runCmd("frame recognizer add -l recognizer.MyOtherFrameRecognizer -s a.out -n bar -x")
+
+ self.expect("frame recognizer list",
+ substrs=['0: recognizer.MyFrameRecognizer, module a.out, function foo',
+ '1: recognizer.MyOtherFrameRecognizer, module a.out, function bar (regexp)'
+ ])
+
+ self.runCmd("frame recognizer delete 0")
+
+ self.expect("frame recognizer list",
+ substrs=['1: recognizer.MyOtherFrameRecognizer, module a.out, function bar (regexp)'])
+
+ self.runCmd("frame recognizer clear")
+
+ self.expect("frame recognizer list",
+ substrs=['no matching results found.'])
+
+ self.runCmd("frame recognizer add -l recognizer.MyFrameRecognizer -s a.out -n foo")
+
+ lldbutil.run_break_set_by_symbol(self, "foo")
+ self.runCmd("r")
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
+
+ process = target.GetProcess()
+ thread = process.GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ self.assertEqual(frame.GetSymbol().GetName(), "foo")
+ self.assertFalse(frame.GetLineEntry().IsValid())
+
+ self.expect("frame variable",
+ substrs=['(int) a = 42', '(int) b = 56'])
+
+ # Recognized arguments don't show up by default...
+ variables = frame.GetVariables(lldb.SBVariablesOptions())
+ self.assertEqual(variables.GetSize(), 0)
+
+ # ...unless you set target.display-recognized-arguments to 1...
+ self.runCmd("settings set target.display-recognized-arguments 1")
+ variables = frame.GetVariables(lldb.SBVariablesOptions())
+ self.assertEqual(variables.GetSize(), 2)
+
+ # ...and you can reset it back to 0 to hide them again...
+ self.runCmd("settings set target.display-recognized-arguments 0")
+ variables = frame.GetVariables(lldb.SBVariablesOptions())
+ self.assertEqual(variables.GetSize(), 0)
+
+ # ... or explicitly ask for them with SetIncludeRecognizedArguments(True).
+ opts = lldb.SBVariablesOptions()
+ opts.SetIncludeRecognizedArguments(True)
+ variables = frame.GetVariables(opts)
+
+ self.assertEqual(variables.GetSize(), 2)
+ self.assertEqual(variables.GetValueAtIndex(0).name, "a")
+ self.assertEqual(variables.GetValueAtIndex(0).signed, 42)
+ self.assertEqual(variables.GetValueAtIndex(1).name, "b")
+ self.assertEqual(variables.GetValueAtIndex(1).signed, 56)
+
+ self.expect("frame recognizer info 0",
+ substrs=['frame 0 is recognized by recognizer.MyFrameRecognizer'])
+
+ self.expect("frame recognizer info 999", error=True,
+ substrs=['no frame with index 999'])
+
+ self.expect("frame recognizer info 1",
+ substrs=['frame 1 not recognized by any recognizer'])
+
+ # FIXME: The following doesn't work yet, but should be fixed.
+ """
+ lldbutil.run_break_set_by_symbol(self, "bar")
+ self.runCmd("c")
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
+
+ self.expect("frame variable -t",
+ substrs=['(int *) a = '])
+
+ self.expect("frame variable -t *a",
+ substrs=['*a = 78'])
+ """
diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m
new file mode 100644
index 000000000000..51103ae038ac
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/main.m
@@ -0,0 +1,28 @@
+//===-- main.m ------------------------------------------------*- ObjC -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#import <Foundation/Foundation.h>
+
+void foo(int a, int b)
+{
+ printf("%d %d\n", a, b);
+}
+
+void bar(int *ptr)
+{
+ printf("%d\n", *ptr);
+}
+
+int main (int argc, const char * argv[])
+{
+ foo(42, 56);
+ int i = 78;
+ bar(&i);
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py
new file mode 100644
index 000000000000..a8a506745118
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/frame-recognizer/recognizer.py
@@ -0,0 +1,21 @@
+# encoding: utf-8
+
+import lldb
+
+class MyFrameRecognizer(object):
+ def get_recognized_arguments(self, frame):
+ if frame.name == "foo":
+ arg1 = frame.EvaluateExpression("$arg1").signed
+ arg2 = frame.EvaluateExpression("$arg2").signed
+ val1 = lldb.target.CreateValueFromExpression("a", "%d" % arg1)
+ val2 = lldb.target.CreateValueFromExpression("b", "%d" % arg2)
+ return [val1, val2]
+ elif frame.name == "bar":
+ arg1 = frame.EvaluateExpression("$arg1").signed
+ val1 = lldb.target.CreateValueFromExpression("a", "(int *)%d" % arg1)
+ return [val1]
+ return []
+
+class MyOtherFrameRecognizer(object):
+ def get_recognized_arguments(self, frame):
+ return []
diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py
new file mode 100644
index 000000000000..6e28d5b54052
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestArmRegisterDefinition.py
@@ -0,0 +1,130 @@
+from __future__ import print_function
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+class TestArmRegisterDefinition(GDBRemoteTestBase):
+
+ @skipIfXmlSupportMissing
+ @skipIfRemote
+ def test(self):
+ """
+ Test lldb's parsing of the <architecture> tag in the target.xml register
+ description packet.
+ """
+ class MyResponder(MockGDBServerResponder):
+
+ def qXferRead(self, obj, annex, offset, length):
+ if annex == "target.xml":
+ return """<?xml version="1.0"?>
+ <!DOCTYPE feature SYSTEM "gdb-target.dtd">
+ <target>
+ <architecture>arm</architecture>
+ <feature name="org.gnu.gdb.arm.m-profile">
+ <reg name="r0" bitsize="32" type="uint32" group="general"/>
+ <reg name="r1" bitsize="32" type="uint32" group="general"/>
+ <reg name="r2" bitsize="32" type="uint32" group="general"/>
+ <reg name="r3" bitsize="32" type="uint32" group="general"/>
+ <reg name="r4" bitsize="32" type="uint32" group="general"/>
+ <reg name="r5" bitsize="32" type="uint32" group="general"/>
+ <reg name="r6" bitsize="32" type="uint32" group="general"/>
+ <reg name="r7" bitsize="32" type="uint32" group="general"/>
+ <reg name="r8" bitsize="32" type="uint32" group="general"/>
+ <reg name="r9" bitsize="32" type="uint32" group="general"/>
+ <reg name="r10" bitsize="32" type="uint32" group="general"/>
+ <reg name="r11" bitsize="32" type="uint32" group="general"/>
+ <reg name="r12" bitsize="32" type="uint32" group="general"/>
+ <reg name="sp" bitsize="32" type="data_ptr" group="general"/>
+ <reg name="lr" bitsize="32" type="uint32" group="general"/>
+ <reg name="pc" bitsize="32" type="code_ptr" group="general"/>
+ <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/>
+ <reg name="MSP" bitsize="32" regnum="26" type="uint32" group="general"/>
+ <reg name="PSP" bitsize="32" regnum="27" type="uint32" group="general"/>
+ <reg name="PRIMASK" bitsize="32" regnum="28" type="uint32" group="general"/>
+ <reg name="BASEPRI" bitsize="32" regnum="29" type="uint32" group="general"/>
+ <reg name="FAULTMASK" bitsize="32" regnum="30" type="uint32" group="general"/>
+ <reg name="CONTROL" bitsize="32" regnum="31" type="uint32" group="general"/>
+ <reg name="FPSCR" bitsize="32" type="uint32" group="float"/>
+ <reg name="s0" bitsize="32" type="float" group="float"/>
+ <reg name="s1" bitsize="32" type="float" group="float"/>
+ <reg name="s2" bitsize="32" type="float" group="float"/>
+ <reg name="s3" bitsize="32" type="float" group="float"/>
+ <reg name="s4" bitsize="32" type="float" group="float"/>
+ <reg name="s5" bitsize="32" type="float" group="float"/>
+ <reg name="s6" bitsize="32" type="float" group="float"/>
+ <reg name="s7" bitsize="32" type="float" group="float"/>
+ <reg name="s8" bitsize="32" type="float" group="float"/>
+ <reg name="s9" bitsize="32" type="float" group="float"/>
+ <reg name="s10" bitsize="32" type="float" group="float"/>
+ <reg name="s11" bitsize="32" type="float" group="float"/>
+ <reg name="s12" bitsize="32" type="float" group="float"/>
+ <reg name="s13" bitsize="32" type="float" group="float"/>
+ <reg name="s14" bitsize="32" type="float" group="float"/>
+ <reg name="s15" bitsize="32" type="float" group="float"/>
+ <reg name="s16" bitsize="32" type="float" group="float"/>
+ <reg name="s17" bitsize="32" type="float" group="float"/>
+ <reg name="s18" bitsize="32" type="float" group="float"/>
+ <reg name="s19" bitsize="32" type="float" group="float"/>
+ <reg name="s20" bitsize="32" type="float" group="float"/>
+ <reg name="s21" bitsize="32" type="float" group="float"/>
+ <reg name="s22" bitsize="32" type="float" group="float"/>
+ <reg name="s23" bitsize="32" type="float" group="float"/>
+ <reg name="s24" bitsize="32" type="float" group="float"/>
+ <reg name="s25" bitsize="32" type="float" group="float"/>
+ <reg name="s26" bitsize="32" type="float" group="float"/>
+ <reg name="s27" bitsize="32" type="float" group="float"/>
+ <reg name="s28" bitsize="32" type="float" group="float"/>
+ <reg name="s29" bitsize="32" type="float" group="float"/>
+ <reg name="s30" bitsize="32" type="float" group="float"/>
+ <reg name="s31" bitsize="32" type="float" group="float"/>
+ </feature>
+ </target>""", False
+ else:
+ return None, False
+
+ def readRegister(self, regnum):
+ return "E01"
+
+ def readRegisters(self):
+ return "20000000f8360020001000002fcb0008f8360020a0360020200c0020000000000000000000000000000000000000000000000000b87f0120b7d100082ed2000800000001b87f01200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+
+ def haltReason(self):
+ return "S05"
+
+ def qfThreadInfo(self):
+ return "mdead"
+
+ def qC(self):
+ return ""
+
+ def qSupported(self, client_supported):
+ return "PacketSize=4000;qXfer:memory-map:read-;QStartNoAckMode+;qXfer:threads:read+;hwbreak+;qXfer:features:read+"
+
+ def QThreadSuffixSupported(self):
+ return "OK"
+
+ def QListThreadsInStopReply(self):
+ return "OK"
+
+ self.server.responder = MyResponder()
+ if self.TraceOn():
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("log enable gdb-remote packets", result)
+ self.dbg.SetDefaultArchitecture("armv7em")
+ target = self.dbg.CreateTargetWithFileAndArch(None, None)
+
+ process = self.connect(target)
+
+ if self.TraceOn():
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("target list", result)
+ print(result.GetOutput())
+
+ r0_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("r0")
+ self.assertEqual(r0_valobj.GetValueAsUnsigned(), 0x20)
+
+ pc_valobj = process.GetThreadAtIndex(0).GetFrameAtIndex(0).FindRegister("pc")
+ self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x0800d22e)
diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py
new file mode 100644
index 000000000000..66a271e126dc
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestNoWatchpointSupportInfo.py
@@ -0,0 +1,64 @@
+from __future__ import print_function
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+class TestNoWatchpointSupportInfo(GDBRemoteTestBase):
+
+ @skipIfXmlSupportMissing
+ @skipIfRemote
+ def test(self):
+ """
+ Test lldb's parsing of the <architecture> tag in the target.xml register
+ description packet.
+ """
+ class MyResponder(MockGDBServerResponder):
+
+ def haltReason(self):
+ return "T02thread:1ff0d;thread-pcs:10001bc00;"
+
+ def threadStopInfo(self, threadnum):
+ if threadnum == 0x1ff0d:
+ return "T02thread:1ff0d;thread-pcs:10001bc00;"
+
+ def setBreakpoint(self, packet):
+ if packet.startswith("Z2,"):
+ return "OK"
+
+ def qXferRead(self, obj, annex, offset, length):
+ if annex == "target.xml":
+ return """<?xml version="1.0"?>
+ <target version="1.0">
+ <architecture>i386:x86-64</architecture>
+ <feature name="org.gnu.gdb.i386.core">
+ <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
+ </feature>
+ </target>""", False
+ else:
+ return None, False
+
+ self.server.responder = MyResponder()
+ if self.TraceOn():
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("log enable gdb-remote packets", result)
+ self.dbg.SetDefaultArchitecture("x86_64")
+ target = self.dbg.CreateTargetWithFileAndArch(None, None)
+
+ process = self.connect(target)
+
+ if self.TraceOn():
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("target list", result)
+ print(result.GetOutput())
+
+
+ err = lldb.SBError()
+ wp = target.WatchAddress(0x100, 8, False, True, err)
+ if self.TraceOn() and (err.Fail() or wp.IsValid == False):
+ strm = lldb.SBStream()
+ err.GetDescription(strm)
+ print("watchpoint failed: %s" % strm.GetData())
+ self.assertTrue(wp.IsValid())
diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py
new file mode 100644
index 000000000000..7b733e77e679
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestStopPCs.py
@@ -0,0 +1,46 @@
+from __future__ import print_function
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+
+class TestStopPCs(GDBRemoteTestBase):
+
+ @skipIfXmlSupportMissing
+ def test(self):
+ class MyResponder(MockGDBServerResponder):
+ def haltReason(self):
+ return "T02thread:1ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;"
+
+ def threadStopInfo(self, threadnum):
+ if threadnum == 0x1ff0d:
+ return "T02thread:1ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;"
+ if threadnum == 0x2ff0d:
+ return "T00thread:2ff0d;threads:1ff0d,2ff0d;thread-pcs:10001bc00,10002bc00;"
+
+ def qXferRead(self, obj, annex, offset, length):
+ if annex == "target.xml":
+ return """<?xml version="1.0"?>
+ <target version="1.0">
+ <architecture>i386:x86-64</architecture>
+ <feature name="org.gnu.gdb.i386.core">
+ <reg name="rip" bitsize="64" regnum="0" type="code_ptr" group="general"/>
+ </feature>
+ </target>""", False
+ else:
+ return None, False
+
+ self.server.responder = MyResponder()
+ target = self.dbg.CreateTarget('')
+ if self.TraceOn():
+ self.runCmd("log enable gdb-remote packets")
+ process = self.connect(target)
+
+ self.assertEqual(process.GetNumThreads(), 2)
+ th0 = process.GetThreadAtIndex(0)
+ th1 = process.GetThreadAtIndex(1)
+ self.assertEqual(th0.GetThreadID(), 0x1ff0d)
+ self.assertEqual(th1.GetThreadID(), 0x2ff0d)
+ self.assertEqual(th0.GetFrameAtIndex(0).GetPC(), 0x10001bc00)
+ self.assertEqual(th1.GetFrameAtIndex(0).GetPC(), 0x10002bc00)
diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py
index 184867e480b4..57c5ff0aac25 100644
--- a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py
+++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/TestTargetXMLArch.py
@@ -121,4 +121,4 @@ class TestTargetXMLArch(GDBRemoteTestBase):
if self.TraceOn():
interp.HandleCommand("target list", result)
print(result.GetOutput())
- self.assertTrue(target.GetTriple().startswith('x86_64--'))
+ self.assertTrue(target.GetTriple().startswith('x86_64-unknown-unknown'))
diff --git a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py
index d8d759a5dd58..a9e553cbb7d5 100644
--- a/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py
+++ b/packages/Python/lldbsuite/test/functionalities/gdb_remote_client/gdbclientutils.py
@@ -102,12 +102,13 @@ class MockGDBServerResponder:
return self.interrupt()
if packet == "c":
return self.cont()
- if packet == "g":
+ if packet[0] == "g":
return self.readRegisters()
if packet[0] == "G":
return self.writeRegisters(packet[1:])
if packet[0] == "p":
- return self.readRegister(int(packet[1:], 16))
+ regnum = packet[1:].split(';')[0]
+ return self.readRegister(int(regnum, 16))
if packet[0] == "P":
register, value = packet[1:].split("=")
return self.readRegister(int(register, 16), value)
@@ -124,12 +125,16 @@ class MockGDBServerResponder:
return self.qSupported(packet[11:].split(";"))
if packet == "qfThreadInfo":
return self.qfThreadInfo()
+ if packet == "qsThreadInfo":
+ return self.qsThreadInfo()
if packet == "qC":
return self.qC()
if packet == "QEnableErrorStrings":
return self.QEnableErrorStrings()
if packet == "?":
return self.haltReason()
+ if packet == "s":
+ return self.haltReason()
if packet[0] == "H":
return self.selectThread(packet[1], int(packet[2:], 16))
if packet[0:6] == "qXfer:":
@@ -144,6 +149,16 @@ class MockGDBServerResponder:
return self.vAttach(int(pid, 16))
if packet[0] == "Z":
return self.setBreakpoint(packet)
+ if packet.startswith("qThreadStopInfo"):
+ threadnum = int (packet[15:], 16)
+ return self.threadStopInfo(threadnum)
+ if packet == "QThreadSuffixSupported":
+ return self.QThreadSuffixSupported()
+ if packet == "QListThreadsInStopReply":
+ return self.QListThreadsInStopReply()
+ if packet.startswith("qMemoryRegionInfo:"):
+ return self.qMemoryRegionInfo()
+
return self.other(packet)
def interrupt(self):
@@ -179,6 +194,9 @@ class MockGDBServerResponder:
def qfThreadInfo(self):
return "l"
+ def qsThreadInfo(self):
+ return "l"
+
def qC(self):
return "QC0"
@@ -204,10 +222,22 @@ class MockGDBServerResponder:
def setBreakpoint(self, packet):
raise self.UnexpectedPacketException()
+ def threadStopInfo(self, threadnum):
+ return ""
+
def other(self, packet):
# empty string means unsupported
return ""
+ def QThreadSuffixSupported(self):
+ return ""
+
+ def QListThreadsInStopReply(self):
+ return ""
+
+ def qMemoryRegionInfo(self):
+ return ""
+
"""
Raised when we receive a packet for which there is no default action.
Override the responder class to implement behavior suitable for the test at
@@ -246,7 +276,7 @@ class MockGDBServer:
addr = ("127.0.0.1", self.port)
self._socket.bind(addr)
self.port = self._socket.getsockname()[1]
- self._socket.listen(0)
+ self._socket.listen(1)
self._thread = threading.Thread(target=self._run)
self._thread.start()
diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py
index 4f54f5d4103b..528192519513 100644
--- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py
+++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/TestInferiorCrashing.py
@@ -16,59 +16,42 @@ class CrashingInferiorTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_inferior_crashing(self):
"""Test that lldb reliably catches the inferior crashing (command)."""
self.build()
self.inferior_crashing()
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_inferior_crashing_register(self):
"""Test that lldb reliably reads registers from the inferior after crashing (command)."""
self.build()
self.inferior_crashing_registers()
@add_test_categories(['pyapi'])
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
def test_inferior_crashing_python(self):
"""Test that lldb reliably catches the inferior crashing (Python API)."""
self.build()
self.inferior_crashing_python()
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
def test_inferior_crashing_expr(self):
"""Test that the lldb expression interpreter can read from the inferior after crashing (command)."""
self.build()
self.inferior_crashing_expr()
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_inferior_crashing_step(self):
"""Test that stepping after a crash behaves correctly."""
self.build()
self.inferior_crashing_step()
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
@skipIfTargetAndroid() # debuggerd interferes with this test on Android
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_inferior_crashing_step_after_break(self):
"""Test that lldb functions correctly after stepping through a crash."""
self.build()
self.inferior_crashing_step_after_break()
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24778, This actually works, but the test relies on the output format instead of the API")
# Inferior exits after stepping after a segfault. This is working as
# intended IMHO.
@skipIfLinux
diff --git a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py
index d8efe65dc7f6..2cd4d46a7ca8 100644
--- a/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py
+++ b/packages/Python/lldbsuite/test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py
@@ -29,13 +29,11 @@ class CrashingRecursiveInferiorTestCase(TestBase):
self.recursive_inferior_crashing_registers()
@add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_recursive_inferior_crashing_python(self):
"""Test that lldb reliably catches the inferior crashing (Python API)."""
self.build()
self.recursive_inferior_crashing_python()
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_recursive_inferior_crashing_expr(self):
"""Test that the lldb expression interpreter can read from the inferior after crashing (command)."""
self.build()
@@ -47,8 +45,8 @@ class CrashingRecursiveInferiorTestCase(TestBase):
self.build()
self.recursive_inferior_crashing_step()
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
@skipIfTargetAndroid() # debuggerd interferes with this test on Android
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_recursive_inferior_crashing_step_after_break(self):
"""Test that lldb functions correctly after stepping through a crash."""
self.build()
@@ -58,7 +56,6 @@ class CrashingRecursiveInferiorTestCase(TestBase):
# intended IMHO.
@skipIfLinux
@skipIfFreeBSD
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_recursive_inferior_crashing_expr_step_and_expr(self):
"""Test that lldb expressions work before and after stepping after a crash."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py
index ab5791c614af..7bc5d205a94f 100644
--- a/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py
+++ b/packages/Python/lldbsuite/test/functionalities/load_unload/TestLoadUnload.py
@@ -158,6 +158,7 @@ class LoadUnloadTestCase(TestBase):
@skipIfFreeBSD # llvm.org/pr14424 - missing FreeBSD Makefiles/testcase support
@expectedFailureAndroid # wrong source file shows up for hidden library
@skipIfWindows # Windows doesn't have dlopen and friends, dynamic libraries work differently
+ @skipIfDarwinEmbedded
def test_dyld_library_path(self):
"""Test (DY)LD_LIBRARY_PATH after moving libd.dylib, which defines d_function, somewhere else."""
self.copy_shlibs_to_remote(hidden_dir=True)
diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile b/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile
new file mode 100644
index 000000000000..9d4f3b7f1412
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/memory-region/Makefile
@@ -0,0 +1,8 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
+
+clean::
+ rm -rf $(wildcard *.o *.d *.dSYM)
diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py b/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py
new file mode 100644
index 000000000000..4d10e68672e0
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/memory-region/TestMemoryRegion.py
@@ -0,0 +1,59 @@
+"""
+Test the 'memory region' command.
+"""
+
+from __future__ import print_function
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class MemoryCommandRegion(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ # Find the line number to break for main.c.
+ self.line = line_number(
+ 'main.cpp',
+ '// Run here before printing memory regions')
+
+ def test(self):
+ self.build()
+
+ # Set breakpoint in main and run
+ self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
+ lldbutil.run_break_set_by_file_and_line(
+ self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True)
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+
+ # Test that the first 'memory region' command prints the usage.
+ interp.HandleCommand("memory region", result)
+ self.assertFalse(result.Succeeded())
+ self.assertRegexpMatches(result.GetError(), "Usage: memory region ADDR")
+
+ # Now let's print the memory region starting at 0 which should always work.
+ interp.HandleCommand("memory region 0x0", result)
+ self.assertTrue(result.Succeeded())
+ self.assertRegexpMatches(result.GetOutput(), "\\[0x0+-")
+
+ # Keep printing memory regions until we printed all of them.
+ while True:
+ interp.HandleCommand("memory region", result)
+ if not result.Succeeded():
+ break
+
+ # Now that we reached the end, 'memory region' should again print the usage.
+ interp.HandleCommand("memory region", result)
+ self.assertFalse(result.Succeeded())
+ self.assertRegexpMatches(result.GetError(), "Usage: memory region ADDR")
diff --git a/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp b/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp
new file mode 100644
index 000000000000..116c10a6c3ea
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/memory-region/main.cpp
@@ -0,0 +1,6 @@
+#include <iostream>
+
+int main (int argc, char const **argv) {
+ std::cout << "Program with sections" << std::endl;
+ return 0; // Run here before printing memory regions
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py
index f45479bee0bf..56984885104e 100644
--- a/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py
+++ b/packages/Python/lldbsuite/test/functionalities/memory/cache/TestMemoryCache.py
@@ -24,7 +24,7 @@ class MemoryCacheTestCase(TestBase):
# Find the line number to break inside main().
self.line = line_number('main.cpp', '// Set break point at this line.')
- @expectedFlakeyOS(oslist=["windows"])
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test_memory_cache(self):
"""Test the MemoryCache class with a sequence of 'memory read' and 'memory write' operations."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py b/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py
index 8e0fbaa32018..245aaa819c7f 100644
--- a/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py
+++ b/packages/Python/lldbsuite/test/functionalities/memory/find/TestMemoryFind.py
@@ -24,7 +24,6 @@ class MemoryFindTestCase(TestBase):
# Find the line number to break inside main().
self.line = line_number('main.cpp', '// break here')
- @expectedFailureAll(oslist=["windows"])
def test_memory_find(self):
"""Test the 'memory find' command."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py
index 879f1adebc6a..2c25ccc253fd 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py
@@ -6,6 +6,7 @@ from __future__ import print_function
import shutil
import struct
+import os
import lldb
from lldbsuite.test.decorators import *
@@ -203,6 +204,30 @@ class LinuxCoreTestCase(TestBase):
for regname, value in values.iteritems():
self.expect("register read {}".format(regname), substrs=["{} = {}".format(regname, value)])
+ @expectedFailureAll(bugnumber="llvm.org/pr37371", hostoslist=["windows"])
+ @skipIf(triple='^mips')
+ @skipIfLLVMTargetMissing("X86")
+ def test_i386_sysroot(self):
+ """Test that lldb can find the exe for an i386 linux core file using the sysroot."""
+
+ # Copy linux-i386.out to tmp_sysroot/home/labath/test/a.out (since it was compiled as
+ # /home/labath/test/a.out)
+ tmp_sysroot = os.path.join(self.getBuildDir(), "lldb_i386_mock_sysroot")
+ executable = os.path.join(tmp_sysroot, "home", "labath", "test", "a.out")
+ lldbutil.mkdir_p(os.path.dirname(executable))
+ shutil.copyfile("linux-i386.out", executable)
+
+ # Set sysroot and load core
+ self.runCmd("platform select remote-linux --sysroot '%s'" % tmp_sysroot)
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target, VALID_TARGET)
+ process = target.LoadCore("linux-i386.core")
+
+ # Check that we found a.out from the sysroot
+ self.check_all(process, self._i386_pid, self._i386_regions, "a.out")
+
+ self.dbg.DeleteTarget(target)
+
def check_memory_regions(self, process, region_count):
region_list = process.GetMemoryRegions()
self.assertEqual(region_list.GetSize(), region_count)
@@ -299,15 +324,7 @@ class LinuxCoreTestCase(TestBase):
self.dbg.SetOutputFileHandle(None, False)
self.dbg.SetErrorFileHandle(None, False)
- def do_test(self, filename, pid, region_count, thread_name):
- target = self.dbg.CreateTarget(filename + ".out")
- process = target.LoadCore(filename + ".core")
- self.assertTrue(process, PROCESS_IS_VALID)
- self.assertEqual(process.GetNumThreads(), 1)
- self.assertEqual(process.GetProcessID(), pid)
-
- self.check_state(process)
-
+ def check_stack(self, process, pid, thread_name):
thread = process.GetSelectedThread()
self.assertTrue(thread)
self.assertEqual(thread.GetThreadID(), pid)
@@ -324,6 +341,21 @@ class LinuxCoreTestCase(TestBase):
frame.FindVariable("F").GetValueAsUnsigned(), ord(
backtrace[i][0]))
+ def check_all(self, process, pid, region_count, thread_name):
+ self.assertTrue(process, PROCESS_IS_VALID)
+ self.assertEqual(process.GetNumThreads(), 1)
+ self.assertEqual(process.GetProcessID(), pid)
+
+ self.check_state(process)
+
+ self.check_stack(process, pid, thread_name)
+
self.check_memory_regions(process, region_count)
+ def do_test(self, filename, pid, region_count, thread_name):
+ target = self.dbg.CreateTarget(filename + ".out")
+ process = target.LoadCore(filename + ".core")
+
+ self.check_all(process, pid, region_count, thread_name)
+
self.dbg.DeleteTarget(target)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
index 5960215f8047..46398e39a0e0 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/TestMiniDumpNew.py
@@ -88,6 +88,36 @@ class MiniDumpNewTestCase(TestBase):
self.assertEqual(self.process.GetProcessID(), self._linux_x86_64_pid)
self.check_state()
+ def test_memory_region_name(self):
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("regions-linux-map.dmp")
+ result = lldb.SBCommandReturnObject()
+ addr_region_name_pairs = [
+ ("0x400d9000", "/system/bin/app_process"),
+ ("0x400db000", "/system/bin/app_process"),
+ ("0x400dd000", "/system/bin/linker"),
+ ("0x400ed000", "/system/bin/linker"),
+ ("0x400ee000", "/system/bin/linker"),
+ ("0x400fb000", "/system/lib/liblog.so"),
+ ("0x400fc000", "/system/lib/liblog.so"),
+ ("0x400fd000", "/system/lib/liblog.so"),
+ ("0x400ff000", "/system/lib/liblog.so"),
+ ("0x40100000", "/system/lib/liblog.so"),
+ ("0x40101000", "/system/lib/libc.so"),
+ ("0x40122000", "/system/lib/libc.so"),
+ ("0x40123000", "/system/lib/libc.so"),
+ ("0x40167000", "/system/lib/libc.so"),
+ ("0x40169000", "/system/lib/libc.so"),
+ ]
+ ci = self.dbg.GetCommandInterpreter()
+ for (addr, region_name) in addr_region_name_pairs:
+ command = 'memory region ' + addr
+ ci.HandleCommand(command, result, False)
+ message = 'Ensure memory "%s" shows up in output for "%s"' % (
+ region_name, command)
+ self.assertTrue(region_name in result.GetOutput(), message)
+
def test_modules_in_mini_dump(self):
"""Test that lldb can read the list of modules from the minidump."""
# target create -c linux-x86_64.dmp
@@ -97,14 +127,18 @@ class MiniDumpNewTestCase(TestBase):
self.assertTrue(self.process, PROCESS_IS_VALID)
expected_modules = [
{
- 'filename' : 'linux-gate.so',
- 'uuid' : '4EAD28F8-88EF-3520-872B-73C6F2FE7306-C41AF22F',
+ 'filename' : 'linux-x86_64',
+ 'uuid' : 'E35C283B-C327-C287-62DB-788BF5A4078B-E2351448',
},
{
'filename' : 'libm-2.19.so',
'uuid' : 'D144258E-6149-00B2-55A3-1F3FD2283A87-8670D5BC',
},
{
+ 'filename' : 'libgcc_s.so.1',
+ 'uuid' : '36311B44-5771-0AE5-578C-4BF00791DED7-359DBB92',
+ },
+ {
'filename' : 'libstdc++.so.6.0.19',
'uuid' : '76190E92-2AF7-457D-078F-75C9B15FA184-E83EB506',
},
@@ -113,24 +147,20 @@ class MiniDumpNewTestCase(TestBase):
'uuid' : 'CF699A15-CAAE-64F5-0311-FC4655B86DC3-9A479789',
},
{
- 'filename' : 'linux-x86_64',
- 'uuid' : 'E35C283B-C327-C287-62DB-788BF5A4078B-E2351448',
- },
- {
- 'filename' : 'libgcc_s.so.1',
- 'uuid' : '36311B44-5771-0AE5-578C-4BF00791DED7-359DBB92',
- },
- {
'filename' : 'libpthread-2.19.so',
'uuid' : '31E9F21A-E8C1-0396-171F-1E13DA157809-86FA696C',
},
{
+ 'filename' : 'libbreakpad.so',
+ 'uuid' : '784FD549-332D-826E-D23F-18C17C6F320A',
+ },
+ {
'filename' : 'ld-2.19.so',
'uuid' : 'D0F53790-4076-D73F-29E4-A37341F8A449-E2EF6CD0',
},
{
- 'filename' : 'libbreakpad.so',
- 'uuid' : '784FD549-332D-826E-D23F-18C17C6F320A',
+ 'filename' : 'linux-gate.so',
+ 'uuid' : '4EAD28F8-88EF-3520-872B-73C6F2FE7306-C41AF22F',
},
]
self.assertEqual(self.target.GetNumModules(), len(expected_modules))
@@ -189,6 +219,161 @@ class MiniDumpNewTestCase(TestBase):
stop_description = thread.GetStopDescription(256)
self.assertEqual(stop_description, "")
+ def check_register_unsigned(self, set, name, expected):
+ reg_value = set.GetChildMemberWithName(name)
+ self.assertTrue(reg_value.IsValid(),
+ 'Verify we have a register named "%s"' % (name))
+ self.assertEqual(reg_value.GetValueAsUnsigned(), expected,
+ 'Verify "%s" == %i' % (name, expected))
+
+ def check_register_string_value(self, set, name, expected, format):
+ reg_value = set.GetChildMemberWithName(name)
+ self.assertTrue(reg_value.IsValid(),
+ 'Verify we have a register named "%s"' % (name))
+ if format is not None:
+ reg_value.SetFormat(format)
+ self.assertEqual(reg_value.GetValue(), expected,
+ 'Verify "%s" has string value "%s"' % (name,
+ expected))
+
+ def test_arm64_registers(self):
+ """Test ARM64 registers from a breakpad created minidump."""
+ # target create -c arm64-macos.dmp
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("arm64-macos.dmp")
+ self.check_state()
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ thread = self.process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone)
+ stop_description = thread.GetStopDescription(256)
+ self.assertEqual(stop_description, "")
+ registers = thread.GetFrameAtIndex(0).GetRegisters()
+ # Verify the GPR registers are all correct
+ # Verify x0 - x31 register values
+ gpr = registers.GetValueAtIndex(0)
+ for i in range(32):
+ v = i+1 | i+2 << 32 | i+3 << 48
+ w = i+1
+ self.check_register_unsigned(gpr, 'x%i' % (i), v)
+ self.check_register_unsigned(gpr, 'w%i' % (i), w)
+ # Verify arg1 - arg8 register values
+ for i in range(1, 9):
+ v = i | i+1 << 32 | i+2 << 48
+ self.check_register_unsigned(gpr, 'arg%i' % (i), v)
+ i = 29
+ v = i+1 | i+2 << 32 | i+3 << 48
+ self.check_register_unsigned(gpr, 'fp', v)
+ i = 30
+ v = i+1 | i+2 << 32 | i+3 << 48
+ self.check_register_unsigned(gpr, 'lr', v)
+ i = 31
+ v = i+1 | i+2 << 32 | i+3 << 48
+ self.check_register_unsigned(gpr, 'sp', v)
+ self.check_register_unsigned(gpr, 'pc', 0x1000)
+ self.check_register_unsigned(gpr, 'cpsr', 0x11223344)
+ self.check_register_unsigned(gpr, 'psr', 0x11223344)
+
+ # Verify the FPR registers are all correct
+ fpr = registers.GetValueAtIndex(1)
+ for i in range(32):
+ v = "0x"
+ d = "0x"
+ s = "0x"
+ h = "0x"
+ for j in range(i+15, i-1, -1):
+ v += "%2.2x" % (j)
+ for j in range(i+7, i-1, -1):
+ d += "%2.2x" % (j)
+ for j in range(i+3, i-1, -1):
+ s += "%2.2x" % (j)
+ for j in range(i+1, i-1, -1):
+ h += "%2.2x" % (j)
+ self.check_register_string_value(fpr, "v%i" % (i), v,
+ lldb.eFormatHex)
+ self.check_register_string_value(fpr, "d%i" % (i), d,
+ lldb.eFormatHex)
+ self.check_register_string_value(fpr, "s%i" % (i), s,
+ lldb.eFormatHex)
+ self.check_register_string_value(fpr, "h%i" % (i), h,
+ lldb.eFormatHex)
+ self.check_register_unsigned(gpr, 'fpsr', 0x55667788)
+ self.check_register_unsigned(gpr, 'fpcr', 0x99aabbcc)
+
+ def verify_arm_registers(self, apple=False):
+ """
+ Verify values of all ARM registers from a breakpad created
+ minidump.
+ """
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ if apple:
+ self.process = self.target.LoadCore("arm-macos.dmp")
+ else:
+ self.process = self.target.LoadCore("arm-linux.dmp")
+ self.check_state()
+ self.assertEqual(self.process.GetNumThreads(), 1)
+ thread = self.process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetStopReason(), lldb.eStopReasonNone)
+ stop_description = thread.GetStopDescription(256)
+ self.assertEqual(stop_description, "")
+ registers = thread.GetFrameAtIndex(0).GetRegisters()
+ # Verify the GPR registers are all correct
+ # Verify x0 - x31 register values
+ gpr = registers.GetValueAtIndex(0)
+ for i in range(1, 16):
+ self.check_register_unsigned(gpr, 'r%i' % (i), i+1)
+ # Verify arg1 - arg4 register values
+ for i in range(1, 5):
+ self.check_register_unsigned(gpr, 'arg%i' % (i), i)
+ if apple:
+ self.check_register_unsigned(gpr, 'fp', 0x08)
+ else:
+ self.check_register_unsigned(gpr, 'fp', 0x0c)
+ self.check_register_unsigned(gpr, 'lr', 0x0f)
+ self.check_register_unsigned(gpr, 'sp', 0x0e)
+ self.check_register_unsigned(gpr, 'pc', 0x10)
+ self.check_register_unsigned(gpr, 'cpsr', 0x11223344)
+
+ # Verify the FPR registers are all correct
+ fpr = registers.GetValueAtIndex(1)
+ # Check d0 - d31
+ self.check_register_unsigned(gpr, 'fpscr', 0x55667788aabbccdd)
+ for i in range(32):
+ value = (i+1) | (i+1) << 8 | (i+1) << 32 | (i+1) << 48
+ self.check_register_unsigned(fpr, "d%i" % (i), value)
+ # Check s0 - s31
+ for i in range(32):
+ i_val = (i >> 1) + 1
+ if i & 1:
+ value = "%#8.8x" % (i_val | i_val << 16)
+ else:
+ value = "%#8.8x" % (i_val | i_val << 8)
+ self.check_register_string_value(fpr, "s%i" % (i), value,
+ lldb.eFormatHex)
+ # Check q0 - q15
+ for i in range(15):
+ a = i * 2 + 1
+ b = a + 1
+ value = ("0x00%2.2x00%2.2x0000%2.2x%2.2x"
+ "00%2.2x00%2.2x0000%2.2x%2.2x") % (b, b, b, b, a, a, a, a)
+ self.check_register_string_value(fpr, "q%i" % (i), value,
+ lldb.eFormatHex)
+
+ def test_linux_arm_registers(self):
+ """Test Linux ARM registers from a breakpad created minidump.
+
+ The frame pointer is R11 for linux.
+ """
+ self.verify_arm_registers(apple=False)
+
+ def test_apple_arm_registers(self):
+ """Test Apple ARM registers from a breakpad created minidump.
+
+ The frame pointer is R7 for linux.
+ """
+ self.verify_arm_registers(apple=True)
+
def do_test_deeper_stack(self, binary, core, pid):
target = self.dbg.CreateTarget(binary)
process = target.LoadCore(core)
@@ -263,3 +448,65 @@ class MiniDumpNewTestCase(TestBase):
frame = thread.GetFrameAtIndex(1)
value = frame.EvaluateExpression('x')
self.assertEqual(value.GetValueAsSigned(), 3)
+
+ def test_memory_regions_in_minidump(self):
+ """Test memory regions from a Minidump"""
+ # target create -c regions-linux-map.dmp
+ self.dbg.CreateTarget(None)
+ self.target = self.dbg.GetSelectedTarget()
+ self.process = self.target.LoadCore("regions-linux-map.dmp")
+ self.check_state()
+
+ regions_count = 19
+ region_info_list = self.process.GetMemoryRegions()
+ self.assertEqual(region_info_list.GetSize(), regions_count)
+
+ def check_region(index, start, end, read, write, execute, mapped, name):
+ region_info = lldb.SBMemoryRegionInfo()
+ self.assertTrue(
+ self.process.GetMemoryRegionInfo(start, region_info).Success())
+ self.assertEqual(start, region_info.GetRegionBase())
+ self.assertEqual(end, region_info.GetRegionEnd())
+ self.assertEqual(read, region_info.IsReadable())
+ self.assertEqual(write, region_info.IsWritable())
+ self.assertEqual(execute, region_info.IsExecutable())
+ self.assertEqual(mapped, region_info.IsMapped())
+ self.assertEqual(name, region_info.GetName())
+
+ # Ensure we have the same regions as SBMemoryRegionInfoList contains.
+ if index >= 0 and index < regions_count:
+ region_info_from_list = lldb.SBMemoryRegionInfo()
+ self.assertTrue(region_info_list.GetMemoryRegionAtIndex(
+ index, region_info_from_list))
+ self.assertEqual(region_info_from_list, region_info)
+
+ a = "/system/bin/app_process"
+ b = "/system/bin/linker"
+ c = "/system/lib/liblog.so"
+ d = "/system/lib/libc.so"
+ n = None
+ max_int = 0xffffffffffffffff
+
+ # Test address before the first entry comes back with nothing mapped up
+ # to first valid region info
+ check_region(-1, 0x00000000, 0x400d9000, False, False, False, False, n)
+ check_region( 0, 0x400d9000, 0x400db000, True, False, True, True, a)
+ check_region( 1, 0x400db000, 0x400dc000, True, False, False, True, a)
+ check_region( 2, 0x400dc000, 0x400dd000, True, True, False, True, n)
+ check_region( 3, 0x400dd000, 0x400ec000, True, False, True, True, b)
+ check_region( 4, 0x400ec000, 0x400ed000, True, False, False, True, n)
+ check_region( 5, 0x400ed000, 0x400ee000, True, False, False, True, b)
+ check_region( 6, 0x400ee000, 0x400ef000, True, True, False, True, b)
+ check_region( 7, 0x400ef000, 0x400fb000, True, True, False, True, n)
+ check_region( 8, 0x400fb000, 0x400fc000, True, False, True, True, c)
+ check_region( 9, 0x400fc000, 0x400fd000, True, True, True, True, c)
+ check_region(10, 0x400fd000, 0x400ff000, True, False, True, True, c)
+ check_region(11, 0x400ff000, 0x40100000, True, False, False, True, c)
+ check_region(12, 0x40100000, 0x40101000, True, True, False, True, c)
+ check_region(13, 0x40101000, 0x40122000, True, False, True, True, d)
+ check_region(14, 0x40122000, 0x40123000, True, True, True, True, d)
+ check_region(15, 0x40123000, 0x40167000, True, False, True, True, d)
+ check_region(16, 0x40167000, 0x40169000, True, False, False, True, d)
+ check_region(17, 0x40169000, 0x4016b000, True, True, False, True, d)
+ check_region(18, 0x4016b000, 0x40176000, True, True, False, True, n)
+ check_region(-1, 0x40176000, max_int, False, False, False, False, n)
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp
new file mode 100644
index 000000000000..3b0cb8268def
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-linux.dmp
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp
new file mode 100644
index 000000000000..9ff6a8396ec5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm-macos.dmp
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp
new file mode 100644
index 000000000000..ba658dd48feb
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/arm64-macos.dmp
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp
new file mode 100644
index 000000000000..3f1dd53d98fa
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump-new/regions-linux-map.dmp
Binary files differ
diff --git a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
index 61e2adee41d5..fe13871ddac9 100644
--- a/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
+++ b/packages/Python/lldbsuite/test/functionalities/postmortem/minidump/TestMiniDump.py
@@ -50,28 +50,28 @@ class MiniDumpTestCase(TestBase):
self.assertTrue(self.process, PROCESS_IS_VALID)
expected_modules = [
{
- 'filename' : r"C:\Windows\System32/MSVCP120D.dll",
- 'uuid' : '6E51053C-E757-EB40-8D3F-9722C5BD80DD-01000000',
- },
- {
- 'filename' : r"C:\Windows\SysWOW64/kernel32.dll",
- 'uuid' : '1B7ECBE5-5E00-1341-AB98-98D6913B52D8-02000000',
- },
- {
'filename' : r"C:\Users\amccarth\Documents\Visual Studio 2013\Projects\fizzbuzz\Debug/fizzbuzz.exe",
'uuid' : '91B7450F-969A-F946-BF8F-2D6076EA421A-11000000',
},
{
- 'filename' : r"C:\Windows\System32/MSVCR120D.dll",
- 'uuid' : '86FB8263-C446-4640-AE42-8D97B3F91FF2-01000000',
+ 'filename' : r"C:\Windows\SysWOW64/ntdll.dll",
+ 'uuid' : '6A84B0BB-2C40-5240-A16B-67650BBFE6B0-02000000',
+ },
+ {
+ 'filename' : r"C:\Windows\SysWOW64/kernel32.dll",
+ 'uuid' : '1B7ECBE5-5E00-1341-AB98-98D6913B52D8-02000000',
},
{
'filename' : r"C:\Windows\SysWOW64/KERNELBASE.dll",
'uuid' : '4152F90B-0DCB-D44B-AC5D-186A6452E522-01000000',
},
{
- 'filename' : r"C:\Windows\SysWOW64/ntdll.dll",
- 'uuid' : '6A84B0BB-2C40-5240-A16B-67650BBFE6B0-02000000',
+ 'filename' : r"C:\Windows\System32/MSVCP120D.dll",
+ 'uuid' : '6E51053C-E757-EB40-8D3F-9722C5BD80DD-01000000',
+ },
+ {
+ 'filename' : r"C:\Windows\System32/MSVCR120D.dll",
+ 'uuid' : '86FB8263-C446-4640-AE42-8D97B3F91FF2-01000000',
},
]
self.assertEqual(self.target.GetNumModules(), len(expected_modules))
@@ -80,7 +80,6 @@ class MiniDumpTestCase(TestBase):
self.assertEqual(module.file.fullpath, expected['filename'])
self.assertEqual(module.GetUUIDString(), expected['uuid'])
- @expectedFailureAll(bugnumber="llvm.org/pr35193", hostoslist=["windows"])
def test_stack_info_in_mini_dump(self):
"""Test that we can see a trivial stack in a VS-generate mini dump."""
# target create -c fizzbuzz_no_heap.dmp
diff --git a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py
index 617b4bcfaec3..f485c13fa9f1 100644
--- a/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py
+++ b/packages/Python/lldbsuite/test/functionalities/process_attach/TestProcessAttach.py
@@ -23,7 +23,6 @@ class ProcessAttachTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@skipIfiOSSimulator
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_attach_to_process_by_id(self):
"""Test attach by process id"""
self.build()
@@ -40,7 +39,6 @@ class ProcessAttachTestCase(TestBase):
process = target.GetProcess()
self.assertTrue(process, PROCESS_IS_VALID)
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_attach_to_process_from_different_dir_by_id(self):
"""Test attach by process id"""
newdir = self.getBuildArtifact("newdir")
@@ -67,7 +65,6 @@ class ProcessAttachTestCase(TestBase):
process = target.GetProcess()
self.assertTrue(process, PROCESS_IS_VALID)
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_attach_to_process_by_name(self):
"""Test attach by process name"""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py
index 8496ce6c04d7..d3b153270119 100644
--- a/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py
+++ b/packages/Python/lldbsuite/test/functionalities/process_group/TestChangeProcessGroup.py
@@ -24,7 +24,6 @@ class ChangeProcessGroupTestCase(TestBase):
@skipIfFreeBSD # Times out on FreeBSD llvm.org/pr23731
@skipIfWindows # setpgid call does not exist on Windows
@expectedFailureAndroid("http://llvm.org/pr23762", api_levels=[16])
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_setpgid(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py b/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py
index d362e6a8ae3d..1919d4b1ac6d 100644
--- a/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py
+++ b/packages/Python/lldbsuite/test/functionalities/register/intel_avx/TestYMMRegister.py
@@ -21,7 +21,6 @@ class TestYMMRegister(TestBase):
@skipIfiOSSimulator
@skipIfTargetAndroid()
@skipIf(archs=no_match(['i386', 'x86_64']))
- @expectedFailureAll(oslist=["linux"], bugnumber="rdar://30523153")
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37995")
def test(self):
self.build(dictionary={"CFLAGS_EXTRAS": "-march=haswell"})
diff --git a/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py b/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py
new file mode 100644
index 000000000000..a56282efd77d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/show_location/TestShowLocationDwarf5.py
@@ -0,0 +1,34 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+
+# This test checks that source code location is shown correctly
+# when DWARF5 debug information is used.
+
+class TestTargetSourceMap(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test_source_map(self):
+ # Set the target soure map to map "./" to the current test directory.
+ yaml_path = os.path.join(self.getSourceDir(), "a.yaml")
+ yaml_base, ext = os.path.splitext(yaml_path)
+ obj_path = self.getBuildArtifact(yaml_base)
+ self.yaml2obj(yaml_path, obj_path)
+
+ def cleanup():
+ if os.path.exists(obj_path):
+ os.unlink(obj_path)
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ # Create a target with the object file we just created from YAML
+ target = self.dbg.CreateTarget(obj_path)
+
+ # Check we are able to show the locations properly.
+ self.expect("b main", VALID_BREAKPOINT_LOCATION,
+ substrs=['main + 13 at test.cpp:2:3, address = 0x000000000040052d'])
+
+ self.expect("b foo", VALID_BREAKPOINT_LOCATION,
+ substrs=['foo() + 4 at test.cpp:6:1, address = 0x0000000000400534'])
diff --git a/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml b/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml
new file mode 100644
index 000000000000..27b119d3df63
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/show_location/a.yaml
@@ -0,0 +1,58 @@
+# This file is a shorten version of the output
+# produced with the following invocations and input:
+# ./clang test.cpp -g -gdwarf-5 -o test.exe
+# ./obj2yaml test.exe > test.yaml
+#
+# // test.cpp
+# int main() {
+# return 0;
+# }
+#
+# void foo() {
+# }
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ Entry: 0x0000000000400440
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000400440
+ AddressAlign: 0x0000000000000010
+ Content: 31ED4989D15E4889E24883E4F0505449C7C0B005400048C7C14005400048C7C720054000E8B7FFFFFFF4660F1F44000055B820204000483D202040004889E57417B8000000004885C0740D5DBF20204000FFE00F1F4400005DC3660F1F440000BE20204000554881EE202040004889E548C1FE034889F048C1E83F4801C648D1FE7415B8000000004885C0740B5DBF20204000FFE00F1F005DC3660F1F440000803D391B0000007517554889E5E87EFFFFFFC605271B0000015DC30F1F440000F3C30F1F4000662E0F1F840000000000554889E55DEB89660F1F840000000000554889E531C0C745FC000000005DC390554889E55DC3662E0F1F840000000000415741564189FF415541544C8D25B618000055488D2DB6180000534989F64989D54C29E54883EC0848C1FD03E87FFEFFFF4885ED742031DB0F1F8400000000004C89EA4C89F64489FF41FF14DC4883C3014839EB75EA4883C4085B5D415C415D415E415FC390662E0F1F840000000000F3C3
+ - Name: .debug_str_offsets
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 200000000500000000000000230000002C0000004A0000004F000000530000005B000000
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 636C616E672076657273696F6E20382E302E3020287472756E6B203334313935382900746573742E637070002F686F6D652F756D622F4C4C564D2F6275696C645F6C6C64622F62696E006D61696E00696E74005F5A33666F6F7600666F6F00
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101252513050325721710171B25110112060000022E0011011206401803253A0B3B0B49133F190000032E001101120640186E2503253A0B3B0B3F19000004240003253E0B0B0B000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 50000000050001080000000001000400010800000000000000022005400000000000160000000220054000000000000F00000001560301014F000000033005400000000000060000000156050601050404050400
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 70000000050008004C000000010101FB0E0D00010101010000000100000101011F010000000003011F020F051E021E00000000FD7C0F2E46BA561F7BDA351B04E677091E00000000FD7C0F2E46BA561F7BDA351B04E6770900090220054000000000000105030AC905003F05010A4B0202000101
+ - Name: .debug_line_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 2F686F6D652F756D622F4C4C564D2F6275696C645F6C6C64622F62696E00746573742E63707000
+...
diff --git a/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py b/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py
index a6c38ca1d091..f2027eb131c5 100644
--- a/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py
+++ b/packages/Python/lldbsuite/test/functionalities/stats_api/TestStatisticsAPI.py
@@ -17,6 +17,15 @@ class TestStatsAPI(TestBase):
self.build()
exe = self.getBuildArtifact("a.out")
target = self.dbg.CreateTarget(exe)
+
+ # Test enabling/disabling stats
+ self.assertFalse(target.GetCollectingStats())
+ target.SetCollectingStats(True)
+ self.assertTrue(target.GetCollectingStats())
+ target.SetCollectingStats(False)
+ self.assertFalse(target.GetCollectingStats())
+
+ # Test the function to get the statistics in JSON'ish.
stats = target.GetStatistics()
stream = lldb.SBStream()
res = stats.GetAsJSON(stream)
diff --git a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile b/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile
index 0d70f2595019..0d70f2595019 100644
--- a/packages/Python/lldbsuite/test/functionalities/embedded_interpreter/Makefile
+++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/Makefile
diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py b/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py
new file mode 100644
index 000000000000..1383a03f4647
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/Steps.py
@@ -0,0 +1,37 @@
+import lldb
+
+class StepWithChild:
+ def __init__(self, thread_plan):
+ self.thread_plan = thread_plan
+ self.child_thread_plan = self.queue_child_thread_plan()
+
+ def explains_stop(self, event):
+ return False
+
+ def should_stop(self, event):
+ if not self.child_thread_plan.IsPlanComplete():
+ return False
+
+ self.thread_plan.SetPlanComplete(True)
+
+ return True
+
+ def should_step(self):
+ return False
+
+ def queue_child_thread_plan(self):
+ return None
+
+class StepOut(StepWithChild):
+ def __init__(self, thread_plan, dict):
+ StepWithChild.__init__(self, thread_plan)
+
+ def queue_child_thread_plan(self):
+ return self.thread_plan.QueueThreadPlanForStepOut(0)
+
+class StepScripted(StepWithChild):
+ def __init__(self, thread_plan, dict):
+ StepWithChild.__init__(self, thread_plan)
+
+ def queue_child_thread_plan(self):
+ return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut")
diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py b/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
new file mode 100644
index 000000000000..a111ede6739c
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/TestStepScripted.py
@@ -0,0 +1,41 @@
+"""
+Tests stepping with scripted thread plans.
+"""
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.lldbtest import *
+
+class StepScriptedTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def test_standard_step_out(self):
+ """Tests stepping with the scripted thread plan laying over a standard thread plan for stepping out."""
+ self.build()
+ self.main_source_file = lldb.SBFileSpec("main.c")
+ self.step_out_with_scripted_plan("Steps.StepOut")
+
+ def test_scripted_step_out(self):
+ """Tests stepping with the scripted thread plan laying over an another scripted thread plan for stepping out."""
+ self.build()
+ self.main_source_file = lldb.SBFileSpec("main.c")
+ self.step_out_with_scripted_plan("Steps.StepScripted")
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.runCmd("command script import Steps.py")
+
+ def step_out_with_scripted_plan(self, name):
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file)
+
+ frame = thread.GetFrameAtIndex(0)
+ self.assertEqual("foo", frame.GetFunctionName())
+
+ err = thread.StepUsingScriptedThreadPlan(name)
+ self.assertTrue(err.Success(), err.GetCString())
+
+ frame = thread.GetFrameAtIndex(0)
+ self.assertEqual("main", frame.GetFunctionName())
diff --git a/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c b/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c
new file mode 100644
index 000000000000..88b3c17125db
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/step_scripted/main.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+void foo() {
+ printf("Set a breakpoint here.\n");
+}
+
+int main() {
+ foo();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py
deleted file mode 100644
index 767b368cc7dc..000000000000
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookCmd.py
+++ /dev/null
@@ -1,77 +0,0 @@
-"""
-Test lldb target stop-hook command.
-"""
-
-from __future__ import print_function
-
-
-import os
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class StopHookCmdTestCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers inside main.cpp.
- self.begl = line_number(
- 'main.cpp',
- '// Set breakpoint here to test target stop-hook.')
- self.endl = line_number(
- 'main.cpp',
- '// End of the line range for which stop-hook is to be run.')
- self.line = line_number(
- 'main.cpp',
- '// Another breakpoint which is outside of the stop-hook range.')
-
- @no_debug_info_test
- def test_not_crashing_if_no_target(self):
- """target stop-hook list should not crash if no target has been set."""
- self.runCmd("target stop-hook list", check=False)
-
- def test(self):
- """Test a sequence of target stop-hook commands."""
- self.build()
- exe = self.getBuildArtifact("a.out")
- self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
-
- lldbutil.run_break_set_by_file_and_line(
- self, "main.cpp", self.begl, num_expected_locations=1, loc_exact=True)
-
- lldbutil.run_break_set_by_file_and_line(
- self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
-
- self.runCmd(
- "target stop-hook add -f main.cpp -l %d -e %d -o 'expr ptr'" %
- (self.begl, self.endl))
-
- self.expect('target stop-hook list', 'Stop Hook added successfully',
- substrs=['State: enabled',
- 'expr ptr'])
-
- self.runCmd('target stop-hook disable')
-
- self.expect('target stop-hook list', 'Stop Hook disabled successfully',
- substrs=['State: disabled',
- 'expr ptr'])
-
- self.runCmd('target stop-hook enable')
-
- self.expect('target stop-hook list', 'Stop Hook enabled successfully',
- substrs=['State: enabled',
- 'expr ptr'])
-
- self.runCmd("settings set auto-confirm true")
- self.addTearDownHook(
- lambda: self.runCmd("settings clear auto-confirm"))
-
- self.runCmd('target stop-hook delete')
-
- self.expect('target stop-hook list', 'Stop Hook deleted successfully',
- substrs=['No stop hooks.'])
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py
deleted file mode 100644
index b76d98a333c2..000000000000
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/TestStopHookMechanism.py
+++ /dev/null
@@ -1,128 +0,0 @@
-"""
-Test lldb target stop-hook mechanism to see whether it fires off correctly .
-"""
-
-from __future__ import print_function
-
-
-import os
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import configuration
-from lldbsuite.test import lldbutil
-
-
-class StopHookMechanismTestCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers inside main.cpp.
- self.begl = line_number(
- 'main.cpp',
- '// Set breakpoint here to test target stop-hook.')
- self.endl = line_number(
- 'main.cpp',
- '// End of the line range for which stop-hook is to be run.')
- self.correct_step_line = line_number(
- 'main.cpp', '// We should stop here after stepping.')
- self.line = line_number(
- 'main.cpp',
- '// Another breakpoint which is outside of the stop-hook range.')
-
- @skipIfFreeBSD # llvm.org/pr15037
- # stop-hooks sometimes fail to fire on Linux
- @expectedFlakeyLinux('llvm.org/pr15037')
- @expectedFailureAll(
- hostoslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- @skipIf(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], archs=['armv7', 'armv7k']) # <rdar://problem/34582291> problem with armv7 and step-over and stop-hook firing on ios etc systems
- def test(self):
- """Test the stop-hook mechanism."""
- self.build()
-
- import pexpect
- exe = self.getBuildArtifact("a.out")
- prompt = "(lldb) "
- add_prompt = "Enter your stop hook command(s). Type 'DONE' to end."
- add_prompt1 = "> "
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn('%s %s' %
- (lldbtest_config.lldbExec, self.lldbOption))
- child = self.child
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- if lldb.remote_platform:
- child.expect_exact(prompt)
- child.sendline(
- 'platform select %s' %
- lldb.remote_platform.GetName())
- child.expect_exact(prompt)
- child.sendline(
- 'platform connect %s' %
- configuration.lldb_platform_url)
- child.expect_exact(prompt)
- child.sendline(
- 'platform settings -w %s' %
- configuration.lldb_platform_working_dir)
-
- child.expect_exact(prompt)
- child.sendline('target create %s' % exe)
-
- # Set the breakpoint, followed by the target stop-hook commands.
- child.expect_exact(prompt)
- child.sendline('breakpoint set -f main.cpp -l %d' % self.begl)
- child.expect_exact(prompt)
- child.sendline('breakpoint set -f main.cpp -l %d' % self.line)
- child.expect_exact(prompt)
- child.sendline(
- 'target stop-hook add -f main.cpp -l %d -e %d' %
- (self.begl, self.endl))
- child.expect_exact(add_prompt)
- child.expect_exact(add_prompt1)
- child.sendline('expr ptr')
- child.expect_exact(add_prompt1)
- child.sendline('DONE')
- child.expect_exact(prompt)
- child.sendline('target stop-hook list')
-
- # Now run the program, expect to stop at the first breakpoint which is
- # within the stop-hook range.
- child.expect_exact(prompt)
- child.sendline('run')
- # Make sure we see the stop hook text from the stop of the process from
- # the run hitting the first breakpoint
- child.expect_exact('(void *) $')
- child.expect_exact(prompt)
- child.sendline('thread step-over')
- # Expecting to find the output emitted by the firing of our stop hook.
- child.expect_exact('(void *) $')
- # This is orthogonal to the main stop hook test, but this example shows a bug in
- # CLANG where the line table entry for the "return -1" actually includes some code
- # from the other branch of the if/else, so we incorrectly stop at the "return -1" line.
- # I fixed that in lldb and I'm sticking in a test here because I don't want to have to
- # make up a whole nother test case for it.
- child.sendline('frame info')
- at_line = 'at main.cpp:%d' % (self.correct_step_line)
- print('expecting "%s"' % at_line)
- child.expect_exact(at_line)
-
- # Now continue the inferior, we'll stop at another breakpoint which is
- # outside the stop-hook range.
- child.sendline('process continue')
- child.expect_exact(
- '// Another breakpoint which is outside of the stop-hook range.')
- # self.DebugPExpect(child)
- child.sendline('thread step-over')
- child.expect_exact(
- '// Another breakpoint which is outside of the stop-hook range.')
- # self.DebugPExpect(child)
- # Verify that the 'Stop Hooks' mechanism is NOT BEING fired off.
- self.expect(child.before, exe=False, matching=False,
- substrs=['(void *) $'])
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py b/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py
deleted file mode 100644
index 88267b60b978..000000000000
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/TestStopHookMultipleThreads.py
+++ /dev/null
@@ -1,100 +0,0 @@
-"""
-Test that lldb stop-hook works for multiple threads.
-"""
-
-from __future__ import print_function
-
-
-import os
-import time
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import configuration
-from lldbsuite.test import lldbutil
-
-
-class StopHookForMultipleThreadsTestCase(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Our simple source filename.
- self.source = 'main.cpp'
- # Find the line number to break inside main().
- self.first_stop = line_number(
- self.source, '// Set break point at this line, and add a stop-hook.')
- self.thread_function = line_number(
- self.source,
- '// Break here to test that the stop-hook mechanism works for multiple threads.')
- # Build dictionary to have unique executable names for each test
- # method.
- self.exe_name = self.testMethodName
- self.d = {'CXX_SOURCES': self.source, 'EXE': self.exe_name}
-
- @expectedFlakeyFreeBSD("llvm.org/pr15037")
- # stop hooks sometimes fail to fire on Linux
- @expectedFlakeyLinux("llvm.org/pr15037")
- @expectedFailureAll(
- hostoslist=["windows"],
- bugnumber="llvm.org/pr22274: need a pexpect replacement for windows")
- def test_stop_hook_multiple_threads(self):
- """Test that lldb stop-hook works for multiple threads."""
- self.build(dictionary=self.d)
- self.setTearDownCleanup(dictionary=self.d)
-
- import pexpect
- exe = self.getBuildArtifact(self.exe_name)
- prompt = "(lldb) "
-
- # So that the child gets torn down after the test.
- self.child = pexpect.spawn('%s %s' %
- (lldbtest_config.lldbExec, self.lldbOption))
- child = self.child
- # Turn on logging for what the child sends back.
- if self.TraceOn():
- child.logfile_read = sys.stdout
-
- if lldb.remote_platform:
- child.expect_exact(prompt)
- child.sendline(
- 'platform select %s' %
- lldb.remote_platform.GetName())
- child.expect_exact(prompt)
- child.sendline(
- 'platform connect %s' %
- configuration.lldb_platform_url)
- child.expect_exact(prompt)
- child.sendline(
- 'platform settings -w %s' %
- configuration.lldb_platform_working_dir)
-
- child.expect_exact(prompt)
- child.sendline('target create %s' % exe)
-
- # Set the breakpoint, followed by the target stop-hook commands.
- child.expect_exact(prompt)
- child.sendline('breakpoint set -f main.cpp -l %d' % self.first_stop)
- child.expect_exact(prompt)
- child.sendline(
- 'breakpoint set -f main.cpp -l %d' %
- self.thread_function)
- child.expect_exact(prompt)
-
- # Now run the program, expect to stop at the first breakpoint which is
- # within the stop-hook range.
- child.sendline('run')
- # 'Process 2415 launched', 'Process 2415 stopped'
- child.expect_exact("Process")
- child.expect_exact(prompt)
- child.sendline(
- 'target stop-hook add -o "frame variable --show-globals g_val"')
- child.expect_exact("Stop hook") # 'Stop hook #1 added.'
- child.expect_exact(prompt)
-
- # Continue and expect to find the output emitted by the firing of our
- # stop hook.
- child.sendline('continue')
- child.expect_exact('(uint32_t) ::g_val = ')
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/TestAmbiguousTailCallSeq1.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp
new file mode 100644
index 000000000000..48190184be10
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp
@@ -0,0 +1,33 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; //% self.filecheck("bt", "main.cpp")
+ // CHECK-NOT: func{{[23]}}_amb
+}
+
+void __attribute__((noinline)) func3_amb() { sink(); /* tail */ }
+
+void __attribute__((noinline)) func2_amb() { sink(); /* tail */ }
+
+void __attribute__((noinline)) func1() {
+ if (x > 0)
+ func2_amb(); /* tail */
+ else
+ func3_amb(); /* tail */
+}
+
+int __attribute__((disable_tail_calls)) main(int argc, char **) {
+ // The sequences `main -> func1 -> f{2,3}_amb -> sink` are both plausible. Test
+ // that lldb doesn't attempt to guess which one occurred.
+ func1();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/TestAmbiguousTailCallSeq2.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp
new file mode 100644
index 000000000000..1651db2ea4a1
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/ambiguous_tail_call_seq2/main.cpp
@@ -0,0 +1,38 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; //% self.filecheck("bt", "main.cpp")
+ // CHECK-NOT: func{{[23]}}
+}
+
+void func2();
+
+void __attribute__((noinline)) func1() {
+ if (x < 1)
+ func2();
+ else
+ sink();
+}
+
+void __attribute__((noinline)) func2() {
+ if (x < 1)
+ sink();
+ else
+ func1();
+}
+
+int main() {
+ // Tail recursion creates ambiguous execution histories.
+ x = 0;
+ func1();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/TestDisambiguateCallSite.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp
new file mode 100644
index 000000000000..d3aef19f7a4f
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_call_site/main.cpp
@@ -0,0 +1,32 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial")
+ // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt]
+ // CHECK-NEXT: func2{{.*}} [opt] [artificial]
+ // CHECK-NEXT: main{{.*}} [opt]
+}
+
+void __attribute__((noinline)) func2() {
+ sink(); /* tail */
+}
+
+void __attribute__((noinline)) func1() { sink(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main(int argc, char **) {
+ // The sequences `main -> f{1,2} -> sink` are both plausible. Test that
+ // return-pc call site info allows lldb to pick the correct sequence.
+ func2();
+ if (argc == 100)
+ func1();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/TestDisambiguatePathsToCommonSink.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp
new file mode 100644
index 000000000000..5189218c4ef4
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp
@@ -0,0 +1,38 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink2() {
+ x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=FROM-FUNC1")
+ // FROM-FUNC1: frame #0: 0x{{[0-9a-f]+}} a.out`sink{{.*}} at main.cpp:[[@LINE-1]]:{{.*}} [opt]
+ // FROM-FUNC1-NEXT: sink({{.*}} [opt]
+ // FROM-FUNC1-NEXT: func1{{.*}} [opt] [artificial]
+ // FROM-FUNC1-NEXT: main{{.*}} [opt]
+}
+
+void __attribute__((noinline)) sink(bool called_from_main) {
+ if (called_from_main) {
+ x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=FROM-MAIN")
+ // FROM-MAIN: frame #0: 0x{{[0-9a-f]+}} a.out`sink{{.*}} at main.cpp:[[@LINE-1]]:{{.*}} [opt]
+ // FROM-MAIN-NEXT: main{{.*}} [opt]
+ } else {
+ sink2();
+ }
+}
+
+void __attribute__((noinline)) func1() { sink(false); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main(int argc, char **) {
+ // When func1 tail-calls sink, make sure that the former appears in the
+ // backtrace.
+ sink(true);
+ func1();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/TestDisambiguateTailCallSeq.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp
new file mode 100644
index 000000000000..3c723b8a3ee3
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp
@@ -0,0 +1,31 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial")
+ // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt]
+ // CHECK-NEXT: func3{{.*}} [opt] [artificial]
+ // CHECK-NEXT: func1{{.*}} [opt] [artificial]
+ // CHECK-NEXT: main{{.*}} [opt]
+}
+
+void __attribute__((noinline)) func3() { sink(); /* tail */ }
+
+void __attribute__((noinline)) func2() { sink(); /* tail */ }
+
+void __attribute__((noinline)) func1() { func3(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main(int argc, char **) {
+ // The sequences `main -> func1 -> f{2,3} -> sink` are both plausible. Test
+ // that lldb picks the latter sequence.
+ func1();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/TestInliningAndTailCalls.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
new file mode 100644
index 000000000000..e4504ad151fa
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/inlining_and_tail_calls/main.cpp
@@ -0,0 +1,50 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) tail_call_sink() {
+ x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=TAIL-CALL-SINK")
+ // TAIL-CALL-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`tail_call_sink() at main.cpp:[[@LINE-1]]:4 [opt]
+ // TAIL-CALL-SINK-NEXT: func3{{.*}} [opt] [artificial]
+ // TAIL-CALL-SINK-NEXT: main{{.*}} [opt]
+
+ // TODO: The backtrace should include inlinable_function_which_tail_calls.
+}
+
+void __attribute__((always_inline)) inlinable_function_which_tail_calls() {
+ tail_call_sink();
+}
+
+void __attribute__((noinline)) func3() {
+ inlinable_function_which_tail_calls();
+}
+
+void __attribute__((always_inline)) inline_sink() {
+ x++; //% self.filecheck("bt", "main.cpp", "-check-prefix=INLINE-SINK")
+ // INLINE-SINK: frame #0: 0x{{[0-9a-f]+}} a.out`func2() [inlined] inline_sink() at main.cpp:[[@LINE-1]]:4 [opt]
+ // INLINE-SINK-NEXT: func2{{.*}} [opt]
+ // INLINE-SINK-NEXT: func1{{.*}} [opt] [artificial]
+ // INLINE-SINK-NEXT: main{{.*}} [opt]
+}
+
+void __attribute__((noinline)) func2() { inline_sink(); /* inlined */ }
+
+void __attribute__((noinline)) func1() { func2(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main() {
+ // First, call a function that tail-calls a function, which itself inlines
+ // a third function.
+ func1();
+
+ // Next, call a function which contains an inlined tail-call.
+ func3();
+
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py
new file mode 100644
index 000000000000..038a0c45bf42
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/TestTailCallFrameSBAPI.py
@@ -0,0 +1,73 @@
+"""
+Test SB API support for identifying artificial (tail call) frames.
+"""
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+class TestTailCallFrameSBAPI(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ # If your test case doesn't stress debug info, the
+ # set this to true. That way it won't be run once for
+ # each debug info format.
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipIf(compiler="clang", compiler_version=['<', '7.0'])
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265")
+ def test_tail_call_frame_sbapi(self):
+ self.build()
+ self.do_test()
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def do_test(self):
+ exe = self.getBuildArtifact("a.out")
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ breakpoint = target.BreakpointCreateBySourceRegex("break here",
+ lldb.SBFileSpec("main.cpp"))
+ self.assertTrue(breakpoint and
+ breakpoint.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ error = lldb.SBError()
+ launch_info = lldb.SBLaunchInfo(None)
+ process = target.Launch(launch_info, error)
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # Did we hit our breakpoint?
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process,
+ breakpoint)
+ self.assertEqual(
+ len(threads), 1,
+ "There should be a thread stopped at our breakpoint")
+
+ self.assertEqual(breakpoint.GetHitCount(), 1)
+
+ thread = threads[0]
+
+ # Here's what we expect to see in the backtrace:
+ # frame #0: ... a.out`sink() at main.cpp:13:4 [opt]
+ # frame #1: ... a.out`func3() at main.cpp:14:1 [opt] [artificial]
+ # frame #2: ... a.out`func2() at main.cpp:18:62 [opt]
+ # frame #3: ... a.out`func1() at main.cpp:18:85 [opt] [artificial]
+ # frame #4: ... a.out`main at main.cpp:23:3 [opt]
+ names = ["sink", "func3", "func2", "func1", "main"]
+ artificiality = [False, True, False, True, False]
+ for idx, (name, is_artificial) in enumerate(zip(names, artificiality)):
+ frame = thread.GetFrameAtIndex(idx)
+
+ # Use a relaxed substring check because function dislpay names are
+ # platform-dependent. E.g we see "void sink(void)" on Windows, but
+ # "sink()" on Darwin. This seems like a bug -- just work around it
+ # for now.
+ self.assertTrue(name in frame.GetDisplayFunctionName())
+ self.assertEqual(frame.IsArtificial(), is_artificial)
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp
new file mode 100644
index 000000000000..f9e84da51739
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/sbapi_support/main.cpp
@@ -0,0 +1,25 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; /* break here */
+}
+
+void __attribute__((noinline)) func3() { sink(); /* tail */ }
+
+void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ }
+
+void __attribute__((noinline)) func1() { func2(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main() {
+ func1(); /* regular */
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/TestArtificialFrameStepOutMessage.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp
new file mode 100644
index 000000000000..f2f11365df7a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_message/main.cpp
@@ -0,0 +1,28 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; //% self.filecheck("finish", "main.cpp", "-implicit-check-not=artificial")
+ // CHECK: stop reason = step out
+ // CHECK-NEXT: Stepped out past: frame #1: 0x{{[0-9a-f]+}} a.out`func3{{.*}} [opt] [artificial]
+ // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`func2{{.*}} [opt]
+}
+
+void __attribute__((noinline)) func3() { sink(); /* tail */ }
+
+void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ }
+
+void __attribute__((noinline)) func1() { func2(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main() {
+ func1(); /* regular */
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py
new file mode 100644
index 000000000000..2b432e56a740
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/TestSteppingOutWithArtificialFrames.py
@@ -0,0 +1,95 @@
+"""
+Test SB API support for identifying artificial (tail call) frames.
+"""
+
+import lldb
+import lldbsuite.test.lldbutil as lldbutil
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+
+class TestArtificialFrameThreadStepOut1(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ # If your test case doesn't stress debug info, the
+ # set this to true. That way it won't be run once for
+ # each debug info format.
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def prepare_thread(self):
+ exe = self.getBuildArtifact("a.out")
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+
+ breakpoint = target.BreakpointCreateBySourceRegex("break here",
+ lldb.SBFileSpec("main.cpp"))
+ self.assertTrue(breakpoint and
+ breakpoint.GetNumLocations() == 1,
+ VALID_BREAKPOINT)
+
+ error = lldb.SBError()
+ launch_info = lldb.SBLaunchInfo(None)
+ process = target.Launch(launch_info, error)
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # Did we hit our breakpoint?
+ threads = lldbutil.get_threads_stopped_at_breakpoint(process,
+ breakpoint)
+ self.assertEqual(
+ len(threads), 1,
+ "There should be a thread stopped at our breakpoint")
+
+ self.assertEqual(breakpoint.GetHitCount(), 1)
+
+ thread = threads[0]
+
+ # Here's what we expect to see in the backtrace:
+ # frame #0: ... a.out`sink() at main.cpp:13:4 [opt]
+ # frame #1: ... a.out`func3() at main.cpp:14:1 [opt] [artificial]
+ # frame #2: ... a.out`func2() at main.cpp:18:62 [opt]
+ # frame #3: ... a.out`func1() at main.cpp:18:85 [opt] [artificial]
+ # frame #4: ... a.out`main at main.cpp:23:3 [opt]
+ return thread
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265")
+ def test_stepping_out_past_artificial_frame(self):
+ self.build()
+ thread = self.prepare_thread()
+
+ # Frame #0's ancestor is artificial. Stepping out should move to
+ # frame #2, because we behave as-if artificial frames were not present.
+ thread.StepOut()
+ frame2 = thread.GetSelectedFrame()
+ self.assertEqual(frame2.GetDisplayFunctionName(), "func2()")
+ self.assertFalse(frame2.IsArtificial())
+
+ # Ditto: stepping out of frame #2 should move to frame #4.
+ thread.StepOut()
+ frame4 = thread.GetSelectedFrame()
+ self.assertEqual(frame4.GetDisplayFunctionName(), "main")
+ self.assertFalse(frame2.IsArtificial())
+
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265")
+ def test_return_past_artificial_frame(self):
+ self.build()
+ thread = self.prepare_thread()
+
+ value = lldb.SBValue()
+
+ # Frame #0's ancestor is artificial. Returning from frame #0 should move
+ # to frame #2.
+ thread.ReturnFromFrame(thread.GetSelectedFrame(), value)
+ frame2 = thread.GetSelectedFrame()
+ self.assertEqual(frame2.GetDisplayFunctionName(), "func2()")
+ self.assertFalse(frame2.IsArtificial())
+
+ # Ditto: stepping out of frame #2 should move to frame #4.
+ thread.ReturnFromFrame(thread.GetSelectedFrame(), value)
+ frame4 = thread.GetSelectedFrame()
+ self.assertEqual(frame4.GetDisplayFunctionName(), "main")
+ self.assertFalse(frame2.IsArtificial())
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp
new file mode 100644
index 000000000000..f7a81873906e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/thread_step_out_or_return/main.cpp
@@ -0,0 +1,25 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; // break here
+}
+
+void __attribute__((noinline)) func3() { sink(); /* tail */ }
+
+void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ }
+
+void __attribute__((noinline)) func1() { func2(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main() {
+ func1(); /* regular */
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile
new file mode 100644
index 000000000000..15bc2e7f415b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/Makefile
@@ -0,0 +1,4 @@
+LEVEL = ../../../make
+CXX_SOURCES := main.cpp
+include $(LEVEL)/Makefile.rules
+CXXFLAGS += -g -O1 -glldb
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py
new file mode 100644
index 000000000000..aec4d503fd73
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/TestUnambiguousTailCalls.py
@@ -0,0 +1,5 @@
+from lldbsuite.test import lldbinline
+from lldbsuite.test import decorators
+
+lldbinline.MakeInlineTest(__file__, globals(),
+ [decorators.skipUnlessHasCallSiteInfo])
diff --git a/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp
new file mode 100644
index 000000000000..c180d45b9de6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/tail_call_frames/unambiguous_sequence/main.cpp
@@ -0,0 +1,30 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+volatile int x;
+
+void __attribute__((noinline)) sink() {
+ x++; //% self.filecheck("bt", "main.cpp", "-implicit-check-not=artificial")
+ // CHECK: frame #0: 0x{{[0-9a-f]+}} a.out`sink() at main.cpp:[[@LINE-1]]:4 [opt]
+ // CHECK-NEXT: frame #1: 0x{{[0-9a-f]+}} a.out`func3{{.*}} [opt] [artificial]
+ // CHECK-NEXT: frame #2: 0x{{[0-9a-f]+}} a.out`func2{{.*}} [opt]
+ // CHECK-NEXT: frame #3: 0x{{[0-9a-f]+}} a.out`func1{{.*}} [opt] [artificial]
+ // CHECK-NEXT: frame #4: 0x{{[0-9a-f]+}} a.out`main{{.*}} [opt]
+}
+
+void __attribute__((noinline)) func3() { sink(); /* tail */ }
+
+void __attribute__((disable_tail_calls, noinline)) func2() { func3(); /* regular */ }
+
+void __attribute__((noinline)) func1() { func2(); /* tail */ }
+
+int __attribute__((disable_tail_calls)) main() {
+ func1(); /* regular */
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile b/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile
new file mode 100644
index 000000000000..15cb0b64f218
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/Makefile
@@ -0,0 +1,16 @@
+LEVEL := ../../make
+
+LIB_PREFIX := load_
+
+LD_EXTRAS := -L. -l$(LIB_PREFIX)a
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
+
+a.out: lib_a
+
+lib_%:
+ $(MAKE) VPATH=$(SRCDIR) -I $(SRCDIR) -f $(SRCDIR)/$*.mk
+
+clean::
+ $(MAKE) -f $(SRCDIR)/a.mk clean
diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py b/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py
new file mode 100644
index 000000000000..a6c383ce3c80
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/TestTargetCreateDeps.py
@@ -0,0 +1,100 @@
+"""
+Test that loading of dependents works correctly for all the potential
+combinations.
+"""
+
+from __future__ import print_function
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+@skipIfWindows # Windows deals differently with shared libs.
+class TargetDependentsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ TestBase.setUp(self)
+ self.build()
+
+ def has_exactly_one_image(self, matching, msg=""):
+ self.expect(
+ "image list",
+ "image list should contain at least one image",
+ substrs=['[ 0]'])
+ should_match = not matching
+ self.expect(
+ "image list", msg, matching=should_match, substrs=['[ 1]'])
+
+ @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files
+ def test_dependents_implicit_default_exe(self):
+ """Test default behavior"""
+ exe = self.getBuildArtifact("a.out")
+ self.runCmd("target create " + exe, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(False)
+
+ @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files
+ def test_dependents_explicit_default_exe(self):
+ """Test default behavior"""
+ exe = self.getBuildArtifact("a.out")
+ self.runCmd("target create -ddefault " + exe, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(False)
+
+ def test_dependents_explicit_true_exe(self):
+ """Test default behavior"""
+ exe = self.getBuildArtifact("a.out")
+ self.runCmd("target create -dtrue " + exe, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(True)
+
+ @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files
+ def test_dependents_explicit_false_exe(self):
+ """Test default behavior"""
+ exe = self.getBuildArtifact("a.out")
+ self.runCmd("target create -dfalse " + exe, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(False)
+
+ def test_dependents_implicit_false_exe(self):
+ """Test default behavior"""
+ exe = self.getBuildArtifact("a.out")
+ self.runCmd("target create -d " + exe, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(True)
+
+ def test_dependents_implicit_default_lib(self):
+ ctx = self.platformContext
+ dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension
+ lib = self.getBuildArtifact(dylibName)
+ self.runCmd("target create " + lib, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(True)
+
+ def test_dependents_explicit_default_lib(self):
+ ctx = self.platformContext
+ dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension
+ lib = self.getBuildArtifact(dylibName)
+ self.runCmd("target create -ddefault " + lib, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(True)
+
+ def test_dependents_explicit_true_lib(self):
+ ctx = self.platformContext
+ dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension
+ lib = self.getBuildArtifact(dylibName)
+ self.runCmd("target create -dtrue " + lib, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(True)
+
+ @expectedFailureAll(oslist=["linux"]) #linux does not support loading dependent files
+ def test_dependents_explicit_false_lib(self):
+ ctx = self.platformContext
+ dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension
+ lib = self.getBuildArtifact(dylibName)
+ self.runCmd("target create -dfalse " + lib, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(False)
+
+ def test_dependents_implicit_false_lib(self):
+ ctx = self.platformContext
+ dylibName = ctx.shlib_prefix + 'load_a.' + ctx.shlib_extension
+ lib = self.getBuildArtifact(dylibName)
+ self.runCmd("target create -d " + lib, CURRENT_EXECUTABLE_SET)
+ self.has_exactly_one_image(True)
diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp
new file mode 100644
index 000000000000..c0dac40d0eed
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.cpp
@@ -0,0 +1,13 @@
+//===-- b.c -----------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int a_function ()
+{
+ return 500;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk
new file mode 100644
index 000000000000..f199bfed5b0d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/a.mk
@@ -0,0 +1,9 @@
+LEVEL := ../../make
+
+LIB_PREFIX := load_
+
+DYLIB_NAME := $(LIB_PREFIX)a
+DYLIB_CXX_SOURCES := a.cpp
+DYLIB_ONLY := YES
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp b/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp
new file mode 100644
index 000000000000..08fbb59d8a58
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_create_deps/main.cpp
@@ -0,0 +1,17 @@
+//===-- main.c --------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+extern int a_function ();
+extern int b_function ();
+
+int
+main (int argc, char const *argv[])
+{
+ return a_function();
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/Makefile b/packages/Python/lldbsuite/test/functionalities/target_var/Makefile
new file mode 100644
index 000000000000..bb9cc4f2f66d
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_var/Makefile
@@ -0,0 +1,10 @@
+LEVEL = ../../make
+
+include $(LEVEL)/Makefile.rules
+
+a.out: globals.ll
+ $(CC) $(CFLAGS) -g -c $^ -o globals.o
+ $(LD) $(LDFLAGS) -g globals.o -o $@
+
+clean::
+ rm -rf globals.o a.out *.dSYM
diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py b/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py
new file mode 100644
index 000000000000..d3afacca72f5
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_var/TestTargetVar.py
@@ -0,0 +1,23 @@
+"""
+Test that target var can resolve complex DWARF expressions.
+"""
+
+import lldb
+import sys
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class targetCommandTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ @skipIfDarwinEmbedded # needs x86_64
+ @skipIf(debug_info="gmodules") # not relevant
+ @skipIf(compiler="clang", compiler_version=['<', '7.0'])
+ def testTargetVarExpr(self):
+ self.build()
+ lldbutil.run_to_name_breakpoint(self, 'main')
+ self.expect("target variable i", substrs=['i', '42'])
diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/globals.c b/packages/Python/lldbsuite/test/functionalities/target_var/globals.c
new file mode 100644
index 000000000000..266192849641
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_var/globals.c
@@ -0,0 +1,6 @@
+int i = 42;
+int *p = &i;
+
+int main() {
+ return *p;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll b/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll
new file mode 100644
index 000000000000..192d4e126981
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/target_var/globals.ll
@@ -0,0 +1,42 @@
+source_filename = "globals.c"
+target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-apple-macosx10.14.0"
+
+@i = global i32 42, align 4
+@p = global i32* @i, align 8, !dbg !0, !dbg !6
+
+; Function Attrs: noinline nounwind optnone ssp uwtable
+define i32 @main() #0 !dbg !15 {
+entry:
+ %retval = alloca i32, align 4
+ store i32 0, i32* %retval, align 4
+ %0 = load i32*, i32** @p, align 8, !dbg !18
+ %1 = load i32, i32* %0, align 4, !dbg !18
+ ret i32 %1, !dbg !18
+}
+
+attributes #0 = { noinline nounwind optnone ssp uwtable }
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!10, !11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression(DW_OP_deref))
+!1 = distinct !DIGlobalVariable(name: "i", scope: !2, file: !3, line: 1, type: !9, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, emissionKind: FullDebug, globals: !5)
+!3 = !DIFile(filename: "globals.c", directory: "/")
+!4 = !{}
+!5 = !{!0, !6}
+!6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression())
+!7 = distinct !DIGlobalVariable(name: "p", scope: !2, file: !3, line: 2, type: !8, isLocal: false, isDefinition: true)
+!8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !{i32 2, !"Dwarf Version", i32 4}
+!11 = !{i32 2, !"Debug Info Version", i32 3}
+!12 = !{i32 1, !"wchar_size", i32 4}
+!13 = !{i32 7, !"PIC Level", i32 2}
+!14 = !{!"clang version 8.0.0 (trunk 340838) (llvm/trunk 340843)"}
+!15 = distinct !DISubprogram(name: "main", scope: !3, file: !3, line: 4, type: !16, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: false, unit: !2, retainedNodes: !4)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9}
+!18 = !DILocation(line: 5, scope: !15)
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile
new file mode 100644
index 000000000000..f0bcf9752de2
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/Makefile
@@ -0,0 +1,6 @@
+LEVEL = ../../../make
+
+CXXFLAGS += -std=c++11
+CXX_SOURCES := main.cpp
+ENABLE_THREADS := YES
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py
new file mode 100644
index 000000000000..4e595ea4c5f6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/TestBacktraceLimit.py
@@ -0,0 +1,31 @@
+"""
+Test that the target.process.thread.max-backtrace-depth setting works.
+"""
+
+import unittest2
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class BacktraceLimitSettingTest(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ NO_DEBUG_INFO_TESTCASE = True
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def test_backtrace_depth(self):
+ """Test that the max-backtrace-depth setting limits backtraces."""
+ self.build()
+ self.main_source_file = lldb.SBFileSpec("main.cpp")
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+ "Set a breakpoint here", self.main_source_file)
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("settings set target.process.thread.max-backtrace-depth 30", result)
+ self.assertEqual(True, result.Succeeded())
+ self.assertEqual(30, thread.GetNumFrames())
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp
new file mode 100644
index 000000000000..eca1eadc8e45
--- /dev/null
+++ b/packages/Python/lldbsuite/test/functionalities/thread/backtrace_limit/main.cpp
@@ -0,0 +1,13 @@
+int bottom () {
+ return 1; // Set a breakpoint here
+}
+int foo(int in) {
+ if (in > 0)
+ return foo(--in) + 5;
+ else
+ return bottom();
+}
+int main()
+{
+ return foo(500);
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py
index b20b738825a2..fa96db06a59d 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/crash_during_step/TestCrashDuringStep.py
@@ -20,7 +20,6 @@ class CrashDuringStepTestCase(TestBase):
TestBase.setUp(self)
self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
# IO error due to breakpoint at invalid address
@expectedFailureAll(triple=re.compile('^mips'))
def test_step_inst_with(self):
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py
index 3f26d8c76579..2afa77d34b5e 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py
@@ -23,7 +23,6 @@ class CreateAfterAttachTestCase(TestBase):
# Occasionally hangs on Windows, may be same as other issues.
@skipIfWindows
@skipIfiOSSimulator
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_create_after_attach_with_popen(self):
"""Test thread creation after process attach."""
self.build(dictionary=self.getBuildFlags(use_cpp11=False))
@@ -34,7 +33,6 @@ class CreateAfterAttachTestCase(TestBase):
@skipIfRemote
@skipIfWindows # Windows doesn't have fork.
@skipIfiOSSimulator
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_create_after_attach_with_fork(self):
"""Test thread creation after process attach."""
self.build(dictionary=self.getBuildFlags(use_cpp11=False))
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
index c62990ccc93a..76c2c47da2cf 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
@@ -23,9 +23,6 @@ class ExitDuringBreakpointTestCase(TestBase):
# Find the line number for our breakpoint.
self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
- @expectedFailureAll(
- oslist=["linux"],
- bugnumber="llvm.org/pr15824 thread states not properly maintained")
def test(self):
"""Test thread exit during breakpoint handling."""
self.build(dictionary=self.getBuildFlags())
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
index 0343a888a0f1..76488a7185de 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/exit_during_step/TestExitDuringStep.py
@@ -18,6 +18,7 @@ class ExitDuringStepTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipIfFreeBSD # llvm.org/pr21411: test is hanging
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test(self):
"""Test thread exit during step handling."""
self.build(dictionary=self.getBuildFlags())
@@ -27,6 +28,7 @@ class ExitDuringStepTestCase(TestBase):
True)
@skipIfFreeBSD # llvm.org/pr21411: test is hanging
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test_step_over(self):
"""Test thread exit during step-over handling."""
self.build(dictionary=self.getBuildFlags())
@@ -36,6 +38,7 @@ class ExitDuringStepTestCase(TestBase):
False)
@skipIfFreeBSD # llvm.org/pr21411: test is hanging
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test_step_in(self):
"""Test thread exit during step-in handling."""
self.build(dictionary=self.getBuildFlags())
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py
index 3300078e8c60..7194dafe0ac1 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/jump/TestThreadJump.py
@@ -17,7 +17,6 @@ class ThreadJumpTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr32343")
def test(self):
"""Test thread jump handling."""
self.build(dictionary=self.getBuildFlags())
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py
index cff9b5a8d5e5..3d7e26816f84 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/multi_break/TestMultipleBreakpoints.py
@@ -32,9 +32,7 @@ class MultipleBreakpointTestCase(TestBase):
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr18190 thread states not properly maintained")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr24668, llvm.org/pr38373
def test(self):
"""Test simultaneous breakpoints in multiple threads."""
self.build(dictionary=self.getBuildFlags())
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
index 724b9d8be907..9aa4a831a745 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/num_threads/TestNumThreads.py
@@ -64,7 +64,7 @@ class NumberOfThreadsTestCase(TestBase):
'Number of expected threads and actual threads do not match.')
@skipIfDarwin # rdar://33462362
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr37658")
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr37658, llvm.org/pr38373
def test_unique_stacks(self):
"""Test backtrace unique with multiple threads executing the same stack."""
self.build()
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py
index 0cbd94e199dc..4b1247316e18 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/state/TestThreadStates.py
@@ -52,17 +52,6 @@ class ThreadStateTestCase(TestBase):
self.thread_state_after_expression_test()
# thread states not properly maintained
- @unittest2.expectedFailure("llvm.org/pr16712")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
- @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>
- def test_process_interrupt(self):
- """Test process interrupt."""
- self.build(dictionary=self.getBuildFlags(use_cpp11=False))
- self.process_interrupt_test()
-
- # thread states not properly maintained
@unittest2.expectedFailure("llvm.org/pr15824 and <rdar://problem/28557237>")
@expectedFailureAll(
oslist=["windows"],
@@ -198,13 +187,19 @@ class ThreadStateTestCase(TestBase):
# Let the process run to completion
self.runCmd("process continue")
- def process_interrupt_test(self):
+ @expectedFailureAll(
+ oslist=["windows"],
+ bugnumber="llvm.org/pr24668: Breakpoints not resolved correctly")
+ @skipIfDarwin # llvm.org/pr15824 thread states not properly maintained and <rdar://problem/28557237>
+ @no_debug_info_test
+ def test_process_interrupt(self):
"""Test process interrupt and continue."""
+ self.build(dictionary=self.getBuildFlags(use_cpp11=False))
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
# This should create a breakpoint in the main thread.
- lldbutil.run_break_set_by_file_and_line(
+ bpno = lldbutil.run_break_set_by_file_and_line(
self, "main.cpp", self.break_1, num_expected_locations=1)
# Run the program.
@@ -218,6 +213,10 @@ class ThreadStateTestCase(TestBase):
process, lldb.eStopReasonBreakpoint)
self.assertIsNotNone(thread)
+ # Remove the breakpoint to avoid the single-step-over-bkpt dance in the
+ # "continue" below
+ self.assertTrue(target.BreakpointDelete(bpno))
+
# Continue, the inferior will go into an infinite loop waiting for
# 'g_test' to change.
self.dbg.SetAsync(True)
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py
index 238b18837884..e786e8d7ff1e 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/step_out/TestThreadStepOut.py
@@ -25,6 +25,7 @@ class ThreadStepOutTestCase(TestBase):
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr18066 inferior does not exit")
+ @skipIfWindows # This test will hang on windows llvm.org/pr21753
@expectedFailureAll(oslist=["windows"])
def test_step_single_thread(self):
"""Test thread step out on one thread via command interpreter. """
@@ -39,6 +40,7 @@ class ThreadStepOutTestCase(TestBase):
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint")
+ @skipIfWindows # This test will hang on windows llvm.org/pr21753
@expectedFailureAll(oslist=["windows"])
@expectedFailureAll(oslist=["watchos"], archs=['armv7k'], bugnumber="rdar://problem/34674488") # stop reason is trace when it should be step-out
def test_step_all_threads(self):
@@ -54,6 +56,7 @@ class ThreadStepOutTestCase(TestBase):
@expectedFailureAll(
oslist=["freebsd"],
bugnumber="llvm.org/pr19347 2nd thread stops at breakpoint")
+ @skipIfWindows # This test will hang on windows llvm.org/pr21753
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24681")
def test_python(self):
"""Test thread step out on one thread via Python API (dwarf)."""
diff --git a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
index 07ceb3f5f6b7..c8b6e675b8a9 100644
--- a/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
+++ b/packages/Python/lldbsuite/test/functionalities/thread/thread_exit/TestThreadExit.py
@@ -8,6 +8,7 @@ from __future__ import print_function
import os
import time
import lldb
+from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
import lldbsuite.test.lldbutil as lldbutil
@@ -25,6 +26,7 @@ class ThreadExitTestCase(TestBase):
self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here')
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test(self):
"""Test thread exit handling."""
self.build(dictionary=self.getBuildFlags())
diff --git a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py
index 7302f76c1fbc..a6d77924892b 100644
--- a/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py
+++ b/packages/Python/lldbsuite/test/functionalities/watchpoint/multiple_hits/TestMultipleHits.py
@@ -22,6 +22,7 @@ class MultipleHitsTestCase(TestBase):
oslist=["windows"],
bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
@skipIf(bugnumber="llvm.org/pr30758", oslist=["linux"], archs=["arm", "aarch64", "powerpc64le"])
+ @skipIfwatchOS
def test(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/packages/Python/lldbsuite/test/help/TestHelp.py b/packages/Python/lldbsuite/test/help/TestHelp.py
index 2b89b49a6229..7d66b08b86a2 100644
--- a/packages/Python/lldbsuite/test/help/TestHelp.py
+++ b/packages/Python/lldbsuite/test/help/TestHelp.py
@@ -231,6 +231,17 @@ class HelpCommandTestCase(TestBase):
self.expect("help averyfriendlyalias", matching=True,
substrs=['I am a very friendly alias'])
@no_debug_info_test
+ def test_alias_prints_origin(self):
+ """Test that 'help <unique_match_to_alias>' prints the alias origin."""
+ def cleanup():
+ self.runCmd('command unalias alongaliasname', check=False)
+
+ self.addTearDownHook(cleanup)
+ self.runCmd('command alias alongaliasname help')
+ self.expect("help alongaliasna", matching=True,
+ substrs=["'alongaliasna' is an abbreviation for 'help'"])
+
+ @no_debug_info_test
def test_help_format_output(self):
"""Test that help output reaches TerminalWidth."""
self.runCmd(
diff --git a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py
index 930a09412eab..e3ae93d3a5ba 100644
--- a/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py
+++ b/packages/Python/lldbsuite/test/lang/c/anonymous/TestAnonymous.py
@@ -70,7 +70,6 @@ class AnonymousTestCase(TestBase):
self.expect("expression z.y", VARIABLES_DISPLAYED_CORRECTLY,
substrs=["(type_y) $", "dummy = 2"])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21550")
def test_expr_null(self):
self.build()
self.common_setup(self.line2)
diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py
index 22b8a2991001..ba924683ad75 100644
--- a/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py
+++ b/packages/Python/lldbsuite/test/lang/c/bitfields/TestBitfields.py
@@ -116,6 +116,38 @@ class BitfieldsTestCase(TestBase):
self.expect("expr/x (packed.c)", VARIABLES_DISPLAYED_CORRECTLY,
substrs=['uint32_t', "7112233"])
+ for bit in range(1,18):
+ expected = "1" if bit in [1, 5, 7, 13] else "0"
+ self.expect("expr even_more_bits.b" + str(bit), VARIABLES_DISPLAYED_CORRECTLY,
+ substrs=['uint8_t', expected])
+
+ for bit in [3, 10, 14]:
+ self.expect("expr even_more_bits.b" + str(bit) + " = 1", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs=['uint8_t', "1"])
+
+ self.expect(
+ "frame variable --show-types even_more_bits",
+ VARIABLES_DISPLAYED_CORRECTLY,
+ substrs=[
+ '(uint8_t:1) b1 = \'\\x01\'',
+ '(uint8_t:1) b2 = \'\\0\'',
+ '(uint8_t:1) b3 = \'\\x01\'',
+ '(uint8_t:1) b4 = \'\\0\'',
+ '(uint8_t:1) b5 = \'\\x01\'',
+ '(uint8_t:1) b6 = \'\\0\'',
+ '(uint8_t:1) b7 = \'\\x01\'',
+ '(uint8_t:1) b8 = \'\\0\'',
+ '(uint8_t:1) b9 = \'\\0\'',
+ '(uint8_t:1) b10 = \'\\x01\'',
+ '(uint8_t:1) b12 = \'\\0\'',
+ '(uint8_t:1) b13 = \'\\x01\'',
+ '(uint8_t:1) b14 = \'\\x01\'',
+ '(uint8_t:1) b15 = \'\\0\'',
+ '(uint8_t:1) b16 = \'\\0\'',
+ '(uint8_t:1) b17 = \'\\0\'',
+ ])
+
+
@add_test_categories(['pyapi'])
# BitFields exhibit crashes in record layout on Windows
# (http://llvm.org/pr21800)
diff --git a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c
index 236c926d81bd..fe972dbbe856 100644
--- a/packages/Python/lldbsuite/test/lang/c/bitfields/main.c
+++ b/packages/Python/lldbsuite/test/lang/c/bitfields/main.c
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include <stdint.h>
#include <stdio.h>
+#include <string.h>
int main (int argc, char const *argv[])
{
@@ -63,6 +64,20 @@ int main (int argc, char const *argv[])
more_bits.c = 1;
more_bits.d = 0;
+ struct EvenMoreBits
+ {
+ uint8_t b1 : 1, b2 : 1, b3 : 1, b4 : 1, b5 : 1, b6 : 1,
+ b7 : 1, b8 : 1, b9 : 1, b10 : 1, b11 : 1, b12 : 1,
+ b13 : 1, b14 : 1, b15 : 1, b16 : 1, b17 : 1;
+ };
+
+ struct EvenMoreBits even_more_bits;
+ memset(&even_more_bits, 0, sizeof(even_more_bits));
+ even_more_bits.b1 = 1;
+ even_more_bits.b5 = 1;
+ even_more_bits.b7 = 1;
+ even_more_bits.b13 = 1;
+
#pragma pack(1)
struct PackedBits
{
diff --git a/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py b/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
index fa14e5ef62e6..b0fde47a2c0b 100644
--- a/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
+++ b/packages/Python/lldbsuite/test/lang/c/conflicting-symbol/TestConflictingSymbol.py
@@ -93,6 +93,7 @@ class TestConflictingSymbols(TestBase):
"Multiple internal symbols"])
@expectedFailureAll(bugnumber="llvm.org/pr35043")
+ @skipIfWindows # This test is "passing" on Windows, but it is a false positive.
def test_shadowed(self):
self.build()
exe = self.getBuildArtifact("a.out")
diff --git a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py
index 576e9ecd52ad..311c5ec8e120 100644
--- a/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py
+++ b/packages/Python/lldbsuite/test/lang/c/inlines/TestRedefinitionsInInlines.py
@@ -3,9 +3,7 @@ from lldbsuite.test import decorators
lldbinline.MakeInlineTest(__file__,
globals(),
- [decorators.expectedFailureAll(oslist=["windows"],
- bugnumber="llvm.org/pr27845"),
- decorators.expectedFailureAll(compiler="clang",
- compiler_version=["<",
- "3.5"],
- bugnumber="llvm.org/pr27845")])
+ [decorators.expectedFailureAll(compiler="clang",
+ compiler_version=["<",
+ "3.5"],
+ bugnumber="llvm.org/pr27845")])
diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile b/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile
new file mode 100644
index 000000000000..fd7201886586
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/c/local_variables/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+CFLAGS_EXTRAS += -O1
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py b/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py
new file mode 100644
index 000000000000..7071b675f3bc
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/c/local_variables/TestLocalVariables.py
@@ -0,0 +1,55 @@
+"""Show local variables and check that they can be inspected.
+
+This test was added after we made a change in clang to normalize
+DW_OP_constu(X < 32) to DW_OP_litX which broke the debugger because
+it didn't read the value as an unsigned.
+"""
+
+from __future__ import print_function
+
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LocalVariablesTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+ # Find the line number to break inside main().
+ self.source = 'main.c'
+ self.line = line_number(
+ self.source, '// Set break point at this line.')
+
+ def test_c_local_variables(self):
+ """Test local variable value."""
+ self.build()
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ # Break inside the main.
+ lldbutil.run_break_set_by_file_and_line(
+ self, self.source, self.line, num_expected_locations=1, loc_exact=True)
+
+ # Now launch the process, and do not stop at entry point.
+ process = target.LaunchSimple(
+ None, None, self.get_process_working_directory())
+ self.assertTrue(process, PROCESS_IS_VALID)
+
+ # The stop reason of the thread should be breakpoint.
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped',
+ 'stop reason = breakpoint'])
+
+ # The breakpoint should have a hit count of 1.
+ self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
+ substrs=[' resolved, hit count = 1'])
+
+ self.expect("frame variable i", VARIABLES_DISPLAYED_CORRECTLY,
+ substrs=['(unsigned int) i = 10'])
diff --git a/packages/Python/lldbsuite/test/lang/c/local_variables/main.c b/packages/Python/lldbsuite/test/lang/c/local_variables/main.c
new file mode 100644
index 000000000000..2ab579a71a75
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/c/local_variables/main.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+
+void bar(unsigned i)
+{
+ printf("%d\n", i);
+}
+
+void foo(unsigned j)
+{
+ unsigned i = j;
+ bar(i);
+ i = 10;
+ bar(i); // Set break point at this line.
+}
+
+int main(int argc, char** argv)
+{
+ foo(argc);
+}
diff --git a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py
index f53a19138356..d1595163f6e3 100644
--- a/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py
+++ b/packages/Python/lldbsuite/test/lang/c/shared_lib/TestSharedLib.py
@@ -35,12 +35,10 @@ class SharedLibTestCase(TestBase):
"expression GetMeASubFoo(my_foo_ptr)",
startstr="(sub_foo *) $")
- @expectedFailureAll(oslist=["windows"])
def test_expr(self):
"""Test that types work when defined in a shared library and forward-declared in the main executable"""
self.common_test_expr(True)
- @expectedFailureAll(oslist=["windows"])
def test_expr_no_preload(self):
"""Test that types work when defined in a shared library and forward-declared in the main executable, but with preloading disabled"""
self.common_test_expr(False)
diff --git a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py
index b1c8a5ecf4bf..597a247178e4 100644
--- a/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py
+++ b/packages/Python/lldbsuite/test/lang/c/strings/TestCStrings.py
@@ -11,7 +11,6 @@ class CStringsTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_with_run_command(self):
"""Tests that C strings work as expected in expressions"""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py
index af362f5be5d7..c8308c16011e 100644
--- a/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py
+++ b/packages/Python/lldbsuite/test/lang/c/struct_types/TestStructTypes.py
@@ -1,7 +1,4 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
-lldbinline.MakeInlineTest(
- __file__, globals(), [
- decorators.expectedFailureAll(
- oslist=["windows"], bugnumber="llvm.org/pr24764")])
+lldbinline.MakeInlineTest(__file__, globals())
diff --git a/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py b/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py
index b2c9bbb83c0f..9eb25e4d1050 100644
--- a/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py
+++ b/packages/Python/lldbsuite/test/lang/c/unicode/TestUnicodeSymbols.py
@@ -9,6 +9,7 @@ class TestUnicodeSymbols(TestBase):
mydir = TestBase.compute_mydir(__file__)
+ @skipIf(compiler="clang", compiler_version=['<', '7.0'])
def test_union_members(self):
self.build()
spec = lldb.SBModuleSpec()
diff --git a/packages/Python/lldbsuite/test/lang/c/vla/Makefile b/packages/Python/lldbsuite/test/lang/c/vla/Makefile
new file mode 100644
index 000000000000..b09a579159d4
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/c/vla/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py b/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py
new file mode 100644
index 000000000000..f6341ec24fa6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/c/vla/TestVLA.py
@@ -0,0 +1,27 @@
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import decorators
+import lldbsuite.test.lldbutil as lldbutil
+
+
+class TestVLA(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @decorators.skipIf(compiler="clang", compiler_version=['<', '8.0'])
+ def test_vla(self):
+ self.build()
+ _, process, _, _ = lldbutil.run_to_source_breakpoint(
+ self, "break here", lldb.SBFileSpec('main.c'))
+
+ def test(a, array):
+ for i in range(a):
+ self.expect("fr v vla[%d]"%i, substrs=["int", "%d"%(a-i)])
+ self.expect("expr vla[%d]"%i, substrs=["int", "%d"%(a-i)])
+ self.expect("frame var vla", substrs=array)
+ self.expect("expr vla", error=True, substrs=["incomplete"])
+
+ test(2, ["int []", "[0] = 2, [1] = 1"])
+ process.Continue()
+ test(4, ["int []", "[0] = 4, [1] = 3, [2] = 2, [3] = 1"])
+
diff --git a/packages/Python/lldbsuite/test/lang/c/vla/main.c b/packages/Python/lldbsuite/test/lang/c/vla/main.c
new file mode 100644
index 000000000000..ba9cc1855607
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/c/vla/main.c
@@ -0,0 +1,15 @@
+void pause() {}
+
+int foo(int a) {
+ int vla[a];
+
+ for (int i = 0; i < a; ++i)
+ vla[i] = a-i;
+
+ pause(); // break here
+ return vla[a-1];
+}
+
+int main (void) {
+ return foo(2) + foo(4);
+}
diff --git a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py
index 9b227bc8d3c8..b6274b3d2669 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/call-function/TestCallCPPFunction.py
@@ -16,9 +16,6 @@ class CallCPPFunctionTestCase(TestBase):
TestBase.setUp(self)
self.line = line_number('main.cpp', '// breakpoint')
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_with_run_command(self):
"""Test calling a function by basename"""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py
index a344c4f7d18a..080c051de98f 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/chained-calls/TestCppChainedCalls.py
@@ -8,7 +8,6 @@ class TestCppChainedCalls(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_with_run_command(self):
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py b/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py
index aad2ea20c133..7e67f73b7092 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/class-template-parameter-pack/TestClassTemplateParameterPack.py
@@ -4,6 +4,4 @@ from lldbsuite.test import decorators
lldbinline.MakeInlineTest(
__file__, globals(), [
decorators.expectedFailureAll(
- oslist=["windows"], bugnumber="llvm.org/pr24764"),
- decorators.expectedFailureAll(
compiler="gcc")])
diff --git a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py
index 97b0bfd8aee0..eead3c509ff0 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/class_static/TestStaticVariables.py
@@ -23,7 +23,6 @@ class StaticVariableTestCase(TestBase):
# Find the line number to break at.
self.line = line_number('main.cpp', '// Set break point at this line.')
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
def test_with_run_command(self):
"""Test that file and class static variables display correctly."""
self.build()
@@ -63,7 +62,6 @@ class StaticVariableTestCase(TestBase):
compiler=["clang"],
compiler_version=["<", "3.9"],
bugnumber='llvm.org/pr20550')
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
def test_with_run_command_complete(self):
"""
Test that file and class static variables display correctly with
@@ -108,8 +106,8 @@ class StaticVariableTestCase(TestBase):
compiler=["clang"],
compiler_version=["<", "3.9"],
bugnumber='llvm.org/pr20550')
- @add_test_categories(['pyapi'])
@expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
+ @add_test_categories(['pyapi'])
def test_with_python_api(self):
"""Test Python APIs on file and class static variables."""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py
index fa68d0a15021..4ead709cf565 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/global_operators/TestCppGlobalOperators.py
@@ -49,7 +49,6 @@ class TestCppGlobalOperators(TestBase):
return thread.GetSelectedFrame()
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_equals_operator(self):
frame = self.prepare_executable_and_get_frame()
@@ -87,7 +86,6 @@ class TestCppGlobalOperators(TestBase):
self.assertTrue(got_type.IsPointerType())
self.assertEqual(got_type.GetPointeeType().GetName(), "Struct")
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765")
def test_operator_new(self):
frame = self.prepare_executable_and_get_frame()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py
index 284caabbc17b..c8308c16011e 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/lambdas/TestLambdas.py
@@ -1,7 +1,4 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
-lldbinline.MakeInlineTest(
- __file__, globals(), [
- lldbinline.expectedFailureAll(
- oslist=["windows"])])
+lldbinline.MakeInlineTest(__file__, globals())
diff --git a/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py b/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py
index af362f5be5d7..c8308c16011e 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/llvm-style/TestLLVMStyle.py
@@ -1,7 +1,4 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
-lldbinline.MakeInlineTest(
- __file__, globals(), [
- decorators.expectedFailureAll(
- oslist=["windows"], bugnumber="llvm.org/pr24764")])
+lldbinline.MakeInlineTest(__file__, globals())
diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py
index 2837cfd9244e..9c65966b348a 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/namespace/TestNamespaceLookup.py
@@ -42,11 +42,9 @@ class NamespaceLookupTestCase(TestBase):
'stop reason = breakpoint'])
@expectedFailureAll(
- oslist=[
- "windows",
- "linux",
- "freebsd"],
+ oslist=["freebsd"],
bugnumber="llvm.org/pr25819")
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test_scope_lookup_with_run_command(self):
"""Test scope lookup of functions in lldb."""
self.build()
@@ -185,6 +183,7 @@ class NamespaceLookupTestCase(TestBase):
self.expect("expr -- foo()", startstr="(int) $2 = 42")
@unittest2.expectedFailure("lldb file scope lookup bugs")
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test_file_scope_lookup_with_run_command(self):
"""Test file scope lookup in lldb."""
self.build()
@@ -204,7 +203,7 @@ class NamespaceLookupTestCase(TestBase):
# finds the global ::func().
self.expect("expr -- func()", startstr="(int) $0 = 2")
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr25819")
+ @skipIfWindows # This is flakey on Windows: llvm.org/pr38373
def test_scope_lookup_before_using_with_run_command(self):
"""Test scope lookup before using in lldb."""
self.build()
@@ -230,10 +229,7 @@ class NamespaceLookupTestCase(TestBase):
oslist=["linux"],
debug_info=["dwo"]) # Skip to avoid crash
@expectedFailureAll(
- oslist=[
- "windows",
- "linux",
- "freebsd"],
+ oslist=["freebsd"],
bugnumber="llvm.org/pr25819")
def test_scope_after_using_directive_lookup_with_run_command(self):
"""Test scope lookup after using directive in lldb."""
@@ -297,10 +293,7 @@ class NamespaceLookupTestCase(TestBase):
self.expect("expr -- func()", startstr="error")
@expectedFailureAll(
- oslist=[
- "windows",
- "linux",
- "freebsd"],
+ oslist=["freebsd"],
bugnumber="llvm.org/pr25819")
def test_scope_lookup_shadowed_by_using_with_run_command(self):
"""Test scope lookup shadowed by using in lldb."""
diff --git a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py
index af362f5be5d7..c8308c16011e 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/namespace_conflicts/TestNamespaceConflicts.py
@@ -1,7 +1,4 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
-lldbinline.MakeInlineTest(
- __file__, globals(), [
- decorators.expectedFailureAll(
- oslist=["windows"], bugnumber="llvm.org/pr24764")])
+lldbinline.MakeInlineTest(__file__, globals())
diff --git a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py
index 7f68eb8923eb..ad969ef3d088 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/overloaded-functions/TestOverloadedFunctions.py
@@ -16,9 +16,6 @@ class OverloadedFunctionsTestCase(TestBase):
TestBase.setUp(self)
self.line = line_number('main.cpp', '// breakpoint')
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_with_run_command(self):
"""Test that functions with the same name are resolved correctly"""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py
index cc79366c7149..5e31d93eb163 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/rvalue-references/TestRvalueReferences.py
@@ -16,9 +16,6 @@ class RvalueReferencesTestCase(TestBase):
@expectedFailureAll(
compiler="icc",
bugnumber="ICC (13.1, 14-beta) do not emit DW_TAG_rvalue_reference_type.")
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_with_run_command(self):
"""Test that rvalues are supported in the C++ expression parser"""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py
index c7afeb2dbb6f..213e7fbe9022 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/scope/TestCppScope.py
@@ -15,7 +15,7 @@ class TestCppScopes(TestBase):
def test_all_but_c(self):
self.do_test(False)
- @expectedFailureAll(oslist=["windows"])
+ @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24764")
def test_c(self):
self.do_test(True)
diff --git a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py
index 404ef22a0b8c..4b422674134c 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/static_methods/TestCPPStaticMethods.py
@@ -16,7 +16,6 @@ class CPPStaticMethodsTestCase(TestBase):
TestBase.setUp(self)
self.line = line_number('main.cpp', '// Break at this line')
- @expectedFailureAll(oslist=["windows"])
def test_with_run_command(self):
"""Test that static methods are properly distinguished from regular methods"""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile
new file mode 100644
index 000000000000..a42bb089d15a
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/Makefile
@@ -0,0 +1,7 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+CXXFLAGS += -std=c++11
+USE_LIBCPP := 1
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py
new file mode 100644
index 000000000000..abd35acd15bb
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/TestStdFunctionStepIntoCallable.py
@@ -0,0 +1,71 @@
+"""
+Test stepping into std::function
+"""
+
+from __future__ import print_function
+
+
+import lldb
+import sys
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LibCxxFunctionSteppingIntoCallableTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @add_test_categories(["libc++"])
+ def test(self):
+ """Test that std::function as defined by libc++ is correctly printed by LLDB"""
+ self.build()
+
+ self.main_source = "main.cpp"
+ self.main_source_spec = lldb.SBFileSpec(self.main_source)
+ self.source_foo_line = line_number(
+ self.main_source, '// Source foo start line')
+ self.source_lambda_f2_line = line_number(
+ self.main_source, '// Source lambda used by f2 start line')
+ self.source_lambda_f3_line = line_number(
+ self.main_source, '// Source lambda used by f3 start line')
+ self.source_bar_operator_line = line_number(
+ self.main_source, '// Source Bar::operator()() start line')
+ self.source_bar_add_num_line = line_number(
+ self.main_source, '// Source Bar::add_num start line')
+ self.source_main_invoking_f1 = line_number(
+ self.main_source, '// Source main invoking f1')
+
+ (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
+ self, "// Set break point at this line.", self.main_source_spec)
+
+ thread.StepInto()
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_main_invoking_f1 ) ;
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ;
+
+ thread.StepInto()
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_foo_line ) ;
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ;
+ process.Continue()
+
+ thread.StepInto()
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_lambda_f2_line ) ;
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ;
+ process.Continue()
+
+ thread.StepInto()
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_lambda_f3_line ) ;
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ;
+ process.Continue()
+
+ thread.StepInto()
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_bar_operator_line ) ;
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ;
+ process.Continue()
+
+ thread.StepInto()
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetLine(), self.source_bar_add_num_line ) ;
+ self.assertEqual( thread.GetFrameAtIndex(0).GetLineEntry().GetFileSpec().GetFilename(), self.main_source) ;
+ process.Continue()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp
new file mode 100644
index 000000000000..a85e77db040e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/cpp/std-function-step-into-callable/main.cpp
@@ -0,0 +1,38 @@
+#include <functional>
+
+int foo(int x, int y) {
+ return x + y - 1; // Source foo start line
+}
+
+struct Bar {
+ int operator()() {
+ return 66 ; // Source Bar::operator()() start line
+ }
+ int add_num(int i) const { return i + 3 ; } // Source Bar::add_num start line
+ int num_ = 0 ;
+} ;
+
+int main (int argc, char *argv[])
+{
+ int acc = 42;
+ std::function<int (int,int)> f1 = foo;
+ std::function<int (int)> f2 = [acc,f1] (int x) -> int {
+ return x+f1(acc,x); // Source lambda used by f2 start line
+ };
+
+ auto f = [](int x, int y) { return x + y; }; // Source lambda used by f3 start line
+ auto g = [](int x, int y) { return x * y; } ;
+ std::function<int (int,int)> f3 = argc %2 ? f : g ;
+
+ Bar bar1 ;
+ std::function<int ()> f4( bar1 ) ;
+ std::function<int (const Bar&, int)> f5 = &Bar::add_num;
+ std::function<int(Bar const&)> f_mem = &Bar::num_;
+
+ return f_mem(bar1) + // Set break point at this line.
+ f1(acc,acc) + // Source main invoking f1
+ f2(acc) + // Set break point at this line.
+ f3(acc+1,acc+2) + // Set break point at this line.
+ f4() + // Set break point at this line.
+ f5(bar1, 10); // Set break point at this line.
+}
diff --git a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
index 42c372489c63..d11004e66d0a 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/stl/TestSTL.py
@@ -26,6 +26,7 @@ class STLTestCase(TestBase):
self.line = line_number(
self.source, '// Set break point at this line.')
+ @skipIf
@expectedFailureAll(bugnumber="llvm.org/PR36713")
def test(self):
"""Test some expressions involving STL data types."""
diff --git a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py
index 054bc93c3189..8f2ab56488f7 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/template/TestTemplateArgs.py
@@ -47,7 +47,6 @@ class TemplateArgsTestCase(TestBase):
# Get frame for current thread
return thread.GetSelectedFrame()
- @expectedFailureAll(oslist=["windows"])
def test_integer_args(self):
frame = self.prepareProcess()
@@ -111,11 +110,9 @@ class TemplateArgsTestCase(TestBase):
self.assertTrue(f4.GetType().GetName() == 'int')
self.assertTrue(f4.GetValue() == '42')
-
# Gcc does not generate the necessary DWARF attribute for enum template
# parameters.
@expectedFailureAll(bugnumber="llvm.org/pr28354", compiler="gcc")
- @expectedFailureAll(oslist=["windows"])
def test_enum_args(self):
frame = self.prepareProcess()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py
index 94d52e368e8c..7fa3f95ae9a7 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/TestCppTypeLookup.py
@@ -52,23 +52,23 @@ class TestCppTypeLookup(TestBase):
self.assertTrue(expr_result.GetError().Fail(),
"'namespace_only' exists in namespace only")
- # Make sure we can find the correct type in a namespace "a"
- expr_result = frame.EvaluateExpression("*((a::namespace_only *)&i)")
+ # Make sure we can find the correct type in a namespace "nsp_a"
+ expr_result = frame.EvaluateExpression("*((nsp_a::namespace_only *)&i)")
self.check_value(expr_result, "a", 123)
- # Make sure we can find the correct type in a namespace "b"
- expr_result = frame.EvaluateExpression("*((b::namespace_only *)&i)")
+ # Make sure we can find the correct type in a namespace "nsp_b"
+ expr_result = frame.EvaluateExpression("*((nsp_b::namespace_only *)&i)")
self.check_value(expr_result, "b", 123)
# Make sure we can find the correct type in the root namespace
expr_result = frame.EvaluateExpression("*((namespace_and_file *)&i)")
self.check_value(expr_result, "ff", 123)
- # Make sure we can find the correct type in a namespace "a"
+ # Make sure we can find the correct type in a namespace "nsp_a"
expr_result = frame.EvaluateExpression(
- "*((a::namespace_and_file *)&i)")
+ "*((nsp_a::namespace_and_file *)&i)")
self.check_value(expr_result, "aa", 123)
- # Make sure we can find the correct type in a namespace "b"
+ # Make sure we can find the correct type in a namespace "nsp_b"
expr_result = frame.EvaluateExpression(
- "*((b::namespace_and_file *)&i)")
+ "*((nsp_b::namespace_and_file *)&i)")
self.check_value(expr_result, "bb", 123)
# Make sure we don't accidentally accept structures that exist only
@@ -84,11 +84,11 @@ class TestCppTypeLookup(TestBase):
expr_result = frame.EvaluateExpression(
"*((contains_type::in_contains_type *)&i)")
self.check_value(expr_result, "fff", 123)
- # Make sure we can find the correct type in a namespace "a"
+ # Make sure we can find the correct type in a namespace "nsp_a"
expr_result = frame.EvaluateExpression(
- "*((a::contains_type::in_contains_type *)&i)")
+ "*((nsp_a::contains_type::in_contains_type *)&i)")
self.check_value(expr_result, "aaa", 123)
- # Make sure we can find the correct type in a namespace "b"
+ # Make sure we can find the correct type in a namespace "nsp_b"
expr_result = frame.EvaluateExpression(
- "*((b::contains_type::in_contains_type *)&i)")
+ "*((nsp_b::contains_type::in_contains_type *)&i)")
self.check_value(expr_result, "bbb", 123)
diff --git a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
index b244e80962c8..ae44bfa7c7d5 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
+++ b/packages/Python/lldbsuite/test/lang/cpp/type_lookup/main.cpp
@@ -11,7 +11,7 @@
// levels in the code and test that we can properly locate these types with
// a varienty of different expressions.
-namespace a {
+namespace nsp_a {
struct namespace_only {
int a;
};
@@ -24,7 +24,7 @@ namespace a {
};
};
};
-namespace b {
+namespace nsp_b {
struct namespace_only {
int b;
};
@@ -50,12 +50,12 @@ struct contains_type {
int main (int argc, char const *argv[]) {
- a::namespace_only a_namespace_only = { 1 };
- a::namespace_and_file a_namespace_and_file = { 2 };
- a::contains_type::in_contains_type a_in_contains_type = { 3 };
- b::namespace_only b_namespace_only = { 11 };
- b::namespace_and_file b_namespace_and_file = { 22 };
- b::contains_type::in_contains_type b_in_contains_type = { 33 };
+ nsp_a::namespace_only a_namespace_only = { 1 };
+ nsp_a::namespace_and_file a_namespace_and_file = { 2 };
+ nsp_a::contains_type::in_contains_type a_in_contains_type = { 3 };
+ nsp_b::namespace_only b_namespace_only = { 11 };
+ nsp_b::namespace_and_file b_namespace_and_file = { 22 };
+ nsp_b::contains_type::in_contains_type b_in_contains_type = { 33 };
namespace_and_file file_namespace_and_file = { 44 };
contains_type::in_contains_type file_in_contains_type = { 55 };
int i = 123; // Provide an integer that can be used for casting
diff --git a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py
index 216f86064dca..1a50c9dfc69f 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/unicode-literals/TestUnicodeLiterals.py
@@ -31,25 +31,16 @@ class UnicodeLiteralsTestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_expr1(self):
"""Test that the expression parser returns proper Unicode strings."""
self.build()
self.rdar12991846(expr=1)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_expr2(self):
"""Test that the expression parser returns proper Unicode strings."""
self.build()
self.rdar12991846(expr=2)
- @expectedFailureAll(
- oslist=["windows"],
- bugnumber="llvm.org/pr24489: Name lookup not working correctly on Windows")
def test_expr3(self):
"""Test that the expression parser returns proper Unicode strings."""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py
index b3fe9c40c198..365eb829ba64 100644
--- a/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py
+++ b/packages/Python/lldbsuite/test/lang/cpp/virtual/TestVirtual.py
@@ -36,6 +36,7 @@ class CppVirtualMadness(TestBase):
@expectedFailureAll(
compiler="icc",
bugnumber="llvm.org/pr16808 lldb does not call the correct virtual function with icc.")
+ @skipIfWindows # This test will hang on windows llvm.org/pr21753
def test_virtual_madness(self):
"""Test that expression works correctly with virtual inheritance as well as virtual function."""
self.build()
diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py b/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py
deleted file mode 100644
index 963e0676100d..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/expressions/TestExpressions.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""Test the go expression parser/interpreter."""
-
-import os
-import time
-import unittest2
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestGoUserExpression(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- @add_test_categories(['pyapi'])
- @skipIfRemote # Not remote test suit ready
- @skipIfFreeBSD # Test hanging on FreeBSD - llvm.org/pr37194
- @skipUnlessGoInstalled
- def test_with_dsym_and_python_api(self):
- """Test GoASTUserExpress."""
- self.buildGo()
- self.launchProcess()
- self.go_expressions()
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers to break inside main().
- self.main_source = "main.go"
- self.break_line = line_number(
- self.main_source, '// Set breakpoint here.')
-
- def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin):
- tl = self.target().FindTypes(name)
- self.assertEqual(1, len(tl))
- t = list(tl)[0]
- self.assertEqual(name, t.name)
- self.assertEqual(typeclass, t.type)
- if size > 0:
- self.assertEqual(size, t.size)
-
- def launchProcess(self):
- exe = self.getBuildArtifact("a.out")
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- bpt = target.BreakpointCreateByLocation(
- self.main_source, self.break_line)
- self.assertTrue(bpt, VALID_BREAKPOINT)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # The stop reason of the thread should be breakpoint.
- thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt)
-
- # Make sure we stopped at the first breakpoint.
- self.assertTrue(
- len(thread_list) != 0,
- "No thread stopped at our breakpoint.")
- self.assertTrue(len(thread_list) == 1,
- "More than one thread stopped at our breakpoint.")
-
- frame = thread_list[0].GetFrameAtIndex(0)
- self.assertTrue(frame, "Got a valid frame 0 frame.")
-
- def go_expressions(self):
- frame = self.frame()
- v = frame.EvaluateExpression("1")
- self.assertEqual(1, v.GetValueAsSigned())
- x = frame.EvaluateExpression("x")
- self.assertEqual(22, x.GetValueAsSigned())
-
- a = frame.EvaluateExpression("a")
- self.assertEqual(3, a.GetNumChildren())
- a0 = a.GetChildAtIndex(0)
- self.assertEqual(8, a0.GetValueAsSigned())
-
- # Array indexing
- a0 = frame.EvaluateExpression("a[0]")
- self.assertEqual(8, a0.GetValueAsSigned())
-
- # Slice indexing
- b1 = frame.EvaluateExpression("b[1]")
- self.assertEqual(9, b1.GetValueAsSigned())
-
- # Test global in this package
- g = frame.EvaluateExpression("myGlobal")
- self.assertEqual(17, g.GetValueAsSigned(), str(g))
-
- # Global with package name
- g = frame.EvaluateExpression("main.myGlobal")
- self.assertEqual(17, g.GetValueAsSigned(), str(g))
-
- # Global with quoted package name
- g = frame.EvaluateExpression('"main".myGlobal')
- self.assertEqual(17, g.GetValueAsSigned(), str(g))
-
- # Casting with package local type
- s = frame.EvaluateExpression("*(*myStruct)(i.data)")
- sb = s.GetChildMemberWithName("a")
- self.assertEqual(2, sb.GetValueAsSigned())
-
- # casting with explicit package
- s = frame.EvaluateExpression("*(*main.myStruct)(i.data)")
- sb = s.GetChildMemberWithName("a")
- self.assertEqual(2, sb.GetValueAsSigned())
-
- # Casting quoted package
- s = frame.EvaluateExpression('*(*"main".myStruct)(i.data)')
- sb = s.GetChildMemberWithName("b")
- self.assertEqual(-1, sb.GetValueAsSigned())
-
-if __name__ == '__main__':
- import atexit
- lldb.SBDebugger.Initialize()
- atexit.register(lambda: lldb.SBDebugger.Terminate())
- unittest2.main()
diff --git a/packages/Python/lldbsuite/test/lang/go/expressions/main.go b/packages/Python/lldbsuite/test/lang/go/expressions/main.go
deleted file mode 100644
index c8b97fe07d7d..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/expressions/main.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package main
-
-import "fmt"
-
-type myStruct struct {
- a, b int
-}
-
-var myGlobal = 17
-
-func myFunc(i interface{}) {
- a := [...]int{8, 9, 10}
- b := a[:]
- x := 22
- fmt.Println(a, b, x, i, myGlobal) // Set breakpoint here.
-}
-
-func main() {
- s := myStruct {2, -1}
- myFunc(s)
-} \ No newline at end of file
diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py b/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py
deleted file mode 100644
index b31ac35be46c..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/formatters/TestGoFormatters.py
+++ /dev/null
@@ -1,76 +0,0 @@
-"""Test the Go Data Formatter Plugin."""
-
-import os
-import time
-import unittest2
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestGoLanguage(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure
- @skipIfRemote # Not remote test suite ready
- @no_debug_info_test
- @skipUnlessGoInstalled
- def test_go_formatter_plugin(self):
- """Test go data formatters."""
- self.buildGo()
- self.launchProcess()
- self.check_formatters()
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers to break inside main().
- self.main_source = "main.go"
- self.break_line = line_number(self.main_source, '// stop here')
-
- def launchProcess(self):
- exe = self.getBuildArtifact("a.out")
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- self.bpt = target.BreakpointCreateByLocation(
- self.main_source, self.break_line)
- self.assertTrue(self.bpt, VALID_BREAKPOINT)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # The stop reason of the thread should be breakpoint.
- thread_list = lldbutil.get_threads_stopped_at_breakpoint(
- process, self.bpt)
-
- # Make sure we stopped at the first breakpoint.
- self.assertTrue(
- len(thread_list) != 0,
- "No thread stopped at our breakpoint.")
- self.assertTrue(len(thread_list) == 1,
- "More than one thread stopped at our breakpoint.")
-
- frame = thread_list[0].GetFrameAtIndex(0)
- self.assertTrue(frame, "Got a valid frame 0 frame.")
-
- def check_formatters(self):
- a = self.frame().FindVariable('a')
- self.assertEqual('(string) a = "my string"', str(a))
- b = self.frame().FindVariable('b')
- self.assertEqual(
- "([]int) b = (len 2, cap 7) {\n [0] = 0\n [1] = 0\n}",
- str(b))
-
-
-if __name__ == '__main__':
- import atexit
- lldb.SBDebugger.Initialize()
- atexit.register(lambda: lldb.SBDebugger.Terminate())
- unittest2.main()
diff --git a/packages/Python/lldbsuite/test/lang/go/formatters/main.go b/packages/Python/lldbsuite/test/lang/go/formatters/main.go
deleted file mode 100644
index 7956ad66bcb4..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/formatters/main.go
+++ /dev/null
@@ -1,9 +0,0 @@
-package main
-
-import "fmt"
-
-func main() {
- a := "my string"
- b := make([]int, 2, 7)
- fmt.Println(a, b) // stop here
-} \ No newline at end of file
diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py b/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py
deleted file mode 100644
index 027fb3adc0cf..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/goroutines/TestGoroutines.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"""Test the Go OS Plugin."""
-
-from __future__ import print_function
-
-
-import os
-import time
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestGoASTContext(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- @add_test_categories(['pyapi'])
- @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure
- @skipIfRemote # Not remote test suite ready
- @no_debug_info_test
- @skipUnlessGoInstalled
- def test_goroutine_plugin(self):
- """Test goroutine as threads support."""
- self.buildGo()
- self.launchProcess()
- self.check_goroutines()
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers to break inside main().
- self.main_source = "main.go"
- self.break_line1 = line_number(self.main_source, '// stop1')
- self.break_line2 = line_number(self.main_source, '// stop2')
- self.break_line3 = line_number(self.main_source, '// stop3')
-
- def launchProcess(self):
- exe = self.getBuildArtifact("a.out")
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- self.bpt1 = target.BreakpointCreateByLocation(
- self.main_source, self.break_line1)
- self.assertTrue(self.bpt1, VALID_BREAKPOINT)
- self.bpt2 = target.BreakpointCreateByLocation(
- self.main_source, self.break_line2)
- self.assertTrue(self.bpt2, VALID_BREAKPOINT)
- self.bpt3 = target.BreakpointCreateByLocation(
- self.main_source, self.break_line3)
- self.assertTrue(self.bpt3, VALID_BREAKPOINT)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # The stop reason of the thread should be breakpoint.
- thread_list = lldbutil.get_threads_stopped_at_breakpoint(
- process, self.bpt1)
-
- # Make sure we stopped at the first breakpoint.
- self.assertTrue(
- len(thread_list) != 0,
- "No thread stopped at our breakpoint.")
- self.assertTrue(len(thread_list) == 1,
- "More than one thread stopped at our breakpoint.")
-
- frame = thread_list[0].GetFrameAtIndex(0)
- self.assertTrue(frame, "Got a valid frame 0 frame.")
-
- def check_goroutines(self):
- self.assertLess(len(self.process().threads), 20)
- self.process().Continue()
-
- # Make sure we stopped at the 2nd breakpoint
- thread_list = lldbutil.get_threads_stopped_at_breakpoint(
- self.process(), self.bpt2)
- self.assertTrue(
- len(thread_list) != 0,
- "No thread stopped at our breakpoint.")
- self.assertTrue(len(thread_list) == 1,
- "More than one thread stopped at our breakpoint.")
-
- # There's (at least) 21 goroutines.
- self.assertGreater(len(self.process().threads), 20)
- # self.dbg.HandleCommand("log enable lldb os")
-
- # Now test that stepping works if the memory thread moves to a
- # different backing thread.
- for i in list(range(11)):
- self.thread().StepOver()
- self.assertEqual(
- lldb.eStopReasonPlanComplete,
- self.thread().GetStopReason(),
- self.thread().GetStopDescription(100))
-
- # Disable the plugin and make sure the goroutines disappear
- self.dbg.HandleCommand(
- "settings set plugin.os.goroutines.enable false")
- self.thread().StepInstruction(False)
- self.assertLess(len(self.process().threads), 20)
diff --git a/packages/Python/lldbsuite/test/lang/go/goroutines/main.go b/packages/Python/lldbsuite/test/lang/go/goroutines/main.go
deleted file mode 100644
index bb44f7b8b716..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/goroutines/main.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package main
-
-import (
- "fmt"
- "runtime"
-)
-
-type philosopher struct {
- i int
- forks [2]chan bool
- eating chan int
- done chan struct{}
-}
-
-func (p philosopher) run() {
- for {
- select {
- case <-p.done:
- return
- case <-p.forks[0]:
- p.eat()
- }
- }
-}
-
-func (p philosopher) eat() {
- select {
- case <-p.done:
- return
- case <-p.forks[1]:
- p.eating <- p.i
- p.forks[0] <- true
- p.forks[1] <- true
- runtime.Gosched()
- }
-}
-
-func startPhilosophers(n int) (chan struct{}, chan int) {
- philosophers := make([]*philosopher, n)
- chans := make([]chan bool, n)
- for i := range chans {
- chans[i] = make(chan bool, 1)
- chans[i] <- true
- }
- eating := make(chan int, n)
- done := make(chan struct{})
- for i := range philosophers {
- var min, max int
- if i == n - 1 {
- min = 0
- max = i
- } else {
- min = i
- max = i + 1
- }
- philosophers[i] = &philosopher{i: i, forks: [2]chan bool{chans[min], chans[max]}, eating: eating, done: done}
- go philosophers[i].run()
- }
- return done, eating
-}
-
-func wait(c chan int) {
- fmt.Println(<- c)
- runtime.Gosched()
-}
-
-func main() {
- // Restrict go to 1 real thread so we can be sure we're seeing goroutines
- // and not threads.
- runtime.GOMAXPROCS(1)
- // Create a bunch of goroutines
- done, eating := startPhilosophers(20) // stop1
- // Now turn up the number of threads so this goroutine is likely to get
- // scheduled on a different thread.
- runtime.GOMAXPROCS(runtime.NumCPU()) // stop2
- // Now let things run. Hopefully we'll bounce around
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- wait(eating)
- close(done)
- fmt.Println("done") // stop3
-}
diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime b/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime
deleted file mode 100644
index b06aa656aaa3..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/runtime/TestGoLanguageRuntime
+++ /dev/null
@@ -1,80 +0,0 @@
-"""Test the go dynamic type handling."""
-
-import os, time
-import unittest2
-import lldb
-import lldbutil
-from lldbtest import *
-
-class TestGoLanguageRuntime(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- @python_api_test
- @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr24895')
- @skipIfRemote # Not remote test suite ready
- @skipUnlessGoInstalled
- def test_with_dsym_and_python_api(self):
- """Test GoASTContext dwarf parsing."""
- self.buildGo()
- self.launchProcess()
- self.go_interface_types()
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers to break inside main().
- self.main_source = "main.go"
- self.break_line1 = line_number(self.main_source, '// Set breakpoint 1')
- self.break_line2 = line_number(self.main_source, '// Set breakpoint 2')
-
-
- def launchProcess(self):
- exe = self.getBuildArtifact("a.out")
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- bpt1 = target.BreakpointCreateByLocation(self.main_source, self.break_line1)
- self.assertTrue(bpt1, VALID_BREAKPOINT)
- bpt2 = target.BreakpointCreateByLocation(self.main_source, self.break_line2)
- self.assertTrue(bpt2, VALID_BREAKPOINT)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple (None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # The stop reason of the thread should be breakpoint.
- thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, bpt1)
-
- # Make sure we stopped at the first breakpoint.
- self.assertTrue (len(thread_list) != 0, "No thread stopped at our breakpoint.")
- self.assertTrue (len(thread_list) == 1, "More than one thread stopped at our breakpoint.")
-
- frame = thread_list[0].GetFrameAtIndex(0)
- self.assertTrue (frame, "Got a valid frame 0 frame.")
-
- def go_interface_types(self):
- f = self.frame()
- v = f.FindVariable("a", lldb.eDynamicCanRunTarget)
- self.assertEqual("*int", v.GetType().name)
- self.assertEqual(1, v.Dereference().GetValueAsSigned())
- v = f.FindVariable("b", lldb.eDynamicCanRunTarget)
- self.assertEqual("*float64", v.GetType().name)
- err = lldb.SBError()
- self.assertEqual(2.0, v.Dereference().GetData().GetDouble(err, 0))
- v = f.FindVariable("c", lldb.eDynamicCanRunTarget)
- self.assertEqual("*main.SomeFooer", v.GetType().name)
- self.assertEqual(9, v.Dereference().GetChildAtIndex(0).GetValueAsSigned())
- v = f.FindVariable("d", lldb.eDynamicCanRunTarget)
- self.assertEqual("*main.AnotherFooer", v.GetType().name)
- self.assertEqual(-1, v.Dereference().GetChildAtIndex(0).GetValueAsSigned())
- self.assertEqual(-2, v.Dereference().GetChildAtIndex(1).GetValueAsSigned())
- self.assertEqual(-3, v.Dereference().GetChildAtIndex(2).GetValueAsSigned())
-
-if __name__ == '__main__':
- import atexit
- lldb.SBDebugger.Initialize()
- atexit.register(lambda: lldb.SBDebugger.Terminate())
- unittest2.main()
diff --git a/packages/Python/lldbsuite/test/lang/go/runtime/main.go b/packages/Python/lldbsuite/test/lang/go/runtime/main.go
deleted file mode 100644
index 227c8c377ed7..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/runtime/main.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package main
-
-import "fmt"
-
-type Fooer interface {
- Foo() int
-}
-
-type SomeFooer struct {
- val int
-}
-
-func (s SomeFooer) Foo() int {
- return s.val
-}
-
-type AnotherFooer struct {
- a, b, c int
-}
-
-func (s AnotherFooer) Foo() int {
- return s.a
-}
-
-
-func printEface(a, b, c, d interface{}) {
- fmt.Println(a, b, c, d) // Set breakpoint 1
-}
-
-func printIface(a, b Fooer) {
- fmt.Println(a, b) // Set breakpoint 2
-}
-func main() {
- sf := SomeFooer{9}
- af := AnotherFooer{-1, -2, -3}
- printEface(1,2.0, sf, af)
- printIface(sf, af)
-} \ No newline at end of file
diff --git a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py b/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py
deleted file mode 100644
index 8fb56b9577af..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/types/TestGoASTContext.py
+++ /dev/null
@@ -1,145 +0,0 @@
-"""Test the go DWARF type parsing."""
-
-from __future__ import print_function
-
-
-import os
-import time
-import lldb
-from lldbsuite.test.decorators import *
-from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
-
-class TestGoASTContext(TestBase):
-
- mydir = TestBase.compute_mydir(__file__)
-
- @add_test_categories(['pyapi'])
- @skipIfFreeBSD # llvm.org/pr24895 triggers assertion failure
- @skipIfRemote # Not remote test suit ready
- @no_debug_info_test
- @skipUnlessGoInstalled
- @expectedFailureAll(bugnumber="llvm.org/pr33643")
- def test_with_dsym_and_python_api(self):
- """Test GoASTContext dwarf parsing."""
- self.buildGo()
- self.launchProcess()
- self.go_builtin_types()
- self.check_main_vars()
-
- def setUp(self):
- # Call super's setUp().
- TestBase.setUp(self)
- # Find the line numbers to break inside main().
- self.main_source = "main.go"
- self.break_line = line_number(
- self.main_source, '// Set breakpoint here.')
-
- def check_builtin(self, name, size=0, typeclass=lldb.eTypeClassBuiltin):
- tl = self.target().FindTypes(name)
- self.assertEqual(1, len(tl))
- t = list(tl)[0]
- self.assertEqual(name, t.name)
- self.assertEqual(typeclass, t.type)
- if size > 0:
- self.assertEqual(size, t.size)
-
- def launchProcess(self):
- exe = self.getBuildArtifact("a.out")
-
- target = self.dbg.CreateTarget(exe)
- self.assertTrue(target, VALID_TARGET)
-
- bpt = target.BreakpointCreateByLocation(
- self.main_source, self.break_line)
- self.assertTrue(bpt, VALID_BREAKPOINT)
-
- # Now launch the process, and do not stop at entry point.
- process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
-
- self.assertTrue(process, PROCESS_IS_VALID)
-
- # The stop reason of the thread should be breakpoint.
- thread_list = lldbutil.get_threads_stopped_at_breakpoint(process, bpt)
-
- # Make sure we stopped at the first breakpoint.
- self.assertTrue(
- len(thread_list) != 0,
- "No thread stopped at our breakpoint.")
- self.assertTrue(len(thread_list) == 1,
- "More than one thread stopped at our breakpoint.")
-
- frame = thread_list[0].GetFrameAtIndex(0)
- self.assertTrue(frame, "Got a valid frame 0 frame.")
-
- def go_builtin_types(self):
- address_size = self.target().GetAddressByteSize()
- self.check_builtin('bool')
- self.check_builtin('uint8', 1)
- self.check_builtin('int8', 1)
- self.check_builtin('uint16', 2)
- self.check_builtin('int16', 2)
- self.check_builtin('uint32', 4)
- self.check_builtin('int32', 4)
- self.check_builtin('uint64', 8)
- self.check_builtin('int64', 8)
- self.check_builtin('uintptr', address_size)
- self.check_builtin('int', address_size)
- self.check_builtin('uint', address_size)
- self.check_builtin('float32', 4)
- self.check_builtin('float64', 8)
- self.check_builtin('complex64', 8, lldb.eTypeClassComplexFloat)
- self.check_builtin('complex128', 16, lldb.eTypeClassComplexFloat)
-
- def var(self, name):
- var = self.frame().FindVariable(name)
- self.assertTrue(var.IsValid(), "%s %s" % (VALID_VARIABLE, name))
- return var
-
- def check_main_vars(self):
- v = self.var('theBool')
- self.assertEqual('true', v.value)
-
- v = self.var('theInt')
- self.assertEqual('-7', v.value)
-
- v = self.var('theComplex')
- self.assertEqual('1 + 2i', v.value)
-
- v = self.var('thePointer')
- self.assertTrue(v.TypeIsPointerType())
- self.assertEqual('-10', v.Dereference().value)
- self.assertEqual(1, v.GetNumChildren())
- self.assertEqual('-10', v.GetChildAtIndex(0).value)
-
- # print()
- # print(os.getpid())
- # time.sleep(60)
- v = self.var('theStruct')
- if v.TypeIsPointerType():
- v = v.Dereference()
- self.assertEqual(2, v.GetNumChildren())
- self.assertEqual('7', v.GetChildAtIndex(0).value)
- self.assertEqual('7', v.GetChildMemberWithName('myInt').value)
- self.assertEqual(
- v.load_addr,
- v.GetChildAtIndex(1).GetValueAsUnsigned())
- self.assertEqual(v.load_addr, v.GetChildMemberWithName(
- 'myPointer').GetValueAsUnsigned())
-
- # Test accessing struct fields through pointers.
- v = v.GetChildMemberWithName('myPointer')
- self.assertTrue(v.TypeIsPointerType())
- self.assertEqual(2, v.GetNumChildren())
- self.assertEqual('7', v.GetChildAtIndex(0).value)
- c = v.GetChildMemberWithName('myPointer')
- self.assertTrue(c.TypeIsPointerType())
- self.assertEqual(2, c.GetNumChildren())
- self.assertEqual('7', c.GetChildAtIndex(0).value)
-
- v = self.var('theArray')
- self.assertEqual(5, v.GetNumChildren())
- for i in list(range(5)):
- self.assertEqual(str(i + 1), v.GetChildAtIndex(i).value)
diff --git a/packages/Python/lldbsuite/test/lang/go/types/main.go b/packages/Python/lldbsuite/test/lang/go/types/main.go
deleted file mode 100644
index c74650721d7d..000000000000
--- a/packages/Python/lldbsuite/test/lang/go/types/main.go
+++ /dev/null
@@ -1,47 +0,0 @@
-package main
-
-import "fmt"
-
-type Fooer interface {
- Foo() int
-}
-
-type SomeFooer struct {
- val int
-}
-
-func (s SomeFooer) Foo() int {
- return s.val
-}
-
-type mystruct struct {
- myInt int
- myPointer *mystruct
-}
-
-func main() {
- theBool := true
- theInt := -7
- theComplex := 1 + 2i
- pointee := -10
- thePointer := &pointee
- theStruct := &mystruct { myInt: 7}
- theStruct.myPointer = theStruct
- theArray := [5]byte{1, 2, 3, 4, 5}
- theSlice := theArray[1:2]
- theString := "abc"
-
- f := SomeFooer {9}
- var theEface interface{} = f
- var theFooer Fooer = f
-
- theChan := make(chan int)
- theMap := make(map[int]string)
- theMap[1] = "1"
-
- fmt.Println(theBool) // Set breakpoint here.
- // Reference all the variables so the compiler is happy.
- fmt.Println(theInt, theComplex, thePointer, theStruct.myInt)
- fmt.Println(theArray[0], theSlice[0], theString)
- fmt.Println(theEface, theFooer, theChan, theMap)
-} \ No newline at end of file
diff --git a/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py b/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py
index 2ba57e61349f..a69e8a7aa1f9 100644
--- a/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py
+++ b/packages/Python/lldbsuite/test/lang/mixed/TestMixedLanguages.py
@@ -35,7 +35,7 @@ class MixedLanguagesTestCase(TestBase):
self.format_string = m.group(1)
# Change the default format to print the language.
- format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, lang=${language}}\n"
+ format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\`${function.name}{${function.pc-offset}}}{, lang=${language}}\n"
self.runCmd("settings set frame-format %s" % format_string)
self.expect("settings show frame-format", SETTING_MSG("frame-format"),
substrs=[format_string])
diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile b/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile
new file mode 100644
index 000000000000..261658b10ae8
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/Makefile
@@ -0,0 +1,9 @@
+LEVEL = ../../../make
+
+OBJCXX_SOURCES := main.mm
+
+CFLAGS_EXTRAS += -w
+
+include $(LEVEL)/Makefile.rules
+
+LDFLAGS += -framework Foundation
diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py b/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py
new file mode 100644
index 000000000000..92b32504cf20
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/TestObjCExceptions.py
@@ -0,0 +1,205 @@
+# encoding: utf-8
+"""
+Test lldb Obj-C exception support.
+"""
+
+from __future__ import print_function
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class ObjCExceptionsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipUnlessDarwin
+ def test_objc_exceptions_at_throw(self):
+ self.build()
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ launch_info = lldb.SBLaunchInfo(["a.out", "0"])
+ lldbutil.run_to_name_breakpoint(self, "objc_exception_throw", launch_info=launch_info)
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
+
+ self.expect('thread exception', substrs=[
+ '(NSException *) exception = ',
+ 'name: "ThrownException" - reason: "SomeReason"',
+ ])
+
+ target = self.dbg.GetSelectedTarget()
+ thread = target.GetProcess().GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ opts = lldb.SBVariablesOptions()
+ opts.SetIncludeRecognizedArguments(True)
+ variables = frame.GetVariables(opts)
+
+ self.assertEqual(variables.GetSize(), 1)
+ self.assertEqual(variables.GetValueAtIndex(0).name, "exception")
+
+ lldbutil.run_to_source_breakpoint(self, "// Set break point at this line.", lldb.SBFileSpec("main.mm"), launch_info=launch_info)
+
+ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
+ substrs=['stopped', 'stop reason = breakpoint'])
+
+ target = self.dbg.GetSelectedTarget()
+ thread = target.GetProcess().GetSelectedThread()
+ frame = thread.GetSelectedFrame()
+
+ # No exception being currently thrown/caught at this point
+ self.assertFalse(thread.GetCurrentException().IsValid())
+ self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid())
+
+ self.expect(
+ 'frame variable e1',
+ substrs=[
+ '(NSException *) e1 = ',
+ 'name: "ExceptionName" - reason: "SomeReason"'
+ ])
+
+ self.expect(
+ 'frame variable --dynamic-type no-run-target *e1',
+ substrs=[
+ '(NSException) *e1 = ',
+ 'name = ', '"ExceptionName"',
+ 'reason = ', '"SomeReason"',
+ 'userInfo = ', '1 key/value pair',
+ 'reserved = ', 'nil',
+ ])
+
+ e1 = frame.FindVariable("e1")
+ self.assertTrue(e1)
+ self.assertEqual(e1.type.name, "NSException *")
+ self.assertEqual(e1.GetSummary(), 'name: "ExceptionName" - reason: "SomeReason"')
+ self.assertEqual(e1.GetChildMemberWithName("name").description, "ExceptionName")
+ self.assertEqual(e1.GetChildMemberWithName("reason").description, "SomeReason")
+ userInfo = e1.GetChildMemberWithName("userInfo").dynamic
+ self.assertEqual(userInfo.summary, "1 key/value pair")
+ self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key")
+ self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value")
+ self.assertEqual(e1.GetChildMemberWithName("reserved").description, "<nil>")
+
+ self.expect(
+ 'frame variable e2',
+ substrs=[
+ '(NSException *) e2 = ',
+ 'name: "ThrownException" - reason: "SomeReason"'
+ ])
+
+ self.expect(
+ 'frame variable --dynamic-type no-run-target *e2',
+ substrs=[
+ '(NSException) *e2 = ',
+ 'name = ', '"ThrownException"',
+ 'reason = ', '"SomeReason"',
+ 'userInfo = ', '1 key/value pair',
+ 'reserved = ',
+ ])
+
+ e2 = frame.FindVariable("e2")
+ self.assertTrue(e2)
+ self.assertEqual(e2.type.name, "NSException *")
+ self.assertEqual(e2.GetSummary(), 'name: "ThrownException" - reason: "SomeReason"')
+ self.assertEqual(e2.GetChildMemberWithName("name").description, "ThrownException")
+ self.assertEqual(e2.GetChildMemberWithName("reason").description, "SomeReason")
+ userInfo = e2.GetChildMemberWithName("userInfo").dynamic
+ self.assertEqual(userInfo.summary, "1 key/value pair")
+ self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(0).description, "some_key")
+ self.assertEqual(userInfo.GetChildAtIndex(0).GetChildAtIndex(1).description, "some_value")
+ reserved = e2.GetChildMemberWithName("reserved").dynamic
+ self.assertGreater(reserved.num_children, 0)
+ callStackReturnAddresses = [reserved.GetChildAtIndex(i).GetChildAtIndex(1) for i in range(0, reserved.GetNumChildren())
+ if reserved.GetChildAtIndex(i).GetChildAtIndex(0).description == "callStackReturnAddresses"][0].dynamic
+ children = [callStackReturnAddresses.GetChildAtIndex(i) for i in range(0, callStackReturnAddresses.num_children)]
+
+ pcs = [i.unsigned for i in children]
+ names = [target.ResolveSymbolContextForAddress(lldb.SBAddress(pc, target), lldb.eSymbolContextSymbol).GetSymbol().name for pc in pcs]
+ for n in ["objc_exception_throw", "foo(int)", "main"]:
+ self.assertTrue(n in names, "%s is in the exception backtrace (%s)" % (n, names))
+
+ @skipUnlessDarwin
+ def test_objc_exceptions_at_abort(self):
+ self.build()
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ self.runCmd("run 0")
+
+ # We should be stopped at pthread_kill because of an unhandled exception
+ self.expect("thread list",
+ substrs=['stopped', 'stop reason = signal SIGABRT'])
+
+ self.expect('thread exception', substrs=[
+ '(NSException *) exception = ',
+ 'name: "ThrownException" - reason: "SomeReason"',
+ 'libobjc.A.dylib`objc_exception_throw',
+ 'a.out`foo', 'at main.mm:25',
+ 'a.out`rethrow', 'at main.mm:36',
+ 'a.out`main',
+ ])
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+
+ # There is an exception being currently processed at this point
+ self.assertTrue(thread.GetCurrentException().IsValid())
+ self.assertTrue(thread.GetCurrentExceptionBacktrace().IsValid())
+
+ history_thread = thread.GetCurrentExceptionBacktrace()
+ self.assertGreaterEqual(history_thread.num_frames, 4)
+ for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]:
+ self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1)
+
+ self.runCmd("kill")
+
+ self.runCmd("run 1")
+ # We should be stopped at pthread_kill because of an unhandled exception
+ self.expect("thread list",
+ substrs=['stopped', 'stop reason = signal SIGABRT'])
+
+ self.expect('thread exception', substrs=[
+ '(MyCustomException *) exception = ',
+ 'libobjc.A.dylib`objc_exception_throw',
+ 'a.out`foo', 'at main.mm:27',
+ 'a.out`rethrow', 'at main.mm:36',
+ 'a.out`main',
+ ])
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+
+ history_thread = thread.GetCurrentExceptionBacktrace()
+ self.assertGreaterEqual(history_thread.num_frames, 4)
+ for n in ["objc_exception_throw", "foo(int)", "rethrow(int)", "main"]:
+ self.assertEqual(len([f for f in history_thread.frames if f.GetFunctionName() == n]), 1)
+
+ @skipUnlessDarwin
+ def test_cxx_exceptions_at_abort(self):
+ self.build()
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+ self.assertTrue(target, VALID_TARGET)
+
+ self.runCmd("run 2")
+
+ # We should be stopped at pthread_kill because of an unhandled exception
+ self.expect("thread list",
+ substrs=['stopped', 'stop reason = signal SIGABRT'])
+
+ self.expect('thread exception', substrs=[])
+
+ process = self.dbg.GetSelectedTarget().process
+ thread = process.GetSelectedThread()
+
+ # C++ exceptions are not exposed in the API (yet).
+ self.assertFalse(thread.GetCurrentException().IsValid())
+ self.assertFalse(thread.GetCurrentExceptionBacktrace().IsValid())
diff --git a/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm b/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm
new file mode 100644
index 000000000000..5683882486d8
--- /dev/null
+++ b/packages/Python/lldbsuite/test/lang/objc/exceptions/main.mm
@@ -0,0 +1,63 @@
+//===-- main.m ------------------------------------------------*- ObjC -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#import <Foundation/Foundation.h>
+
+#import <exception>
+#import <stdexcept>
+
+@interface MyCustomException: NSException
+@end
+@implementation MyCustomException
+@end
+
+void foo(int n)
+{
+ NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"some_value", @"some_key", nil];
+ switch (n) {
+ case 0:
+ @throw [[NSException alloc] initWithName:@"ThrownException" reason:@"SomeReason" userInfo:info];
+ case 1:
+ @throw [[MyCustomException alloc] initWithName:@"ThrownException" reason:@"SomeReason" userInfo:info];
+ case 2:
+ throw std::runtime_error("C++ exception");
+ }
+}
+
+void rethrow(int n)
+{
+ @try {
+ foo(n);
+ } @catch(NSException *e) {
+ @throw;
+ }
+}
+
+int main(int argc, const char * argv[])
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:@"some_value", @"some_key", nil];
+ NSException *e1 = [[NSException alloc] initWithName:@"ExceptionName" reason:@"SomeReason" userInfo:info];
+ NSException *e2;
+
+ @try {
+ foo(atoi(argv[1]));
+ } @catch(NSException *e) {
+ e2 = e;
+ }
+
+ NSLog(@"1"); // Set break point at this line.
+
+ rethrow(atoi(argv[1]));
+
+ [pool drain];
+ return 0;
+}
+
diff --git a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
index 29d386253fb4..e9dbe6af864f 100644
--- a/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
+++ b/packages/Python/lldbsuite/test/lang/objc/modules-inline-functions/TestModulesInlineFunctions.py
@@ -23,8 +23,6 @@ class ModulesInlineFunctionsTestCase(TestBase):
def setUp(self):
# Call super's setUp().
TestBase.setUp(self)
- # Find the line number to break inside main().
- self.line = line_number('main.m', '// Set breakpoint here.')
@skipUnlessDarwin
@skipIf(macos_version=["<", "10.12"], debug_info=no_match(["gmodules"]))
@@ -34,19 +32,8 @@ class ModulesInlineFunctionsTestCase(TestBase):
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
# Break inside the foo function which takes a bar_ptr argument.
- lldbutil.run_break_set_by_file_and_line(
- self, "main.m", self.line, num_expected_locations=1, loc_exact=True)
-
- self.runCmd("run", RUN_SUCCEEDED)
-
- # The stop reason of the thread should be breakpoint.
- self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
- substrs=['stopped',
- 'stop reason = breakpoint'])
-
- # The breakpoint should have a hit count of 1.
- self.expect("breakpoint list -f", BREAKPOINT_HIT_ONCE,
- substrs=[' resolved, hit count = 1'])
+ lldbutil.run_to_source_breakpoint(
+ self, '// Set breakpoint here.', lldb.SBFileSpec('main.m'))
self.runCmd(
"settings set target.clang-module-search-paths \"" +
diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h
index 20a81faa1017..5ee6acb2425e 100644
--- a/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h
+++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Bar.h
@@ -9,4 +9,4 @@
- (NSString *)description;
-@end \ No newline at end of file
+@end
diff --git a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h
index 14ff9eed50fd..d58da600765a 100644
--- a/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h
+++ b/packages/Python/lldbsuite/test/lang/objc/real-definition/Foo.h
@@ -8,4 +8,4 @@
- (NSString *)description;
-@end \ No newline at end of file
+@end
diff --git a/packages/Python/lldbsuite/test/lldbinline.py b/packages/Python/lldbsuite/test/lldbinline.py
index bb925ef908f5..c01fef00fe44 100644
--- a/packages/Python/lldbsuite/test/lldbinline.py
+++ b/packages/Python/lldbsuite/test/lldbinline.py
@@ -195,7 +195,6 @@ def MakeInlineTest(__file, __globals, decorators=None):
# Derive the test name from the current file name
file_basename = os.path.basename(__file)
- InlineTest.mydir = TestBase.compute_mydir(__file)
test_name, _ = os.path.splitext(file_basename)
@@ -209,4 +208,5 @@ def MakeInlineTest(__file, __globals, decorators=None):
# Keep track of the original test filename so we report it
# correctly in test results.
test_class.test_filename = __file
+ test_class.mydir = TestBase.compute_mydir(__file)
return test_class
diff --git a/packages/Python/lldbsuite/test/lldbtest.py b/packages/Python/lldbsuite/test/lldbtest.py
index 1b6302ae96a6..161e8c61349d 100644
--- a/packages/Python/lldbsuite/test/lldbtest.py
+++ b/packages/Python/lldbsuite/test/lldbtest.py
@@ -72,8 +72,7 @@ from lldbsuite.support import encoded_file
from lldbsuite.support import funcutils
# See also dotest.parseOptionsAndInitTestdirs(), where the environment variables
-# LLDB_COMMAND_TRACE and LLDB_DO_CLEANUP are set from '-t' and '-r dir'
-# options.
+# LLDB_COMMAND_TRACE is set from '-t' option.
# By default, traceAlways is False.
if "LLDB_COMMAND_TRACE" in os.environ and os.environ[
@@ -740,6 +739,11 @@ class Base(unittest2.TestCase):
else:
self.lldbMiExec = None
+ if "LLDBVSCODE_EXEC" in os.environ:
+ self.lldbVSCodeExec = os.environ["LLDBVSCODE_EXEC"]
+ else:
+ self.lldbVSCodeExec = None
+
# If we spawn an lldb process for test (via pexpect), do not load the
# init file unless told otherwise.
if "NO_LLDBINIT" in os.environ and "NO" == os.environ["NO_LLDBINIT"]:
@@ -1215,12 +1219,15 @@ class Base(unittest2.TestCase):
if os.path.isfile(src):
dst = src.replace(self.log_basename, dst_log_basename)
if os.name == "nt" and os.path.isfile(dst):
- # On Windows, renaming a -> b will throw an exception if b exists. On non-Windows platforms
- # it silently replaces the destination. Ultimately this means that atomic renames are not
- # guaranteed to be possible on Windows, but we need this to work anyway, so just remove the
- # destination first if it already exists.
+ # On Windows, renaming a -> b will throw an exception if
+ # b exists. On non-Windows platforms it silently
+ # replaces the destination. Ultimately this means that
+ # atomic renames are not guaranteed to be possible on
+ # Windows, but we need this to work anyway, so just
+ # remove the destination first if it already exists.
remove_file(dst)
+ lldbutil.mkdir_p(os.path.dirname(dst))
os.rename(src, dst)
else:
# success! (and we don't want log files) delete log files
@@ -1302,18 +1309,6 @@ class Base(unittest2.TestCase):
version = m.group(1)
return version
- def getGoCompilerVersion(self):
- """ Returns a string that represents the go compiler version, or None if go is not found.
- """
- compiler = which("go")
- if compiler:
- version_output = system([[compiler, "version"]])[0]
- for line in version_output.split(os.linesep):
- m = re.search('go version (devel|go\\S+)', line)
- if m:
- return m.group(1)
- return None
-
def platformIsDarwin(self):
"""Returns true if the OS triple for the selected platform is any valid apple OS"""
return lldbplatformutil.platformIsDarwin()
@@ -1582,12 +1577,6 @@ class Base(unittest2.TestCase):
dictionary, testdir, testname):
raise Exception("Don't know how to build binary with gmodules")
- def buildGo(self):
- """Build the default go binary.
- """
- exe = self.getBuildArtifact("a.out")
- system([[which('go'), 'build -gcflags "-N -l" -o %s main.go' % exe]])
-
def signBinary(self, binary_path):
if sys.platform.startswith("darwin"):
codesign_cmd = "codesign --force --sign \"%s\" %s" % (
@@ -1875,18 +1864,16 @@ class TestBase(Base):
# decorators.
Base.setUp(self)
- if self.child:
- # Set the clang modules cache path.
- assert(self.getDebugInfo() == 'default')
- mod_cache = os.path.join(self.getBuildDir(), "module-cache")
- self.runCmd('settings set symbols.clang-modules-cache-path "%s"'
- % mod_cache)
-
- # Disable Spotlight lookup. The testsuite creates
- # different binaries with the same UUID, because they only
- # differ in the debug info, which is not being hashed.
- self.runCmd('settings set symbols.enable-external-lookup false')
+ # Set the clang modules cache path used by LLDB.
+ mod_cache = os.path.join(os.path.join(os.environ["LLDB_BUILD"],
+ "module-cache-lldb"))
+ self.runCmd('settings set symbols.clang-modules-cache-path "%s"'
+ % mod_cache)
+ # Disable Spotlight lookup. The testsuite creates
+ # different binaries with the same UUID, because they only
+ # differ in the debug info, which is not being hashed.
+ self.runCmd('settings set symbols.enable-external-lookup false')
if "LLDB_MAX_LAUNCH_COUNT" in os.environ:
self.maxLaunchCount = int(os.environ["LLDB_MAX_LAUNCH_COUNT"])
@@ -2074,8 +2061,17 @@ class TestBase(Base):
print("Command '" + cmd + "' failed!", file=sbuf)
if check:
+ output = ""
+ if self.res.GetOutput():
+ output += "\nCommand output:\n" + self.res.GetOutput()
+ if self.res.GetError():
+ output += "\nError output:\n" + self.res.GetError()
+ if msg:
+ msg += output
+ if cmd:
+ cmd += output
self.assertTrue(self.res.Succeeded(),
- msg if msg else CMD_MSG(cmd))
+ msg if (msg) else CMD_MSG(cmd))
def match(
self,
@@ -2134,6 +2130,126 @@ class TestBase(Base):
return match_object
+ def check_completion_with_desc(self, str_input, match_desc_pairs):
+ interp = self.dbg.GetCommandInterpreter()
+ match_strings = lldb.SBStringList()
+ description_strings = lldb.SBStringList()
+ num_matches = interp.HandleCompletionWithDescriptions(str_input, len(str_input), 0, -1, match_strings, description_strings)
+ self.assertEqual(len(description_strings), len(match_strings))
+
+ missing_pairs = []
+ for pair in match_desc_pairs:
+ found_pair = False
+ for i in range(num_matches + 1):
+ match_candidate = match_strings.GetStringAtIndex(i)
+ description_candidate = description_strings.GetStringAtIndex(i)
+ if match_candidate == pair[0] and description_candidate == pair[1]:
+ found_pair = True
+ break
+ if not found_pair:
+ missing_pairs.append(pair)
+
+ if len(missing_pairs):
+ error_msg = "Missing pairs:\n"
+ for pair in missing_pairs:
+ error_msg += " [" + pair[0] + ":" + pair[1] + "]\n"
+ error_msg += "Got the following " + str(num_matches) + " completions back:\n"
+ for i in range(num_matches + 1):
+ match_candidate = match_strings.GetStringAtIndex(i)
+ description_candidate = description_strings.GetStringAtIndex(i)
+ error_msg += "[" + match_candidate + ":" + description_candidate + "]\n"
+ self.assertEqual(0, len(missing_pairs), error_msg)
+
+ def complete_exactly(self, str_input, patterns):
+ self.complete_from_to(str_input, patterns, True)
+
+ def complete_from_to(self, str_input, patterns, turn_off_re_match=False):
+ """Test that the completion mechanism completes str_input to patterns,
+ where patterns could be a pattern-string or a list of pattern-strings"""
+ # Patterns should not be None in order to proceed.
+ self.assertFalse(patterns is None)
+ # And should be either a string or list of strings. Check for list type
+ # below, if not, make a list out of the singleton string. If patterns
+ # is not a string or not a list of strings, there'll be runtime errors
+ # later on.
+ if not isinstance(patterns, list):
+ patterns = [patterns]
+
+ interp = self.dbg.GetCommandInterpreter()
+ match_strings = lldb.SBStringList()
+ num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings)
+ common_match = match_strings.GetStringAtIndex(0)
+ if num_matches == 0:
+ compare_string = str_input
+ else:
+ if common_match != None and len(common_match) > 0:
+ compare_string = str_input + common_match
+ else:
+ compare_string = ""
+ for idx in range(1, num_matches+1):
+ compare_string += match_strings.GetStringAtIndex(idx) + "\n"
+
+ for p in patterns:
+ if turn_off_re_match:
+ self.expect(
+ compare_string, msg=COMPLETION_MSG(
+ str_input, p, match_strings), exe=False, substrs=[p])
+ else:
+ self.expect(
+ compare_string, msg=COMPLETION_MSG(
+ str_input, p, match_strings), exe=False, patterns=[p])
+
+ def filecheck(
+ self,
+ command,
+ check_file,
+ filecheck_options = ''):
+ # Run the command.
+ self.runCmd(
+ command,
+ msg="FileCheck'ing result of `{0}`".format(command))
+
+ # Get the error text if there was an error, and the regular text if not.
+ output = self.res.GetOutput() if self.res.Succeeded() \
+ else self.res.GetError()
+
+ # Assemble the absolute path to the check file. As a convenience for
+ # LLDB inline tests, assume that the check file is a relative path to
+ # a file within the inline test directory.
+ if check_file.endswith('.pyc'):
+ check_file = check_file[:-1]
+ check_file_abs = os.path.abspath(check_file)
+
+ # Run FileCheck.
+ filecheck_bin = configuration.get_filecheck_path()
+ if not filecheck_bin:
+ self.assertTrue(False, "No valid FileCheck executable specified")
+ filecheck_args = [filecheck_bin, check_file_abs]
+ if filecheck_options:
+ filecheck_args.append(filecheck_options)
+ subproc = Popen(filecheck_args, stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines = True)
+ cmd_stdout, cmd_stderr = subproc.communicate(input=output)
+ cmd_status = subproc.returncode
+
+ filecheck_cmd = " ".join(filecheck_args)
+ filecheck_trace = """
+--- FileCheck trace (code={0}) ---
+{1}
+
+FileCheck input:
+{2}
+
+FileCheck output:
+{3}
+{4}
+""".format(cmd_status, filecheck_cmd, output, cmd_stdout, cmd_stderr)
+
+ trace = cmd_status != 0 or traceAlways
+ with recording(self, trace) as sbuf:
+ print(filecheck_trace, file=sbuf)
+
+ self.assertTrue(cmd_status == 0)
+
def expect(
self,
str,
diff --git a/packages/Python/lldbsuite/test/lldbutil.py b/packages/Python/lldbsuite/test/lldbutil.py
index dc84383333ee..16950d7b5cdb 100644
--- a/packages/Python/lldbsuite/test/lldbutil.py
+++ b/packages/Python/lldbsuite/test/lldbutil.py
@@ -330,6 +330,20 @@ def sort_stopped_threads(process,
# Utility functions for setting breakpoints
# ==================================================
+def run_break_set_by_script(
+ test,
+ class_name,
+ extra_options=None,
+ num_expected_locations=1):
+ """Set a scripted breakpoint. Check that it got the right number of locations."""
+ test.assertTrue(class_name is not None, "Must pass in a class name.")
+ command = "breakpoint set -P " + class_name
+ if extra_options is not None:
+ command += " " + extra_options
+
+ break_results = run_break_set_command(test, command)
+ check_breakpoint_result(test, break_results, num_locations=num_expected_locations)
+ return get_bpno_from_match(break_results)
def run_break_set_by_file_and_line(
test,
@@ -511,7 +525,7 @@ def run_break_set_command(test, command):
patterns = [
r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>[0-9]+) locations\.$",
r"^Breakpoint (?P<bpno>[0-9]+): (?P<num_locations>no) locations \(pending\)\.",
- r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+), address = (?P<address>0x[0-9a-fA-F]+)$",
+ r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>[+\-]{0,1}[^+]+)( \+ (?P<offset>[0-9]+)){0,1}( \[inlined\] (?P<inline_symbol>.*)){0,1} at (?P<file>[^:]+):(?P<line_no>[0-9]+)(?P<column>(:[0-9]+)?), address = (?P<address>0x[0-9a-fA-F]+)$",
r"^Breakpoint (?P<bpno>[0-9]+): where = (?P<module>.*)`(?P<symbol>.*)( \+ (?P<offset>[0-9]+)){0,1}, address = (?P<address>0x[0-9a-fA-F]+)$"]
match_object = test.match(command, patterns)
break_results = match_object.groupdict()
@@ -722,6 +736,8 @@ def is_thread_crashed(test, thread):
elif test.getPlatform() == "linux":
return thread.GetStopReason() == lldb.eStopReasonSignal and thread.GetStopReasonDataAtIndex(
0) == thread.GetProcess().GetUnixSignals().GetSignalNumberFromName("SIGSEGV")
+ elif test.getPlatform() == "windows":
+ return "Exception 0xc0000005" in thread.GetStopDescription(100)
else:
return "invalid address" in thread.GetStopDescription(100)
@@ -737,7 +753,7 @@ def get_crashed_threads(test, process):
# Helper functions for run_to_{source,name}_breakpoint:
-def run_to_breakpoint_make_target(test, exe_name, in_cwd):
+def run_to_breakpoint_make_target(test, exe_name = "a.out", in_cwd = True):
if in_cwd:
exe = test.getBuildArtifact(exe_name)
@@ -746,7 +762,7 @@ def run_to_breakpoint_make_target(test, exe_name, in_cwd):
test.assertTrue(target, "Target: %s is not valid."%(exe_name))
return target
-def run_to_breakpoint_do_run(test, target, bkpt, launch_info):
+def run_to_breakpoint_do_run(test, target, bkpt, launch_info = None):
# Launch the process, and do not stop at the entry point.
if not launch_info:
@@ -819,9 +835,31 @@ def run_to_source_breakpoint(test, bkpt_pattern, source_spec,
breakpoint = target.BreakpointCreateBySourceRegex(
bkpt_pattern, source_spec, bkpt_module)
test.assertTrue(breakpoint.GetNumLocations() > 0,
- 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'%(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
+ 'No locations found for source breakpoint: "%s", file: "%s", dir: "%s"'
+ %(bkpt_pattern, source_spec.GetFilename(), source_spec.GetDirectory()))
return run_to_breakpoint_do_run(test, target, breakpoint, launch_info)
+def run_to_line_breakpoint(test, source_spec, line_number, column = 0,
+ launch_info = None, exe_name = "a.out",
+ bkpt_module = None,
+ in_cwd = True):
+ """Start up a target, using exe_name as the executable, and run it to
+ a breakpoint set by (source_spec, line_number(, column)).
+
+ The rest of the behavior is the same as run_to_name_breakpoint.
+ """
+
+ target = run_to_breakpoint_make_target(test, exe_name, in_cwd)
+ # Set the breakpoints
+ breakpoint = target.BreakpointCreateByLocation(
+ source_spec, line_number, column, 0, lldb.SBFileSpecList())
+ test.assertTrue(breakpoint.GetNumLocations() > 0,
+ 'No locations found for line breakpoint: "%s:%d(:%d)", dir: "%s"'
+ %(source_spec.GetFilename(), line_number, column,
+ source_spec.GetDirectory()))
+ return run_to_breakpoint_do_run(test, target, breakpoint, launch_info)
+
+
def continue_to_breakpoint(process, bkpt):
""" Continues the process, if it stops, returns the threads stopped at bkpt; otherwise, returns None"""
process.Continue()
diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/Makefile b/packages/Python/lldbsuite/test/macosx/function-starts/Makefile
new file mode 100644
index 000000000000..091876d51c35
--- /dev/null
+++ b/packages/Python/lldbsuite/test/macosx/function-starts/Makefile
@@ -0,0 +1,10 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+EXE := StripMe
+MAKE_DSYM := NO
+
+include $(LEVEL)/Makefile.rules
+
+main.o: main.cpp
+ $(CC) $(CFLAGS_NO_DEBUG) -c $< -o $@
diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py b/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py
new file mode 100644
index 000000000000..ae3b825f95cb
--- /dev/null
+++ b/packages/Python/lldbsuite/test/macosx/function-starts/TestFunctionStarts.py
@@ -0,0 +1,76 @@
+"""
+Test that we read the function starts section.
+"""
+
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+exe_name = "StripMe" # Must match Makefile
+
+class FunctionStartsTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipIfRemote
+ @skipUnlessDarwin
+ def test_function_starts_binary(self):
+ """Test that we make synthetic symbols when we have the binary."""
+ self.build()
+ self.do_function_starts(False)
+
+ @skipIfRemote
+ @skipUnlessDarwin
+ def test_function_starts_no_binary(self):
+ """Test that we make synthetic symbols when we don't have the binary"""
+ self.build()
+ self.do_function_starts(True)
+
+ def do_function_starts(self, in_memory):
+ """Run the binary, stop at our unstripped function,
+ make sure the caller has synthetic symbols"""
+
+ exe = self.getBuildArtifact(exe_name)
+ # Now strip the binary, but leave externals so we can break on dont_strip_me.
+ try:
+ fail_str = system([["strip", "-u", "-x", "-S", exe]])
+ except CalledProcessError as cmd_error:
+ self.fail("Strip failed: %d"%(cmd_error.returncode))
+
+ popen = self.spawnSubprocess(exe)
+ self.addTearDownHook(self.cleanupSubprocesses)
+ if in_memory:
+ remove_file(exe)
+
+ target = self.dbg.CreateTarget(None)
+ self.assertTrue(target.IsValid(), "Got a vaid empty target.")
+ error = lldb.SBError()
+ attach_info = lldb.SBAttachInfo()
+ attach_info.SetProcessID(popen.pid)
+ attach_info.SetIgnoreExisting(False)
+ process = target.Attach(attach_info, error)
+ self.assertTrue(error.Success(), "Didn't attach successfully to %d: %s"%(popen.pid, error.GetCString()))
+
+ bkpt = target.BreakpointCreateByName("dont_strip_me", exe)
+ self.assertTrue(bkpt.GetNumLocations() > 0, "Didn't set the dont_strip_me bkpt.")
+
+ threads = lldbutil.continue_to_breakpoint(process, bkpt)
+ self.assertEqual(len(threads), 1, "Didn't hit my breakpoint.")
+
+ # Our caller frame should have been stripped. Make sure we made a synthetic symbol
+ # for it:
+ thread = threads[0]
+ self.assertTrue(thread.num_frames > 1, "Couldn't backtrace.")
+ name = thread.frame[1].GetFunctionName()
+ self.assertEqual("___lldb_unnamed_symbol1$$StripMe", name, "Frame name not synthetic")
+
+
+
diff --git a/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp b/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp
new file mode 100644
index 000000000000..5a14506d6913
--- /dev/null
+++ b/packages/Python/lldbsuite/test/macosx/function-starts/main.cpp
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <fcntl.h>
+
+#include <chrono>
+#include <thread>
+
+extern void dont_strip_me()
+{
+ printf("I wasn't stripped\n");
+}
+
+static void *a_function()
+{
+ while (1)
+ {
+ std::this_thread::sleep_for(std::chrono::microseconds(100));
+ dont_strip_me();
+ }
+ return 0;
+}
+
+int main(int argc, char const *argv[])
+{
+ a_function();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py b/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py
new file mode 100644
index 000000000000..1bd5ec020dbe
--- /dev/null
+++ b/packages/Python/lldbsuite/test/macosx/load-kext/TestLoadKext.py
@@ -0,0 +1,38 @@
+"""
+Test loading of a kext binary.
+"""
+
+from __future__ import print_function
+
+import shutil
+import struct
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LoadKextTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ TestBase.setUp(self)
+ #super(LoadKextTestCase, self).setUp()
+ #self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+ def test_load_kext(self):
+ """Test that lldb can load a kext binary."""
+
+ # Create kext from YAML.
+ self.yaml2obj("mykext.yaml", self.getBuildArtifact("mykext"))
+
+ target = self.dbg.CreateTarget(self.getBuildArtifact("mykext"))
+
+ self.assertTrue(target.IsValid())
+
+ self.assertEqual(target.GetNumModules(), 1)
+ mod = target.GetModuleAtIndex(0)
+ self.assertEqual(mod.GetFileSpec().GetFilename(), "mykext")
diff --git a/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml b/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml
new file mode 100644
index 000000000000..ccf016304c84
--- /dev/null
+++ b/packages/Python/lldbsuite/test/macosx/load-kext/mykext.yaml
@@ -0,0 +1,222 @@
+--- !mach-o
+FileHeader:
+ magic: 0xFEEDFACF
+ cputype: 0x01000007
+ cpusubtype: 0x00000003
+ filetype: 0x0000000B
+ ncmds: 7
+ sizeofcmds: 520
+ flags: 0x00000085
+ reserved: 0x00000000
+LoadCommands:
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: __TEXT
+ vmaddr: 0
+ vmsize: 4096
+ fileoff: 0
+ filesize: 4096
+ maxprot: 7
+ initprot: 5
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __text
+ segname: __TEXT
+ addr: 0x0000000000000F60
+ size: 158
+ offset: 0x00000F60
+ align: 4
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x80000400
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_SEGMENT_64
+ cmdsize: 152
+ segname: __DATA
+ vmaddr: 4096
+ vmsize: 4096
+ fileoff: 4096
+ filesize: 4096
+ maxprot: 7
+ initprot: 3
+ nsects: 1
+ flags: 0
+ Sections:
+ - sectname: __data
+ segname: __DATA
+ addr: 0x0000000000001000
+ size: 220
+ offset: 0x00001000
+ align: 3
+ reloff: 0x00000000
+ nreloc: 0
+ flags: 0x00000000
+ reserved1: 0x00000000
+ reserved2: 0x00000000
+ reserved3: 0x00000000
+ - cmd: LC_SEGMENT_64
+ cmdsize: 72
+ segname: __LINKEDIT
+ vmaddr: 8192
+ vmsize: 4096
+ fileoff: 8192
+ filesize: 800
+ maxprot: 7
+ initprot: 1
+ nsects: 0
+ flags: 0
+ - cmd: LC_SYMTAB
+ cmdsize: 24
+ symoff: 8224
+ nsyms: 19
+ stroff: 8528
+ strsize: 464
+ - cmd: LC_DYSYMTAB
+ cmdsize: 80
+ ilocalsym: 0
+ nlocalsym: 16
+ iextdefsym: 16
+ nextdefsym: 3
+ iundefsym: 19
+ nundefsym: 0
+ tocoff: 0
+ ntoc: 0
+ modtaboff: 0
+ nmodtab: 0
+ extrefsymoff: 0
+ nextrefsyms: 0
+ indirectsymoff: 0
+ nindirectsyms: 0
+ extreloff: 0
+ nextrel: 0
+ locreloff: 8192
+ nlocrel: 4
+ - cmd: LC_UUID
+ cmdsize: 24
+ uuid: 17A97B33-09B7-3195-9408-DBD965D578A5
+ - cmd: LC_SOURCE_VERSION
+ cmdsize: 16
+ version: 0
+LinkEditData:
+ NameList:
+ - n_strx: 40
+ n_type: 0x64
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 141
+ n_type: 0x64
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 155
+ n_type: 0x66
+ n_sect: 3
+ n_desc: 1
+ n_value: 1543540349
+ - n_strx: 276
+ n_type: 0x20
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 287
+ n_type: 0x20
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 298
+ n_type: 0x20
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 309
+ n_type: 0x20
+ n_sect: 0
+ n_desc: 0
+ n_value: 0
+ - n_strx: 1
+ n_type: 0x64
+ n_sect: 1
+ n_desc: 0
+ n_value: 0
+ - n_strx: 325
+ n_type: 0x1E
+ n_sect: 1
+ n_desc: 0
+ n_value: 3992
+ - n_strx: 333
+ n_type: 0x1E
+ n_sect: 1
+ n_desc: 0
+ n_value: 4018
+ - n_strx: 361
+ n_type: 0x1E
+ n_sect: 1
+ n_desc: 0
+ n_value: 4035
+ - n_strx: 392
+ n_type: 0x1E
+ n_sect: 1
+ n_desc: 0
+ n_value: 4052
+ - n_strx: 417
+ n_type: 0x1E
+ n_sect: 1
+ n_desc: 0
+ n_value: 4068
+ - n_strx: 424
+ n_type: 0x1E
+ n_sect: 2
+ n_desc: 0
+ n_value: 4296
+ - n_strx: 435
+ n_type: 0x1E
+ n_sect: 2
+ n_desc: 0
+ n_value: 4304
+ - n_strx: 446
+ n_type: 0x1E
+ n_sect: 2
+ n_desc: 0
+ n_value: 4312
+ - n_strx: 2
+ n_type: 0x0F
+ n_sect: 2
+ n_desc: 0
+ n_value: 4096
+ - n_strx: 13
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 3936
+ - n_strx: 27
+ n_type: 0x0F
+ n_sect: 1
+ n_desc: 0
+ n_value: 3968
+ StringTable:
+ - ' '
+ - _kmod_info
+ - _mykext_start
+ - _mykext_stop
+ - /tmp/mykext/build/mykext/Build/Intermediates.noindex/mykext.build/Debug/mykext.build/DerivedSources/
+ - mykext_info.c
+ - /tmp/mykext/build/mykext/Build/Intermediates.noindex/mykext.build/Debug/mykext.build/Objects-normal/x86_64/mykext_info.o
+ - _kmod_info
+ - __realmain
+ - __antimain
+ - __kext_apple_cc
+ - __start
+ - _OSKextGetCurrentIdentifier
+ - _OSKextGetCurrentVersionString
+ - _OSKextGetCurrentLoadTag
+ - __stop
+ - __realmain
+ - __antimain
+ - __kext_apple_cc
+ - ''
+ - ''
+...
diff --git a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py
index 59b325f57984..287c1c1b87b3 100644
--- a/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py
+++ b/packages/Python/lldbsuite/test/macosx/nslog/TestDarwinNSLogOutput.py
@@ -95,7 +95,8 @@ class DarwinNSLogOutputTestCase(TestBase):
self.expect(re.compile(r"stop reason = breakpoint"))
def runCmd(self, cmd):
- self.child.sendline(cmd)
+ if self.child:
+ self.child.sendline(cmd)
def expect_prompt(self, exactly=True):
self.expect(self.child_prompt, exactly=exactly)
diff --git a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py
index ba58372ce5b7..cdc9606c377a 100644
--- a/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py
+++ b/packages/Python/lldbsuite/test/macosx/queues/TestQueues.py
@@ -18,10 +18,16 @@ class TestQueues(TestBase):
@skipUnlessDarwin
@add_test_categories(['pyapi'])
- def test_with_python_api(self):
+ def test_with_python_api_queues(self):
"""Test queues inspection SB APIs."""
self.build()
self.queues()
+
+ @skipUnlessDarwin
+ @add_test_categories(['pyapi'])
+ def test_with_python_api_queues_with_backtrace(self):
+ """Test queues inspection SB APIs."""
+ self.build()
self.queues_with_libBacktraceRecording()
def setUp(self):
@@ -113,7 +119,7 @@ class TestQueues(TestBase):
break1 = target.BreakpointCreateByName("stopper", 'a.out')
self.assertTrue(break1, VALID_BREAKPOINT)
process = target.LaunchSimple(
- None, None, self.get_process_working_directory())
+ [], None, self.get_process_working_directory())
self.assertTrue(process, PROCESS_IS_VALID)
threads = lldbutil.get_threads_stopped_at_breakpoint(process, break1)
if len(threads) != 1:
@@ -267,10 +273,14 @@ class TestQueues(TestBase):
self.assertTrue(break1, VALID_BREAKPOINT)
# Now launch the process, and do not stop at entry point.
+ libbtr_path = "/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib"
+ if self.getArchitecture() in ['arm', 'arm64', 'arm64e', 'arm64_32', 'armv7', 'armv7k']:
+ libbtr_path = "/Developer/usr/lib/libBacktraceRecording.dylib"
+
process = target.LaunchSimple(
- None,
+ [],
[
- 'DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib',
+ 'DYLD_INSERT_LIBRARIES=%s' % (libbtr_path),
'DYLD_LIBRARY_PATH=/usr/lib/system/introspection'],
self.get_process_working_directory())
diff --git a/packages/Python/lldbsuite/test/macosx/queues/main.c b/packages/Python/lldbsuite/test/macosx/queues/main.c
index 715a3f3af52c..3978b92bff1a 100644
--- a/packages/Python/lldbsuite/test/macosx/queues/main.c
+++ b/packages/Python/lldbsuite/test/macosx/queues/main.c
@@ -1,13 +1,18 @@
-#include <stdio.h>
+#include <stdatomic.h>
+#include <string.h>
#include <unistd.h>
#include <dispatch/dispatch.h>
#include <pthread.h>
-int finished_enqueueing_work = 0;
+atomic_int finished_enqueueing_work = 0;
+atomic_int thread_count = 0;
void
doing_the_work_1(void *in)
{
+ // This is only counted once because the first job in the queue
+ // starves all the others.
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (1);
}
@@ -26,13 +31,15 @@ submit_work_1b(void *in)
dispatch_queue_t *work_performer_1 = (dispatch_queue_t*) in;
dispatch_async_f (*work_performer_1, NULL, doing_the_work_1);
dispatch_async_f (*work_performer_1, NULL, doing_the_work_1);
+ atomic_fetch_add(&thread_count, 1);
while (1)
- sleep (1);
+ sleep (1);
}
void
doing_the_work_2(void *in)
{
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (1);
}
@@ -42,20 +49,22 @@ submit_work_2(void *in)
{
dispatch_queue_t *work_performer_2 = (dispatch_queue_t*) in;
int i = 0;
- while (i++ < 5000)
+ while (i++ < 5000)
{
dispatch_async_f (*work_performer_2, NULL, doing_the_work_2);
dispatch_async_f (*work_performer_2, NULL, doing_the_work_2);
}
- finished_enqueueing_work = 1;
+ atomic_fetch_add(&finished_enqueueing_work, 1);
}
void
doing_the_work_3(void *in)
{
+ // This counts four times, since the queue is marked as CONCURRENT.
+ atomic_fetch_add(&thread_count, 1);
while (1)
- sleep(1);
+ sleep (1);
}
void
@@ -77,7 +86,7 @@ stopper ()
}
-int main ()
+int main (int argc, const char **argv)
{
dispatch_queue_t work_submittor_1 = dispatch_queue_create ("com.apple.work_submittor_1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t work_submittor_2 = dispatch_queue_create ("com.apple.work_submittor_and_quit_2", DISPATCH_QUEUE_SERIAL);
@@ -97,41 +106,46 @@ int main ()
// Spin up threads with each of the different libdispatch QoS values.
-
dispatch_async (dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{
pthread_setname_np ("user initiated QoS");
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (10);
- });
+ });
dispatch_async (dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{
pthread_setname_np ("user interactive QoS");
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (10);
- });
+ });
dispatch_async (dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
pthread_setname_np ("default QoS");
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (10);
- });
+ });
dispatch_async (dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{
pthread_setname_np ("utility QoS");
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (10);
- });
+ });
dispatch_async (dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), ^{
pthread_setname_np ("background QoS");
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (10);
- });
+ });
dispatch_async (dispatch_get_global_queue(QOS_CLASS_UNSPECIFIED, 0), ^{
pthread_setname_np ("unspecified QoS");
+ atomic_fetch_add(&thread_count, 1);
while (1)
sleep (10);
- });
+ });
-
- while (finished_enqueueing_work == 0)
+ // Unfortunately there is no pthread_barrier on darwin.
+ while ((atomic_load(&thread_count) < 13) || (finished_enqueueing_work == 0))
sleep (1);
- stopper ();
+ stopper ();
}
diff --git a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c
index 613384ff73b3..586500876288 100644
--- a/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c
+++ b/packages/Python/lldbsuite/test/macosx/safe-to-func-call/main.c
@@ -1,3 +1,4 @@
+#include <sys/time.h> // work around module map issue with iOS sdk, <rdar://problem/35159346>
#include <sys/select.h>
#include <stdio.h>
#include <pthread.h>
diff --git a/packages/Python/lldbsuite/test/macosx/universal/Makefile b/packages/Python/lldbsuite/test/macosx/universal/Makefile
index d74ed26f50ab..a83de2a6c7e6 100644
--- a/packages/Python/lldbsuite/test/macosx/universal/Makefile
+++ b/packages/Python/lldbsuite/test/macosx/universal/Makefile
@@ -1,21 +1,25 @@
-CC ?= clang
+LEVEL := ../../make
+
+EXE := testit
+
+include $(LEVEL)/Makefile.rules
all: testit
-testit: testit.i386 testit.x86_64
+testit: testit.x86_64h testit.x86_64
lipo -create -o testit $^
-testit.i386: testit.i386.o
- $(CC) -arch i386 -o testit.i386 $<
+testit.x86_64h: testit.x86_64h.o
+ $(CC) -arch x86_64h -o testit.x86_64h $<
testit.x86_64: testit.x86_64.o
$(CC) -arch x86_64 -o testit.x86_64 $<
-testit.i386.o: main.c
- $(CC) -g -O0 -arch i386 -c -o testit.i386.o $<
+testit.x86_64h.o: main.c
+ $(CC) -g -O0 -arch x86_64h -c -o testit.x86_64h.o $<
testit.x86_64.o: main.c
$(CC) -g -O0 -arch x86_64 -c -o testit.x86_64.o $<
-clean:
+clean::
rm -rf $(wildcard testit* *~)
diff --git a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py
index ca4f3ce9b137..93fb358f4c84 100644
--- a/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py
+++ b/packages/Python/lldbsuite/test/macosx/universal/TestUniversal.py
@@ -11,9 +11,13 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
+def haswellOrLater():
+ features = subprocess.check_output(["sysctl", "machdep.cpu"])
+ return "AVX2" in features.split()
class UniversalTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
mydir = TestBase.compute_mydir(__file__)
def setUp(self):
@@ -24,8 +28,8 @@ class UniversalTestCase(TestBase):
@add_test_categories(['pyapi'])
@skipUnlessDarwin
- @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [
- 'i386', 'x86_64'], "requires i386 or x86_64")
+ @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in
+ ['x86_64'], "requires x86_64")
@skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system
def test_sbdebugger_create_target_with_file_and_target_triple(self):
"""Test the SBDebugger.CreateTargetWithFileAndTargetTriple() API."""
@@ -37,8 +41,9 @@ class UniversalTestCase(TestBase):
# Create a target by the debugger.
target = self.dbg.CreateTargetWithFileAndTargetTriple(
- exe, "i386-apple-macosx")
+ exe, "x86_64-apple-macosx")
self.assertTrue(target, VALID_TARGET)
+ self.expect("image list -A -b", substrs=["x86_64 testit"])
# Now launch the process, and do not stop at entry point.
process = target.LaunchSimple(
@@ -46,13 +51,16 @@ class UniversalTestCase(TestBase):
self.assertTrue(process, PROCESS_IS_VALID)
@skipUnlessDarwin
- @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [
- 'i386', 'x86_64'], "requires i386 or x86_64")
+ @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in
+ ['x86_64'], "requires x86_64")
@skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system
def test_process_launch_for_universal(self):
"""Test process launch of a universal binary."""
from lldbsuite.test.lldbutil import print_registers
+ if not haswellOrLater():
+ return
+
# Invoke the default build rule.
self.build()
@@ -62,69 +70,54 @@ class UniversalTestCase(TestBase):
# By default, x86_64 is assumed if no architecture is specified.
self.expect("file " + exe, CURRENT_EXECUTABLE_SET,
startstr="Current executable set to ",
- substrs=["testit' (x86_64)."])
+ substrs=["testit' (x86_64h)."])
# Break inside the main.
lldbutil.run_break_set_by_file_and_line(
self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
- # We should be able to launch the x86_64 executable.
+ # We should be able to launch the x86_64h executable.
self.runCmd("run", RUN_SUCCEEDED)
- # Check whether we have a 64-bit process launched.
+ # Check whether we have a x86_64h process launched.
target = self.dbg.GetSelectedTarget()
process = target.GetProcess()
- self.assertTrue(target and process and
- self.invoke(process, 'GetAddressByteSize') == 8,
- "64-bit process launched")
-
- frame = process.GetThreadAtIndex(0).GetFrameAtIndex(0)
- registers = print_registers(frame, string_buffer=True)
- self.expect(registers, exe=False,
- substrs=['Name: rax'])
-
+ self.expect("image list -A -b", substrs=["x86_64h testit"])
self.runCmd("continue")
- # Now specify i386 as the architecture for "testit".
- self.expect("file -a i386 " + exe, CURRENT_EXECUTABLE_SET,
+ # Now specify x86_64 as the architecture for "testit".
+ self.expect("file -a x86_64 " + exe, CURRENT_EXECUTABLE_SET,
startstr="Current executable set to ",
- substrs=["testit' (i386)."])
+ substrs=["testit' (x86_64)."])
# Break inside the main.
lldbutil.run_break_set_by_file_and_line(
self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
- # We should be able to launch the i386 executable as well.
+ # We should be able to launch the x86_64 executable as well.
self.runCmd("run", RUN_SUCCEEDED)
- # Check whether we have a 32-bit process launched.
- target = self.dbg.GetSelectedTarget()
- process = target.GetProcess()
- self.assertTrue(target and process,
- "32-bit process launched")
-
- pointerSize = self.invoke(process, 'GetAddressByteSize')
- self.assertTrue(
- pointerSize == 4,
- "AddressByteSize of 32-bit process should be 4, got %d instead." %
- pointerSize)
-
- frame = process.GetThreadAtIndex(0).GetFrameAtIndex(0)
- registers = print_registers(frame, string_buffer=True)
- self.expect(registers, exe=False,
- substrs=['Name: eax'])
-
+ # Check whether we have a x86_64 process launched.
+
+ # FIXME: This wrong. We are expecting x86_64, but spawning a
+ # new process currently doesn't allow specifying a *sub*-architecture.
+ # <rdar://problem/46101466>
+ self.expect("image list -A -b", substrs=["x86_64h testit"])
self.runCmd("continue")
@skipUnlessDarwin
- @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in [
- 'i386', 'x86_64'], "requires i386 or x86_64")
+ @unittest2.skipUnless(hasattr(os, "uname") and os.uname()[4] in
+ ['x86_64'], "requires x86_64")
@skipIfDarwinEmbedded # this test file assumes we're targetting an x86 system
def test_process_attach_with_wrong_arch(self):
- """Test that when we attach to a binary from the wrong fork of a universal binary, we fix up the ABI correctly."""
- # Now keep the architecture at 32 bit, but switch the binary we launch to
- # 64 bit, and make sure on attach we switch to the correct
- # architecture.
+ """Test that when we attach to a binary from the wrong fork of
+ a universal binary, we fix up the ABI correctly."""
+ if not haswellOrLater():
+ return
+
+ # Now keep the architecture at x86_64, but switch the binary
+ # we launch to x86_64h, and make sure on attach we switch to
+ # the correct architecture.
# Invoke the default build rule.
self.build()
@@ -134,10 +127,9 @@ class UniversalTestCase(TestBase):
# Create a target by the debugger.
target = self.dbg.CreateTargetWithFileAndTargetTriple(
- exe, "i386-apple-macosx")
+ exe, "x86_64-apple-macosx")
self.assertTrue(target, VALID_TARGET)
- pointer_size = target.GetAddressByteSize()
- self.assertTrue(pointer_size == 4, "Initially we were 32 bit.")
+ self.expect("image list -A -b", substrs=["x86_64 testit"])
bkpt = target.BreakpointCreateBySourceRegex(
"sleep", lldb.SBFileSpec("main.c"))
@@ -155,14 +147,14 @@ class UniversalTestCase(TestBase):
empty_listener, popen.pid, error)
self.assertTrue(error.Success(), "Attached to process.")
- pointer_size = target.GetAddressByteSize()
- self.assertTrue(pointer_size == 8, "We switched to 64 bit.")
+ self.expect("image list -A -b", substrs=["x86_64h testit"])
- # It may seem odd that I am checking the number of frames, but the bug that
- # motivated this test was that we eventually fixed the architecture, but we
- # left the ABI set to the original value. In that case, if you asked the
- # process for its architecture, it would look right, but since the ABI was
- # wrong, backtracing failed.
+ # It may seem odd to check the number of frames, but the bug
+ # that motivated this test was that we eventually fixed the
+ # architecture, but we left the ABI set to the original value.
+ # In that case, if you asked the process for its architecture,
+ # it would look right, but since the ABI was wrong,
+ # backtracing failed.
threads = lldbutil.continue_to_breakpoint(process, bkpt)
self.assertTrue(len(threads) == 1)
diff --git a/packages/Python/lldbsuite/test/make/Makefile.rules b/packages/Python/lldbsuite/test/make/Makefile.rules
index 32f41b24d5dc..a2dc6cc66595 100644
--- a/packages/Python/lldbsuite/test/make/Makefile.rules
+++ b/packages/Python/lldbsuite/test/make/Makefile.rules
@@ -29,10 +29,10 @@
# SHELL = /bin/sh -x
SRCDIR := $(shell dirname $(firstword $(MAKEFILE_LIST)))/
+BUILDDIR := $(shell pwd)
THIS_FILE_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))/
LLDB_BASE_DIR := $(THIS_FILE_DIR)../../../../../
-
#----------------------------------------------------------------------
# If OS is not defined, use 'uname -s' to determine the OS name.
#
@@ -50,6 +50,33 @@ ifeq "$(OS)" ""
endif
#----------------------------------------------------------------------
+# If OS is Windows, force SHELL to be cmd
+#
+# Some versions of make on Windows will search for other shells such as
+# C:\cygwin\bin\sh.exe. This shell fails for numerous different reasons
+# so default to using cmd.exe.
+#----------------------------------------------------------------------
+ifeq "$(OS)" "Windows_NT"
+ SHELL = $(WINDIR)\system32\cmd.exe
+endif
+
+#----------------------------------------------------------------------
+# If the OS is Windows use double-quotes in commands
+#
+# For other operating systems, single-quotes work fine, but on Windows
+# we strictly required double-quotes
+#----------------------------------------------------------------------
+ifeq "$(HOST_OS)" "Windows_NT"
+ JOIN_CMD = &
+ QUOTE = "
+ FIXUP_SYNTAX_HIGHLIGHTING_IN_MY_EDITOR = "
+else
+ JOIN_CMD = ;
+ QUOTE = '
+ FIXUP_SYNTAX_HIGHLIGHTING_IN_MY_EDITOR = '
+endif
+
+#----------------------------------------------------------------------
# If TRIPLE is not defined try to set the ARCH, CC, CFLAGS, and more
# from the triple alone
#----------------------------------------------------------------------
@@ -63,7 +90,8 @@ ifneq "$(TRIPLE)" ""
TRIPLE_VERSION =$(word 2, $(triple_os_and_version))
ifeq "$(TRIPLE_VENDOR)" "apple"
ifeq "$(TRIPLE_OS)" "ios"
- ifeq "$(SDKROOT)" ""
+ CODESIGN := codesign
+ ifeq "$(SDKROOT)" ""
# Set SDKROOT if it wasn't set
ifneq (,$(findstring arm,$(ARCH)))
SDKROOT = $(shell xcrun --sdk iphoneos --show-sdk-path)
@@ -81,7 +109,8 @@ ifneq "$(TRIPLE)" ""
endif
endif
ifeq "$(TRIPLE_OS)" "watchos"
- ifeq "$(SDKROOT)" ""
+ CODESIGN := codesign
+ ifeq "$(SDKROOT)" ""
# Set SDKROOT if it wasn't set
ifneq (,$(findstring arm,$(ARCH)))
SDKROOT = $(shell xcrun --sdk watchos --show-sdk-path)
@@ -228,6 +257,12 @@ endif
CFLAGS += -I$(SRCDIR) -include $(THIS_FILE_DIR)test_common.h -I$(THIS_FILE_DIR)
CFLAGS += $(NO_LIMIT_DEBUG_INFO_FLAGS) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS)
+# If the OS is Windows, we need to pass -gdwarf to clang, otherwise it will build
+# with codeview by default but all the tests rely on dwarf.
+ifeq "$(OS)" "Windows_NT"
+ CFLAGS += -gdwarf
+endif
+
# Use this one if you want to build one part of the result without debug information:
ifeq "$(OS)" "Darwin"
CFLAGS_NO_DEBUG = -O0 $(ARCHFLAG) $(ARCH) $(FRAMEWORK_INCLUDES) $(ARCH_CFLAGS) $(CFLAGS_EXTRAS)
@@ -239,12 +274,22 @@ ifeq "$(MAKE_DWO)" "YES"
CFLAGS += -gsplit-dwarf
endif
-CLANG_MODULE_CACHE_DIR := module-cache
+# Use a shared module cache when building in the default test build directory.
+CLANG_MODULE_CACHE_DIR := $(shell echo "$(BUILDDIR)" | sed $(QUOTE)s/lldb-test-build.noindex.*/lldb-test-build.noindex\/module-cache-clang/$(QUOTE))
+
+ifeq "$(findstring lldb-test-build.noindex, $(BUILDDIR))" ""
+CLANG_MODULE_CACHE_DIR := $(BUILDDIR)/module-cache
+$(warning failed to set the shared clang module cache dir)
+endif
MANDATORY_MODULE_BUILD_CFLAGS := -fmodules -gmodules -fmodules-cache-path=$(CLANG_MODULE_CACHE_DIR)
ifeq "$(MAKE_GMODULES)" "YES"
CFLAGS += $(MANDATORY_MODULE_BUILD_CFLAGS)
+ CXXFLAGS += $(MANDATORY_MODULE_BUILD_CFLAGS)
+ ifeq "$(OS)" "Darwin"
+ CXXFLAGS += -fcxx-modules
+ endif
endif
CXXFLAGS += -std=c++11 $(CFLAGS) $(ARCH_CXXFLAGS)
@@ -315,7 +360,7 @@ ifneq "$(OS)" "Darwin"
endif
ifdef PIE
- LDFLAGS += -pie
+ LDFLAGS += -pie
endif
#----------------------------------------------------------------------
@@ -380,17 +425,17 @@ ifneq "$(strip $(DYLIB_OBJC_SOURCES))" ""
endif
ifneq "$(strip $(DYLIB_CXX_SOURCES))" ""
- DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o))
- CXX = $(call cxx_compiler,$(CC))
- LD = $(call cxx_linker,$(CC))
+ DYLIB_OBJECTS +=$(strip $(DYLIB_CXX_SOURCES:.cpp=.o))
+ CXX = $(call cxx_compiler,$(CC))
+ LD = $(call cxx_linker,$(CC))
endif
#----------------------------------------------------------------------
# Check if we have a precompiled header
#----------------------------------------------------------------------
ifneq "$(strip $(PCH_CXX_SOURCE))" ""
- PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch)
- PCHFLAGS = -include $(PCH_CXX_SOURCE)
+ PCH_OUTPUT = $(PCH_CXX_SOURCE:.h=.h.pch)
+ PCHFLAGS = -include $(PCH_CXX_SOURCE)
endif
#----------------------------------------------------------------------
@@ -472,21 +517,21 @@ ifneq "$(strip $(CXX_SOURCES) $(OBJCXX_SOURCES))" ""
ifneq "$(filter g++,$(CXX))" ""
CXXVERSION = $(shell $(CXX) -dumpversion | cut -b 1-3)
ifeq "$(CXXVERSION)" "4.6"
- # GCC 4.6 cannot handle -std=c++11, so replace it with -std=c++0x
- # instead. FIXME: remove once GCC version is upgraded.
+ # GCC 4.6 cannot handle -std=c++11, so replace it with -std=c++0x
+ # instead. FIXME: remove once GCC version is upgraded.
override CXXFLAGS := $(subst -std=c++11,-std=c++0x,$(CXXFLAGS))
endif
endif
endif
ifeq ($(findstring clang, $(CXX)), clang)
- CXXFLAGS += --driver-mode=g++
+ CXXFLAGS += --driver-mode=g++
endif
ifneq "$(CXX)" ""
- ifeq ($(findstring clang, $(LD)), clang)
- LDFLAGS += --driver-mode=g++
- endif
+ ifeq ($(findstring clang, $(LD)), clang)
+ LDFLAGS += --driver-mode=g++
+ endif
endif
#----------------------------------------------------------------------
@@ -508,6 +553,9 @@ endif
else
$(EXE) : $(OBJECTS) $(ARCHIVE_NAME)
$(LD) $(OBJECTS) $(LDFLAGS) $(ARCHIVE_NAME) -o "$(EXE)"
+ifneq "$(CODESIGN)" ""
+ $(CODESIGN) -s - "$(EXE)"
+endif
endif
#----------------------------------------------------------------------
@@ -552,6 +600,9 @@ endif
$(DYLIB_FILENAME) : $(DYLIB_OBJECTS)
ifeq "$(OS)" "Darwin"
$(LD) $(DYLIB_OBJECTS) $(LDFLAGS) -install_name "$(DYLIB_EXECUTABLE_PATH)/$(DYLIB_FILENAME)" -dynamiclib -o "$(DYLIB_FILENAME)"
+ifneq "$(CODESIGN)" ""
+ $(CODESIGN) -s - "$(DYLIB_FILENAME)"
+endif
ifneq "$(MAKE_DSYM)" "NO"
ifneq "$(DS)" ""
"$(DS)" $(DSFLAGS) "$(DYLIB_FILENAME)"
@@ -594,14 +645,6 @@ endif
# the compiler -MM option. The -M option will list all system headers,
# and the -MM option will list all non-system dependencies.
#----------------------------------------------------------------------
-ifeq "$(HOST_OS)" "Windows_NT"
- JOIN_CMD = &
- QUOTE = "
-else
- JOIN_CMD = ;
- QUOTE = '
-endif
-
%.d: %.c
@rm -f $@ $(JOIN_CMD) \
$(CC) -M $(CFLAGS) $< > $@.tmp && \
diff --git a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py
index 8a9e456f3458..f5d143fbd40b 100644
--- a/packages/Python/lldbsuite/test/python_api/event/TestEvents.py
+++ b/packages/Python/lldbsuite/test/python_api/event/TestEvents.py
@@ -119,7 +119,6 @@ class EventAPITestCase(TestBase):
@add_test_categories(['pyapi'])
@expectedFlakeyLinux("llvm.org/pr23730") # Flaky, fails ~1/100 cases
- @expectedFlakeyOS(oslist=["windows"])
def test_wait_for_event(self):
"""Exercise SBListener.WaitForEvent() API."""
self.build()
@@ -198,7 +197,6 @@ class EventAPITestCase(TestBase):
@expectedFailureAll(
oslist=["linux"],
bugnumber="llvm.org/pr23617 Flaky, fails ~1/10 cases")
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_add_listener_to_broadcaster(self):
"""Exercise some SBBroadcaster APIs."""
self.build()
diff --git a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py
index 85e915ad3a48..fc2f03f9e617 100644
--- a/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py
+++ b/packages/Python/lldbsuite/test/python_api/frame/TestFrames.py
@@ -20,7 +20,6 @@ class FrameAPITestCase(TestBase):
mydir = TestBase.compute_mydir(__file__)
@add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778")
def test_get_arg_vals_for_call_stack(self):
"""Exercise SBFrame.GetVariables() API to get argument vals."""
self.build()
diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py
index b0f09d2fa7b5..33f4a790aacf 100644
--- a/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py
+++ b/packages/Python/lldbsuite/test/python_api/hello_world/TestHelloWorld.py
@@ -10,8 +10,7 @@ import time
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
-from lldbsuite.test import lldbutil
-
+import lldbsuite.test.lldbutil as lldbutil
class HelloWorldTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
@@ -35,7 +34,7 @@ class HelloWorldTestCase(TestBase):
def test_with_process_launch_api(self):
"""Create target, breakpoint, launch a process, and then kill it."""
# Get the full path to our executable to be attached/debugged.
- exe = self.getBuildArtifact(self.testMethodName)
+ exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())
d = {'EXE': exe}
self.build(dictionary=d)
self.setTearDownCleanup(dictionary=d)
@@ -77,23 +76,22 @@ class HelloWorldTestCase(TestBase):
self.assertEqual(breakpoint.GetHitCount(), 1, BREAKPOINT_HIT_ONCE)
@add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600")
@skipIfiOSSimulator
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
def test_with_attach_to_process_with_id_api(self):
"""Create target, spawn a process, and attach to it with process id."""
- exe = self.getBuildArtifact(self.testMethodName)
+ exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())
d = {'EXE': exe}
self.build(dictionary=d)
self.setTearDownCleanup(dictionary=d)
target = self.dbg.CreateTarget(exe)
# Spawn a new process
- popen = self.spawnSubprocess(exe, ["abc", "xyz"])
+ token = exe+'.token'
+ if os.path.exists(token):
+ os.remove(token)
+ popen = self.spawnSubprocess(exe, [token])
self.addTearDownHook(self.cleanupSubprocesses)
-
- # Give the subprocess time to start and wait for user input
- time.sleep(0.25)
+ lldbutil.wait_for_file_on_target(self, token)
listener = lldb.SBListener("my.attach.listener")
error = lldb.SBError()
@@ -102,30 +100,29 @@ class HelloWorldTestCase(TestBase):
self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
# Let's check the stack traces of the attached process.
- import lldbsuite.test.lldbutil as lldbutil
stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)
self.expect(stacktraces, exe=False,
substrs=['main.c:%d' % self.line2,
- '(int)argc=3'])
+ '(int)argc=2'])
@add_test_categories(['pyapi'])
- @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24600")
@skipIfiOSSimulator
- @expectedFailureAll(oslist=['ios', 'watchos', 'tvos', 'bridgeos'], bugnumber="<rdar://problem/34538611>") # old lldb-server has race condition, launching an inferior and then launching debugserver in quick succession sometimes fails
+ @skipIfSanitized # FIXME: Hangs indefinitely.
def test_with_attach_to_process_with_name_api(self):
"""Create target, spawn a process, and attach to it with process name."""
- exe = self.getBuildArtifact(self.testMethodName)
+ exe = '%s_%d'%(self.getBuildArtifact(self.testMethodName), os.getpid())
d = {'EXE': exe}
self.build(dictionary=d)
self.setTearDownCleanup(dictionary=d)
target = self.dbg.CreateTarget(exe)
- # Spawn a new process
- popen = self.spawnSubprocess(exe, ["abc", "xyz"])
+ # Spawn a new process.
+ token = exe+'.token'
+ if os.path.exists(token):
+ os.remove(token)
+ popen = self.spawnSubprocess(exe, [token])
self.addTearDownHook(self.cleanupSubprocesses)
-
- # Give the subprocess time to start and wait for user input
- time.sleep(0.25)
+ lldbutil.wait_for_file_on_target(self, token)
listener = lldb.SBListener("my.attach.listener")
error = lldb.SBError()
@@ -140,7 +137,6 @@ class HelloWorldTestCase(TestBase):
target.ConnectRemote(listener, None, None, error)
process = target.AttachToProcessWithName(listener, name, False, error)
-
self.assertTrue(error.Success() and process, PROCESS_IS_VALID)
# Verify that after attach, our selected target indeed matches name.
@@ -150,8 +146,7 @@ class HelloWorldTestCase(TestBase):
startstr=name)
# Let's check the stack traces of the attached process.
- import lldbsuite.test.lldbutil as lldbutil
stacktraces = lldbutil.print_stacktraces(process, string_buffer=True)
self.expect(stacktraces, exe=False,
substrs=['main.c:%d' % self.line2,
- '(int)argc=3'])
+ '(int)argc=2'])
diff --git a/packages/Python/lldbsuite/test/python_api/hello_world/main.c b/packages/Python/lldbsuite/test/python_api/hello_world/main.c
index 32b0446517c5..c516f923614f 100644
--- a/packages/Python/lldbsuite/test/python_api/hello_world/main.c
+++ b/packages/Python/lldbsuite/test/python_api/hello_world/main.c
@@ -8,16 +8,22 @@
int main(int argc, char const *argv[])
{
- lldb_enable_attach();
+ lldb_enable_attach();
- printf("Hello world.\n"); // Set break point at this line.
- if (argc == 1)
- return 0;
+ printf("Hello world.\n"); // Set break point at this line.
+ if (argc == 1)
+ return 1;
- // Waiting to be attached by the debugger, otherwise.
- char line[100];
- while (1)
- sleep (1); // Waiting to be attached...
+ // Create the synchronization token.
+ FILE *f;
+ if (f = fopen(argv[1], "wx")) {
+ fputs("\n", f);
+ fflush(f);
+ fclose(f);
+ } else
+ return 1;
- printf("Exiting now\n");
+ // Waiting to be attached by the debugger, otherwise.
+ while (1)
+ sleep(1); // Waiting to be attached...
}
diff --git a/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp b/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp
index 79aa2d0452f4..b38208ce2a35 100644
--- a/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp
+++ b/packages/Python/lldbsuite/test/python_api/name_lookup/main.cpp
@@ -51,4 +51,4 @@ int main (int argc, char const *argv[])
g.unique_function_name();
g.unique_function_name(argc);
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp
index 650d87acd6e6..c54339f3bba6 100644
--- a/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp
+++ b/packages/Python/lldbsuite/test/python_api/sbvalue_persist/main.cpp
@@ -11,4 +11,4 @@ int main() {
f(); // break here
f(); // break here
return 0;
-} \ No newline at end of file
+}
diff --git a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py
index 8a4af0cc2b94..2299f1f1432d 100644
--- a/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py
+++ b/packages/Python/lldbsuite/test/python_api/value/TestValueAPI.py
@@ -153,6 +153,9 @@ class ValueAPITestCase(TestBase):
val_s = target.EvaluateExpression('s')
val_a = target.EvaluateExpression('a')
self.assertTrue(
+ val_s.GetChildMemberWithName('a').GetAddress().IsValid(),
+ VALID_VARIABLE)
+ self.assertTrue(
val_s.GetChildMemberWithName('a').AddressOf(),
VALID_VARIABLE)
self.assertTrue(
diff --git a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
index d5862d274ceb..3c19c589b7a7 100644
--- a/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
+++ b/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
@@ -108,7 +108,6 @@ class TargetWatchAddressAPITestCase(TestBase):
# No size constraint on MIPS for watches
@skipIf(archs=['mips', 'mipsel', 'mips64', 'mips64el'])
@skipIf(archs=['s390x']) # Likewise on SystemZ
- @expectedFailureAll(oslist=["windows"])
def test_watch_address_with_invalid_watch_size(self):
"""Exercise SBTarget.WatchAddress() API but pass an invalid watch_size."""
self.build()
diff --git a/packages/Python/lldbsuite/test/settings/TestSettings.py b/packages/Python/lldbsuite/test/settings/TestSettings.py
index d6fa5a93b72c..b46e3b4103c6 100644
--- a/packages/Python/lldbsuite/test/settings/TestSettings.py
+++ b/packages/Python/lldbsuite/test/settings/TestSettings.py
@@ -132,7 +132,7 @@ class SettingsCommandTestCase(TestBase):
# Change the default format to print function.name rather than
# function.name-with-args
- format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n"
+ format_string = "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}\`${function.name}{${function.pc-offset}}}{ at ${line.file.fullpath}:${line.number}}{, lang=${language}}\n"
self.runCmd("settings set frame-format %s" % format_string)
# Immediately test the setting.
@@ -418,11 +418,11 @@ class SettingsCommandTestCase(TestBase):
# Set to known value
self.runCmd("settings set target.language c89")
# Set to new value with trailing whitespace
- self.runCmd("settings set target.language go ")
+ self.runCmd("settings set target.language c11 ")
self.expect(
"settings show target.language",
SETTING_MSG("target.language"),
- startstr="target.language (language) = go")
+ startstr="target.language (language) = c11")
self.runCmd("settings clear target.language", check=False)
# arguments
self.runCmd("settings set target.run-args 1 2 3") # Set to known value
diff --git a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
index 0df4f8b2d2a8..ea822decdb6f 100644
--- a/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
+++ b/packages/Python/lldbsuite/test/source-manager/TestSourceManager.py
@@ -22,6 +22,8 @@ def ansi_underline_surround_regex(inner_regex_text):
# return re.compile(r"\[4m%s\[0m" % inner_regex_text)
return "4.+\033\\[4m%s\033\\[0m" % inner_regex_text
+def ansi_color_surround_regex(inner_regex_text):
+ return "\033\\[3[0-7]m%s\033\\[0m" % inner_regex_text
class SourceManagerTestCase(TestBase):
@@ -47,7 +49,7 @@ class SourceManagerTestCase(TestBase):
# the character column after the initial whitespace.
return len(stop_line) - len(stop_line.lstrip()) + 1
- def do_display_source_python_api(self, use_color, column_marker_regex):
+ def do_display_source_python_api(self, use_color, needle_regex, highlight_source=False):
self.build()
exe = self.getBuildArtifact("a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
@@ -69,6 +71,9 @@ class SourceManagerTestCase(TestBase):
# Setup whether we should use ansi escape sequences, including color
# and styles such as underline.
self.dbg.SetUseColor(use_color)
+ # Disable syntax highlighting if needed.
+
+ self.runCmd("settings set highlight-source " + str(highlight_source).lower())
filespec = lldb.SBFileSpec(self.file, False)
source_mgr = self.dbg.GetSourceManager()
@@ -87,10 +92,10 @@ class SourceManagerTestCase(TestBase):
# => 4 printf("Hello world.\n"); // Set break point at this line.
# 5 return 0;
# 6 }
- self.expect(stream.GetData(), "Source code displayed correctly",
+ self.expect(stream.GetData(), "Source code displayed correctly:\n" + stream.GetData(),
exe=False,
patterns=['=> %d.*Hello world' % self.line,
- column_marker_regex])
+ needle_regex])
# Boundary condition testings for SBStream(). LLDB should not crash!
stream.Print(None)
@@ -108,9 +113,28 @@ class SourceManagerTestCase(TestBase):
"""Test display of source using the SBSourceManager API, using a
dumb terminal and thus no color support (the default)."""
use_color = True
- underline_regex = ansi_underline_surround_regex(r".")
+ underline_regex = ansi_underline_surround_regex(r"printf")
self.do_display_source_python_api(use_color, underline_regex)
+ @add_test_categories(['pyapi'])
+ def test_display_source_python_ansi_terminal_syntax_highlighting(self):
+ """Test display of source using the SBSourceManager API and check for
+ the syntax highlighted output"""
+ use_color = True
+ syntax_highlighting = True;
+
+ # Just pick 'int' as something that should be colored.
+ color_regex = ansi_color_surround_regex("int")
+ self.do_display_source_python_api(use_color, color_regex, syntax_highlighting)
+
+ # Same for 'char'.
+ color_regex = ansi_color_surround_regex("char")
+ self.do_display_source_python_api(use_color, color_regex, syntax_highlighting)
+
+ # Test that we didn't color unrelated identifiers.
+ self.do_display_source_python_api(use_color, r" main\(", syntax_highlighting)
+ self.do_display_source_python_api(use_color, r"\);", syntax_highlighting)
+
def test_move_and_then_display_source(self):
"""Test that target.source-map settings work by moving main.c to hidden/main.c."""
self.build()
diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py
index ccd7eba8bfe3..848bd3852393 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-mi/interpreter/TestMiInterpreterExec.py
@@ -18,6 +18,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_target_create(self):
"""Test that 'lldb-mi --interpreter' can create target by 'target create' command."""
@@ -39,6 +40,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfRemote # We do not currently support remote debugging via the MI.
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows.
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races.
+ @skipIfDarwin
def test_lldbmi_target_list(self):
"""Test that 'lldb-mi --interpreter' can list targets by 'target list' command."""
@@ -58,6 +60,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_breakpoint_set(self):
"""Test that 'lldb-mi --interpreter' can set breakpoint by 'breakpoint set' command."""
@@ -82,6 +85,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@expectedFlakeyLinux(bugnumber="llvm.org/pr25470")
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_settings_set_target_run_args_before(self):
"""Test that 'lldb-mi --interpreter' can set target arguments by 'setting set target.run-args' command before than target was created."""
@@ -115,6 +119,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_process_launch(self):
"""Test that 'lldb-mi --interpreter' can launch process by "process launch" command."""
@@ -138,6 +143,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_thread_step_in(self):
"""Test that 'lldb-mi --interpreter' can step in by "thread step-in" command."""
@@ -170,6 +176,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfWindows # llvm.org/pr24452: Get lldb-mi tests working on Windows
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_thread_step_over(self):
"""Test that 'lldb-mi --interpreter' can step over by "thread step-over" command."""
@@ -196,6 +203,7 @@ class MiInterpreterExecTestCase(lldbmi_testcase.MiTestCaseBase):
@skipIfFreeBSD # llvm.org/pr22411: Failure presumably due to known thread races
@expectedFlakeyLinux("llvm.org/pr25470")
@skipIfRemote # We do not currently support remote debugging via the MI.
+ @skipIfDarwin
def test_lldbmi_thread_continue(self):
"""Test that 'lldb-mi --interpreter' can continue execution by "thread continue" command."""
diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py
index 7b6ee55b250e..59a5b324465f 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-mi/lldbmi_testcase.py
@@ -40,7 +40,7 @@ class MiTestCaseBase(Base):
pass
Base.tearDown(self)
- def spawnLldbMi(self, args=None):
+ def spawnLldbMi(self, exe=None, args=None, preconfig=True):
import pexpect
self.child = pexpect.spawn("%s --interpreter %s" % (
self.lldbMiExec, args if args else ""), cwd=self.getBuildDir())
@@ -49,6 +49,14 @@ class MiTestCaseBase(Base):
self.child.logfile_read = open(self.mylog, "w")
# wait until lldb-mi has started up and is ready to go
self.expect(self.child_prompt, exactly=True)
+ if preconfig:
+ self.runCmd("settings set symbols.enable-external-lookup false")
+ self.expect("\^done")
+ self.expect(self.child_prompt, exactly=True)
+ if exe:
+ self.runCmd("-file-exec-and-symbols \"%s\"" % exe)
+ # Testcases expect to be able to match output of this command,
+ # see test_lldbmi_specialchars.
def runCmd(self, cmd):
self.child.sendline(cmd)
diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py
index 467952db7eba..b78f4762ddf9 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/TestMiStartupOptions.py
@@ -22,7 +22,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
def test_lldbmi_executable_option_file(self):
"""Test that 'lldb-mi --interpreter %s' loads executable file."""
- self.spawnLldbMi(args="%s" % self.myexe)
+ self.spawnLldbMi(exe=self.myexe)
# Test that the executable is loaded when file was specified
self.expect("-file-exec-and-symbols \"%s\"" % self.myexe)
@@ -52,7 +52,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
# Prepare path to executable
path = "unknown_file"
- self.spawnLldbMi(args="%s" % path)
+ self.spawnLldbMi(exe=path)
# Test that the executable isn't loaded when unknown file was specified
self.expect("-file-exec-and-symbols \"%s\"" % path)
@@ -71,7 +71,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
"""Test that 'lldb-mi --interpreter %s' loads executable which is specified via absolute path."""
# Prepare path to executable
- self.spawnLldbMi(args="%s" % self.myexe)
+ self.spawnLldbMi(exe=self.myexe)
# Test that the executable is loaded when file was specified using
# absolute path
@@ -95,7 +95,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
# Prepare path to executable
path = os.path.relpath(self.myexe, self.getBuildDir())
- self.spawnLldbMi(args="%s" % path)
+ self.spawnLldbMi(exe=path)
# Test that the executable is loaded when file was specified using
# relative path
@@ -119,7 +119,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
# Prepare path to executable
path = "unknown_dir" + self.myexe
- self.spawnLldbMi(args="%s" % path)
+ self.spawnLldbMi(exe=path)
# Test that the executable isn't loaded when file was specified using
# unknown path
@@ -237,7 +237,11 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
# Prepared source file
sourceFile = self.copyScript("start_script_error")
- self.spawnLldbMi(args="--source %s" % sourceFile)
+ self.spawnLldbMi(args="--source %s" % sourceFile, preconfig=False)
+
+ # After 'settings set symbols.enable-external-lookup false'
+ self.expect("settings set symbols.enable-external-lookup false")
+ self.expect("\^done")
# After '-file-exec-and-symbols a.out'
self.expect("-file-exec-and-symbols %s" % self.myexe)
@@ -259,7 +263,7 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
"""Test that 'lldb-mi --log' creates a log file in the current directory."""
logDirectory = self.getBuildDir()
- self.spawnLldbMi(args="%s --log" % self.myexe)
+ self.spawnLldbMi(exe=self.myexe, args="--log")
# Test that the executable is loaded when file was specified
self.expect("-file-exec-and-symbols \"%s\"" % self.myexe)
@@ -296,9 +300,8 @@ class MiStartupOptionsTestCase(lldbmi_testcase.MiTestCaseBase):
import tempfile
logDirectory = tempfile.gettempdir()
- self.spawnLldbMi(
- args="%s --log --log-dir=%s" %
- (self.myexe, logDirectory))
+ self.spawnLldbMi(exe=self.myexe,
+ args="--log --log-dir=%s" % logDirectory)
# Test that the executable is loaded when file was specified
self.expect("-file-exec-and-symbols \"%s\"" % self.myexe)
diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error
index d834e7407c57..a1c581b08e0e 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error
+++ b/packages/Python/lldbsuite/test/tools/lldb-mi/startup_options/start_script_error
@@ -1,2 +1,3 @@
+settings set symbols.enable-external-lookup false
-file-exec-and-symbols a.out
-break-ins -f main
diff --git a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
index 50a94b53a18b..74d194e6dee2 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-mi/syntax/TestMiSyntax.py
@@ -53,7 +53,7 @@ class MiSyntaxTestCase(lldbmi_testcase.MiTestCaseBase):
os.symlink(self.myexe, complicated_myexe)
self.addTearDownHook(lambda: os.unlink(complicated_myexe))
- self.spawnLldbMi(args="\"%s\"" % complicated_myexe)
+ self.spawnLldbMi(exe=complicated_myexe)
# Test that the executable was loaded
self.expect(
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py
index 8c8fed8e44e0..62c948c36cf7 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestAppleSimulatorOSType.py
@@ -19,7 +19,13 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase):
sim_devices = json.loads(sim_devices_str)['devices']
# Find an available simulator for the requested platform
deviceUDID = None
- for (runtime,devices) in sim_devices.items():
+ for simulator in sim_devices:
+ if isinstance(simulator,dict):
+ runtime = simulator['name']
+ devices = simulator['devices']
+ else:
+ runtime = simulator
+ devices = sim_devices[simulator]
if not platform in runtime.lower():
continue
for device in devices:
@@ -95,18 +101,21 @@ class TestAppleSimulatorOSType(gdbremote_testcase.GdbRemoteTestCaseBase):
@apple_simulator_test('iphone')
@debugserver_test
+ @skipIfDarwinEmbedded
def test_simulator_ostype_ios(self):
self.check_simulator_ostype(sdk='iphonesimulator',
platform='ios')
@apple_simulator_test('appletv')
@debugserver_test
+ @skipIfDarwinEmbedded
def test_simulator_ostype_tvos(self):
self.check_simulator_ostype(sdk='appletvsimulator',
platform='tvos')
@apple_simulator_test('watch')
@debugserver_test
+ @skipIfDarwinEmbedded
def test_simulator_ostype_watchos(self):
self.check_simulator_ostype(sdk='watchsimulator',
platform='watchos', arch='i386')
diff --git a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
index 76910758fa91..cfadbc8f7d0f 100644
--- a/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
+++ b/packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteGPacket.py
@@ -35,6 +35,7 @@ class TestGdbRemoteGPacket(gdbremote_testcase.GdbRemoteTestCaseBase):
@skipIfOutOfTreeDebugserver
@debugserver_test
+ @skipIfDarwinEmbedded
def test_g_packet_debugserver(self):
self.init_debugserver_test()
self.run_test_g_packet()
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories b/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories
new file mode 100644
index 000000000000..ce2cfd048e38
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/.categories
@@ -0,0 +1 @@
+lldb-vscode
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile
new file mode 100644
index 000000000000..b09a579159d4
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py
new file mode 100644
index 000000000000..67cd05b83c3b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/TestVSCode_attach.py
@@ -0,0 +1,192 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+import shutil
+import subprocess
+import tempfile
+import threading
+import time
+
+
+def spawn_and_wait(program, delay):
+ if delay:
+ time.sleep(delay)
+ process = subprocess.Popen([program],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ process.wait()
+
+
+class TestVSCode_attach(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def set_and_hit_breakpoint(self, continueToExit=True):
+ source = 'main.c'
+ breakpoint1_line = line_number(source, '// breakpoint 1')
+ lines = [breakpoint1_line]
+ # Set breakoint in the thread function so we can step the threads
+ breakpoint_ids = self.set_source_breakpoints(source, lines)
+ self.assertEqual(len(breakpoint_ids), len(lines),
+ "expect correct number of breakpoints")
+ self.continue_to_breakpoints(breakpoint_ids)
+ if continueToExit:
+ self.continue_to_exit()
+
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_by_pid(self):
+ '''
+ Tests attaching to a process by process ID.
+ '''
+ self.build_and_create_debug_adaptor()
+ program = self.getBuildArtifact("a.out")
+ self.process = subprocess.Popen([program],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ self.attach(pid=self.process.pid)
+ self.set_and_hit_breakpoint(continueToExit=True)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_by_name(self):
+ '''
+ Tests attaching to a process by process name.
+ '''
+ self.build_and_create_debug_adaptor()
+ orig_program = self.getBuildArtifact("a.out")
+ # Since we are going to attach by process name, we need a unique
+ # process name that has minimal chance to match a process that is
+ # already running. To do this we use tempfile.mktemp() to give us a
+ # full path to a location where we can copy our executable. We then
+ # run this copy to ensure we don't get the error "more that one
+ # process matches 'a.out'".
+ program = tempfile.mktemp()
+ shutil.copyfile(orig_program, program)
+ shutil.copymode(orig_program, program)
+
+ def cleanup():
+ if os.path.exists(program):
+ os.unlink(program)
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ self.process = subprocess.Popen([program],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ # Wait for a bit to ensure the process is launched
+ time.sleep(5)
+ self.attach(program=program)
+ self.set_and_hit_breakpoint(continueToExit=True)
+
+ @skipUnlessDarwin
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_by_name_waitFor(self):
+ '''
+ Tests attaching to a process by process name and waiting for the
+ next instance of a process to be launched, ingoring all current
+ ones.
+ '''
+ self.build_and_create_debug_adaptor()
+ program = self.getBuildArtifact("a.out")
+ self.spawn_thread = threading.Thread(target=spawn_and_wait,
+ args=(program, 1.0,))
+ self.spawn_thread.start()
+ self.attach(program=program, waitFor=True)
+ self.set_and_hit_breakpoint(continueToExit=True)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_commands(self):
+ '''
+ Tests the "initCommands", "preRunCommands", "stopCommands",
+ "exitCommands", and "attachCommands" that can be passed during
+ attach.
+
+ "initCommands" are a list of LLDB commands that get executed
+ before the targt is created.
+ "preRunCommands" are a list of LLDB commands that get executed
+ after the target has been created and before the launch.
+ "stopCommands" are a list of LLDB commands that get executed each
+ time the program stops.
+ "exitCommands" are a list of LLDB commands that get executed when
+ the process exits
+ "attachCommands" are a list of LLDB commands that get executed and
+ must have a valid process in the selected target in LLDB after
+ they are done executing. This allows custom commands to create any
+ kind of debug session.
+ '''
+ self.build_and_create_debug_adaptor()
+ program = self.getBuildArtifact("a.out")
+ # Here we just create a target and launch the process as a way to test
+ # if we are able to use attach commands to create any kind of a target
+ # and use it for debugging
+ attachCommands = [
+ 'target create -d "%s"' % (program),
+ 'process launch -- arg1'
+ ]
+ initCommands = ['target list', 'platform list']
+ preRunCommands = ['image list a.out', 'image dump sections a.out']
+ stopCommands = ['frame variable', 'bt']
+ exitCommands = ['expr 2+3', 'expr 3+4']
+ self.attach(program=program,
+ attachCommands=attachCommands,
+ initCommands=initCommands,
+ preRunCommands=preRunCommands,
+ stopCommands=stopCommands,
+ exitCommands=exitCommands)
+
+ # Get output from the console. This should contain both the
+ # "initCommands" and the "preRunCommands".
+ output = self.get_console()
+ # Verify all "initCommands" were found in console output
+ self.verify_commands('initCommands', output, initCommands)
+ # Verify all "preRunCommands" were found in console output
+ self.verify_commands('preRunCommands', output, preRunCommands)
+
+ functions = ['main']
+ breakpoint_ids = self.set_function_breakpoints(functions)
+ self.assertTrue(len(breakpoint_ids) == len(functions),
+ "expect one breakpoint")
+ self.continue_to_breakpoints(breakpoint_ids)
+ output = self.get_console(timeout=1.0)
+ self.verify_commands('stopCommands', output, stopCommands)
+
+ # Continue after launch and hit the "pause()" call and stop the target.
+ # Get output from the console. This should contain both the
+ # "stopCommands" that were run after we stop.
+ self.vscode.request_continue()
+ time.sleep(0.5)
+ self.vscode.request_pause()
+ self.vscode.wait_for_stopped()
+ output = self.get_console(timeout=1.0)
+ self.verify_commands('stopCommands', output, stopCommands)
+
+ # Continue until the program exits
+ self.continue_to_exit()
+ # Get output from the console. This should contain both the
+ # "exitCommands" that were run after the second breakpoint was hit
+ output = self.get_console(timeout=1.0)
+ self.verify_commands('exitCommands', output, exitCommands)
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c
new file mode 100644
index 000000000000..a078d42203eb
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/attach/main.c
@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int argc, char const *argv[]) {
+ printf("pid = %i\n", getpid());
+ sleep(5);
+ return 0; // breakpoint 1
+}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile
new file mode 100644
index 000000000000..314f1cb2f077
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py
new file mode 100644
index 000000000000..1ebf2b8981ab
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setBreakpoints.py
@@ -0,0 +1,211 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import pprint
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+
+
+class TestVSCode_setBreakpoints(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_set_and_clear(self):
+ '''Tests setting and clearing source file and line breakpoints.
+ This packet is a bit tricky on the debug adaptor side since there
+ is no "clearBreakpoints" packet. Source file and line breakpoints
+ are set by sending a "setBreakpoints" packet with a source file
+ specified and zero or more source lines. If breakpoints have been
+ set in the source file before, any exising breakpoints must remain
+ set, and any new breakpoints must be created, and any breakpoints
+ that were in previous requests and are not in the current request
+ must be removed. This function tests this setting and clearing
+ and makes sure things happen correctly. It doesn't test hitting
+ breakpoints and the functionality of each breakpoint, like
+ 'conditions' and 'hitCondition' settings.'''
+ source_basename = 'main.cpp'
+ source_path = os.path.join(os.getcwd(), source_basename)
+ first_line = line_number('main.cpp', 'break 12')
+ second_line = line_number('main.cpp', 'break 13')
+ third_line = line_number('main.cpp', 'break 14')
+ lines = [first_line, second_line, third_line]
+
+ # Visual Studio Code Debug Adaptors have no way to specify the file
+ # without launching or attaching to a process, so we must start a
+ # process in order to be able to set breakpoints.
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+
+ # Set 3 breakoints and verify that they got set correctly
+ response = self.vscode.request_setBreakpoints(source_path, lines)
+ line_to_id = {}
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+ for breakpoint in breakpoints:
+ line = breakpoint['line']
+ # Store the "id" of the breakpoint that was set for later
+ line_to_id[line] = breakpoint['id']
+ self.assertTrue(line in lines, "line expected in lines array")
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint verified")
+
+ # There is no breakpoint delete packet, clients just send another
+ # setBreakpoints packet with the same source file with fewer lines.
+ # Below we remove the second line entry and call the setBreakpoints
+ # function again. We want to verify that any breakpoints that were set
+ # before still have the same "id". This means we didn't clear the
+ # breakpoint and set it again at the same location. We also need to
+ # verify that the second line location was actually removed.
+ lines.remove(second_line)
+ # Set 2 breakoints and verify that the previous breakoints that were
+ # set above are still set.
+ response = self.vscode.request_setBreakpoints(source_path, lines)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+ for breakpoint in breakpoints:
+ line = breakpoint['line']
+ # Verify the same breakpoints are still set within LLDB by
+ # making sure the breakpoint ID didn't change
+ self.assertTrue(line_to_id[line] == breakpoint['id'],
+ "verify previous breakpoints stayed the same")
+ self.assertTrue(line in lines, "line expected in lines array")
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint still verified")
+
+ # Now get the full list of breakpoints set in the target and verify
+ # we have only 2 breakpoints set. The response above could have told
+ # us about 2 breakpoints, but we want to make sure we don't have the
+ # third one still set in the target
+ response = self.vscode.request_testGetTargetBreakpoints()
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+ for breakpoint in breakpoints:
+ line = breakpoint['line']
+ # Verify the same breakpoints are still set within LLDB by
+ # making sure the breakpoint ID didn't change
+ self.assertTrue(line_to_id[line] == breakpoint['id'],
+ "verify previous breakpoints stayed the same")
+ self.assertTrue(line in lines, "line expected in lines array")
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint still verified")
+
+ # Now clear all breakpoints for the source file by passing down an
+ # empty lines array
+ lines = []
+ response = self.vscode.request_setBreakpoints(source_path, lines)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+
+ # Verify with the target that all breakpoints have been cleared
+ response = self.vscode.request_testGetTargetBreakpoints()
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+
+ # Now set a breakpoint again in the same source file and verify it
+ # was added.
+ lines = [second_line]
+ response = self.vscode.request_setBreakpoints(source_path, lines)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+ for breakpoint in breakpoints:
+ line = breakpoint['line']
+ self.assertTrue(line in lines, "line expected in lines array")
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint still verified")
+
+ # Now get the full list of breakpoints set in the target and verify
+ # we have only 2 breakpoints set. The response above could have told
+ # us about 2 breakpoints, but we want to make sure we don't have the
+ # third one still set in the target
+ response = self.vscode.request_testGetTargetBreakpoints()
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(lines),
+ "expect %u source breakpoints" % (len(lines)))
+ for breakpoint in breakpoints:
+ line = breakpoint['line']
+ self.assertTrue(line in lines, "line expected in lines array")
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint still verified")
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_functionality(self):
+ '''Tests hitting breakpoints and the functionality of a single
+ breakpoint, like 'conditions' and 'hitCondition' settings.'''
+ source_basename = 'main.cpp'
+ source_path = os.path.join(os.getcwd(), source_basename)
+ loop_line = line_number('main.cpp', '// break loop')
+
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ # Set a breakpoint at the loop line with no condition and no
+ # hitCondition
+ breakpoint_ids = self.set_source_breakpoints(source_path, [loop_line])
+ self.assertTrue(len(breakpoint_ids) == 1, "expect one breakpoint")
+ self.vscode.request_continue()
+
+ # Verify we hit the breakpoint we just set
+ self.verify_breakpoint_hit(breakpoint_ids)
+
+ # Make sure i is zero at first breakpoint
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 0, 'i != 0 after hitting breakpoint')
+
+ # Update the condition on our breakpoint
+ new_breakpoint_ids = self.set_source_breakpoints(source_path,
+ [loop_line],
+ condition="i==4")
+ self.assertTrue(breakpoint_ids == new_breakpoint_ids,
+ "existing breakpoint should have its condition "
+ "updated")
+
+ self.continue_to_breakpoints(breakpoint_ids)
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 4,
+ 'i != 4 showing conditional works')
+
+ new_breakpoint_ids = self.set_source_breakpoints(source_path,
+ [loop_line],
+ hitCondition="2")
+
+ self.assertTrue(breakpoint_ids == new_breakpoint_ids,
+ "existing breakpoint should have its condition "
+ "updated")
+
+ # Continue with a hitContidtion of 2 and expect it to skip 1 value
+ self.continue_to_breakpoints(breakpoint_ids)
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 6,
+ 'i != 6 showing hitCondition works')
+
+ # continue after hitting our hitCondition and make sure it only goes
+ # up by 1
+ self.continue_to_breakpoints(breakpoint_ids)
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 7,
+ 'i != 7 showing post hitCondition hits every time')
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py
new file mode 100644
index 000000000000..fdba683760e0
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setExceptionBreakpoints.py
@@ -0,0 +1,51 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import pprint
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+
+
+class TestVSCode_setExceptionBreakpoints(
+ lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_functionality(self):
+ '''Tests setting and clearing exception breakpoints.
+ This packet is a bit tricky on the debug adaptor side since there
+ is no "clear exception breakpoints" packet. Exception breakpoints
+ are set by sending a "setExceptionBreakpoints" packet with zero or
+ more exception filters. If exception breakpoints have been set
+ before, any exising breakpoints must remain set, and any new
+ breakpoints must be created, and any breakpoints that were in
+ previous requests and are not in the current request must be
+ removed. This exception tests this setting and clearing and makes
+ sure things happen correctly. It doesn't test hitting breakpoints
+ and the functionality of each breakpoint, like 'conditions' and
+ x'hitCondition' settings.
+ '''
+ # Visual Studio Code Debug Adaptors have no way to specify the file
+ # without launching or attaching to a process, so we must start a
+ # process in order to be able to set breakpoints.
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+
+ filters = ['cpp_throw', 'cpp_catch']
+ response = self.vscode.request_setExceptionBreakpoints(filters)
+ if response:
+ self.assertTrue(response['success'])
+
+ self.continue_to_exception_breakpoint('C++ Throw')
+ self.continue_to_exception_breakpoint('C++ Catch')
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py
new file mode 100644
index 000000000000..c7c67597c86b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/TestVSCode_setFunctionBreakpoints.py
@@ -0,0 +1,167 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import pprint
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+
+
+class TestVSCode_setFunctionBreakpoints(
+ lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # test hangs on linux under heavy load
+ @no_debug_info_test
+ def test_set_and_clear(self):
+ '''Tests setting and clearing function breakpoints.
+ This packet is a bit tricky on the debug adaptor side since there
+ is no "clearFunction Breakpoints" packet. Function breakpoints
+ are set by sending a "setFunctionBreakpoints" packet with zero or
+ more function names. If function breakpoints have been set before,
+ any exising breakpoints must remain set, and any new breakpoints
+ must be created, and any breakpoints that were in previous requests
+ and are not in the current request must be removed. This function
+ tests this setting and clearing and makes sure things happen
+ correctly. It doesn't test hitting breakpoints and the functionality
+ of each breakpoint, like 'conditions' and 'hitCondition' settings.
+ '''
+ # Visual Studio Code Debug Adaptors have no way to specify the file
+ # without launching or attaching to a process, so we must start a
+ # process in order to be able to set breakpoints.
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ bp_id_12 = None
+ functions = ['twelve']
+ # Set a function breakpoint at 'twelve'
+ response = self.vscode.request_setFunctionBreakpoints(functions)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(functions),
+ "expect %u source breakpoints" % (len(functions)))
+ for breakpoint in breakpoints:
+ bp_id_12 = breakpoint['id']
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint verified")
+
+ # Add an extra name and make sure we have two breakpoints after this
+ functions.append('thirteen')
+ response = self.vscode.request_setFunctionBreakpoints(functions)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(functions),
+ "expect %u source breakpoints" % (len(functions)))
+ for breakpoint in breakpoints:
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint verified")
+
+ # There is no breakpoint delete packet, clients just send another
+ # setFunctionBreakpoints packet with the different function names.
+ functions.remove('thirteen')
+ response = self.vscode.request_setFunctionBreakpoints(functions)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(functions),
+ "expect %u source breakpoints" % (len(functions)))
+ for breakpoint in breakpoints:
+ bp_id = breakpoint['id']
+ self.assertTrue(bp_id == bp_id_12,
+ 'verify "twelve" breakpoint ID is same')
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint still verified")
+
+ # Now get the full list of breakpoints set in the target and verify
+ # we have only 1 breakpoints set. The response above could have told
+ # us about 1 breakpoints, but we want to make sure we don't have the
+ # second one still set in the target
+ response = self.vscode.request_testGetTargetBreakpoints()
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(functions),
+ "expect %u source breakpoints" % (len(functions)))
+ for breakpoint in breakpoints:
+ bp_id = breakpoint['id']
+ self.assertTrue(bp_id == bp_id_12,
+ 'verify "twelve" breakpoint ID is same')
+ self.assertTrue(breakpoint['verified'],
+ "expect breakpoint still verified")
+
+ # Now clear all breakpoints for the source file by passing down an
+ # empty lines array
+ functions = []
+ response = self.vscode.request_setFunctionBreakpoints(functions)
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(functions),
+ "expect %u source breakpoints" % (len(functions)))
+
+ # Verify with the target that all breakpoints have been cleared
+ response = self.vscode.request_testGetTargetBreakpoints()
+ if response:
+ breakpoints = response['body']['breakpoints']
+ self.assertTrue(len(breakpoints) == len(functions),
+ "expect %u source breakpoints" % (len(functions)))
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_functionality(self):
+ '''Tests hitting breakpoints and the functionality of a single
+ breakpoint, like 'conditions' and 'hitCondition' settings.'''
+
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ # Set a breakpoint on "twelve" with no condition and no hitCondition
+ functions = ['twelve']
+ breakpoint_ids = self.set_function_breakpoints(functions)
+
+ self.assertTrue(len(breakpoint_ids) == len(functions),
+ "expect one breakpoint")
+
+ # Verify we hit the breakpoint we just set
+ self.continue_to_breakpoints(breakpoint_ids)
+
+ # Make sure i is zero at first breakpoint
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 0, 'i != 0 after hitting breakpoint')
+
+ # Update the condition on our breakpoint
+ new_breakpoint_ids = self.set_function_breakpoints(functions,
+ condition="i==4")
+ self.assertTrue(breakpoint_ids == new_breakpoint_ids,
+ "existing breakpoint should have its condition "
+ "updated")
+
+ self.continue_to_breakpoints(breakpoint_ids)
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 4,
+ 'i != 4 showing conditional works')
+ new_breakpoint_ids = self.set_function_breakpoints(functions,
+ hitCondition="2")
+
+ self.assertTrue(breakpoint_ids == new_breakpoint_ids,
+ "existing breakpoint should have its condition "
+ "updated")
+
+ # Continue with a hitContidtion of 2 and expect it to skip 1 value
+ self.continue_to_breakpoints(breakpoint_ids)
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 6,
+ 'i != 6 showing hitCondition works')
+
+ # continue after hitting our hitCondition and make sure it only goes
+ # up by 1
+ self.continue_to_breakpoints(breakpoint_ids)
+ i = int(self.vscode.get_local_variable_value('i'))
+ self.assertTrue(i == 7,
+ 'i != 7 showing post hitCondition hits every time')
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp
new file mode 100644
index 000000000000..e859b04e3a99
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/breakpoint/main.cpp
@@ -0,0 +1,27 @@
+#include <stdio.h>
+#include <stdexcept>
+
+int twelve(int i) {
+ return 12 + i; // break 12
+}
+
+int thirteen(int i) {
+ return 13 + i; // break 13
+}
+
+namespace a {
+ int fourteen(int i) {
+ return 14 + i; // break 14
+ }
+}
+int main(int argc, char const *argv[]) {
+ for (int i=0; i<10; ++i) {
+ int x = twelve(i) + thirteen(i) + a::fourteen(i); // break loop
+ }
+ try {
+ throw std::invalid_argument( "throwing exception for testing" );
+ } catch (...) {
+ puts("caught exception...");
+ }
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile
new file mode 100644
index 000000000000..b09a579159d4
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py
new file mode 100644
index 000000000000..064cf9a6783e
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/TestVSCode_launch.py
@@ -0,0 +1,352 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import pprint
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+import time
+
+
+class TestVSCode_launch(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_default(self):
+ '''
+ Tests the default launch of a simple program. No arguments,
+ environment, or anything else is specified.
+ '''
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ self.continue_to_exit()
+ # Now get the STDOUT and verify our program argument is correct
+ output = self.get_stdout()
+ self.assertTrue(output and len(output) > 0,
+ "expect program output")
+ lines = output.splitlines()
+ self.assertTrue(program in lines[0],
+ "make sure program path is in first argument")
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_stopOnEntry(self):
+ '''
+ Tests the default launch of a simple program that stops at the
+ entry point instead of continuing.
+ '''
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program, stopOnEntry=True)
+ self.set_function_breakpoints(['main'])
+ stopped_events = self.continue_to_next_stop()
+ for stopped_event in stopped_events:
+ if 'body' in stopped_event:
+ body = stopped_event['body']
+ if 'reason' in body:
+ reason = body['reason']
+ self.assertTrue(
+ reason != 'breakpoint',
+ 'verify stop isn\'t "main" breakpoint')
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_cwd(self):
+ '''
+ Tests the default launch of a simple program with a current working
+ directory.
+ '''
+ program = self.getBuildArtifact("a.out")
+ program_parent_dir = os.path.split(os.path.split(program)[0])[0]
+ self.build_and_launch(program,
+ cwd=program_parent_dir)
+ self.continue_to_exit()
+ # Now get the STDOUT and verify our program argument is correct
+ output = self.get_stdout()
+ self.assertTrue(output and len(output) > 0,
+ "expect program output")
+ lines = output.splitlines()
+ found = False
+ for line in lines:
+ if line.startswith('cwd = \"'):
+ quote_path = '"%s"' % (program_parent_dir)
+ found = True
+ self.assertTrue(quote_path in line,
+ "working directory '%s' not in '%s'" % (
+ program_parent_dir, line))
+ self.assertTrue(found, "verified program working directory")
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_debuggerRoot(self):
+ '''
+ Tests the "debuggerRoot" will change the working directory of
+ the lldb-vscode debug adaptor.
+ '''
+ program = self.getBuildArtifact("a.out")
+ program_parent_dir = os.path.split(os.path.split(program)[0])[0]
+ commands = ['platform shell echo cwd = $PWD']
+ self.build_and_launch(program,
+ debuggerRoot=program_parent_dir,
+ initCommands=commands)
+ output = self.get_console()
+ self.assertTrue(output and len(output) > 0,
+ "expect console output")
+ lines = output.splitlines()
+ prefix = 'cwd = '
+ found = False
+ for line in lines:
+ if line.startswith(prefix):
+ found = True
+ self.assertTrue(program_parent_dir == line[len(prefix):],
+ "lldb-vscode working dir '%s' == '%s'" % (
+ program_parent_dir, line[6:]))
+ self.assertTrue(found, "verified lldb-vscode working directory")
+ self.continue_to_exit()
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_sourcePath(self):
+ '''
+ Tests the "sourcePath" will set the target.source-map.
+ '''
+ program = self.getBuildArtifact("a.out")
+ program_dir = os.path.split(program)[0]
+ self.build_and_launch(program,
+ sourcePath=program_dir)
+ output = self.get_console()
+ self.assertTrue(output and len(output) > 0,
+ "expect console output")
+ lines = output.splitlines()
+ prefix = '(lldb) settings set target.source-map "." '
+ found = False
+ for line in lines:
+ if line.startswith(prefix):
+ found = True
+ quoted_path = '"%s"' % (program_dir)
+ self.assertTrue(quoted_path == line[len(prefix):],
+ "lldb-vscode working dir %s == %s" % (
+ quoted_path, line[6:]))
+ self.assertTrue(found, 'found "sourcePath" in console output')
+ self.continue_to_exit()
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_disableSTDIO(self):
+ '''
+ Tests the default launch of a simple program with STDIO disabled.
+ '''
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program,
+ disableSTDIO=True)
+ self.continue_to_exit()
+ # Now get the STDOUT and verify our program argument is correct
+ output = self.get_stdout()
+ self.assertTrue(output is None or len(output) == 0,
+ "expect no program output")
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_shellExpandArguments_enabled(self):
+ '''
+ Tests the default launch of a simple program with shell expansion
+ enabled.
+ '''
+ program = self.getBuildArtifact("a.out")
+ program_dir = os.path.split(program)[0]
+ glob = os.path.join(program_dir, '*.out')
+ self.build_and_launch(program, args=[glob], shellExpandArguments=True)
+ self.continue_to_exit()
+ # Now get the STDOUT and verify our program argument is correct
+ output = self.get_stdout()
+ self.assertTrue(output and len(output) > 0,
+ "expect no program output")
+ lines = output.splitlines()
+ for line in lines:
+ quote_path = '"%s"' % (program)
+ if line.startswith("arg[1] ="):
+ self.assertTrue(quote_path in line,
+ 'verify "%s" expanded to "%s"' % (
+ glob, program))
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_shellExpandArguments_disabled(self):
+ '''
+ Tests the default launch of a simple program with shell expansion
+ disabled.
+ '''
+ program = self.getBuildArtifact("a.out")
+ program_dir = os.path.split(program)[0]
+ glob = os.path.join(program_dir, '*.out')
+ self.build_and_launch(program,
+ args=[glob],
+ shellExpandArguments=False)
+ self.continue_to_exit()
+ # Now get the STDOUT and verify our program argument is correct
+ output = self.get_stdout()
+ self.assertTrue(output and len(output) > 0,
+ "expect no program output")
+ lines = output.splitlines()
+ for line in lines:
+ quote_path = '"%s"' % (glob)
+ if line.startswith("arg[1] ="):
+ self.assertTrue(quote_path in line,
+ 'verify "%s" stayed to "%s"' % (
+ glob, glob))
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_args(self):
+ '''
+ Tests launch of a simple program with arguments
+ '''
+ program = self.getBuildArtifact("a.out")
+ args = ["one", "with space", "'with single quotes'",
+ '"with double quotes"']
+ self.build_and_launch(program,
+ args=args)
+ self.continue_to_exit()
+
+ # Now get the STDOUT and verify our arguments got passed correctly
+ output = self.get_stdout()
+ self.assertTrue(output and len(output) > 0,
+ "expect program output")
+ lines = output.splitlines()
+ # Skip the first argument that contains the program name
+ lines.pop(0)
+ # Make sure arguments we specified are correct
+ for (i, arg) in enumerate(args):
+ quoted_arg = '"%s"' % (arg)
+ self.assertTrue(quoted_arg in lines[i],
+ 'arg[%i] "%s" not in "%s"' % (i+1, quoted_arg, lines[i]))
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_environment(self):
+ '''
+ Tests launch of a simple program with environment variables
+ '''
+ program = self.getBuildArtifact("a.out")
+ env = ["NO_VALUE", "WITH_VALUE=BAR", "EMPTY_VALUE=",
+ "SPACE=Hello World"]
+ self.build_and_launch(program,
+ env=env)
+ self.continue_to_exit()
+
+ # Now get the STDOUT and verify our arguments got passed correctly
+ output = self.get_stdout()
+ self.assertTrue(output and len(output) > 0,
+ "expect program output")
+ lines = output.splitlines()
+ # Skip the all arguments so we have only environment vars left
+ while len(lines) and lines[0].startswith("arg["):
+ lines.pop(0)
+ # Make sure each environment variable in "env" is actually set in the
+ # program environment that was printed to STDOUT
+ for var in env:
+ found = False
+ for program_var in lines:
+ if var in program_var:
+ found = True
+ break
+ self.assertTrue(found,
+ '"%s" must exist in program environment (%s)' % (
+ var, lines))
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @skipIfLinux # This test is timing out and/or failing on Linux as well as Darwin
+ @no_debug_info_test
+ def test_commands(self):
+ '''
+ Tests the "initCommands", "preRunCommands", "stopCommands" and
+ "exitCommands" that can be passed during launch.
+
+ "initCommands" are a list of LLDB commands that get executed
+ before the targt is created.
+ "preRunCommands" are a list of LLDB commands that get executed
+ after the target has been created and before the launch.
+ "stopCommands" are a list of LLDB commands that get executed each
+ time the program stops.
+ "exitCommands" are a list of LLDB commands that get executed when
+ the process exits
+ '''
+ program = self.getBuildArtifact("a.out")
+ initCommands = ['target list', 'platform list']
+ preRunCommands = ['image list a.out', 'image dump sections a.out']
+ stopCommands = ['frame variable', 'bt']
+ exitCommands = ['expr 2+3', 'expr 3+4']
+ self.build_and_launch(program,
+ initCommands=initCommands,
+ preRunCommands=preRunCommands,
+ stopCommands=stopCommands,
+ exitCommands=exitCommands)
+
+ # Get output from the console. This should contain both the
+ # "initCommands" and the "preRunCommands".
+ output = self.get_console()
+ # Verify all "initCommands" were found in console output
+ self.verify_commands('initCommands', output, initCommands)
+ # Verify all "preRunCommands" were found in console output
+ self.verify_commands('preRunCommands', output, preRunCommands)
+
+ source = 'main.c'
+ first_line = line_number(source, '// breakpoint 1')
+ second_line = line_number(source, '// breakpoint 2')
+ lines = [first_line, second_line]
+
+ # Set 2 breakoints so we can verify that "stopCommands" get run as the
+ # breakpoints get hit
+ breakpoint_ids = self.set_source_breakpoints(source, lines)
+ self.assertTrue(len(breakpoint_ids) == len(lines),
+ "expect correct number of breakpoints")
+
+ # Continue after launch and hit the first breakpoint.
+ # Get output from the console. This should contain both the
+ # "stopCommands" that were run after the first breakpoint was hit
+ self.continue_to_breakpoints(breakpoint_ids)
+ output = self.get_console(timeout=1.0)
+ self.verify_commands('stopCommands', output, stopCommands)
+
+ # Continue again and hit the second breakpoint.
+ # Get output from the console. This should contain both the
+ # "stopCommands" that were run after the second breakpoint was hit
+ self.continue_to_breakpoints(breakpoint_ids)
+ output = self.get_console(timeout=1.0)
+ self.verify_commands('stopCommands', output, stopCommands)
+
+ # Continue until the program exits
+ self.continue_to_exit()
+ # Get output from the console. This should contain both the
+ # "exitCommands" that were run after the second breakpoint was hit
+ output = self.get_console(timeout=1.0)
+ self.verify_commands('exitCommands', output, exitCommands)
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c
new file mode 100644
index 000000000000..aed2af9828f3
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/launch/main.c
@@ -0,0 +1,15 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char const *argv[], char const *envp[]) {
+ for (int i=0; i<argc; ++i)
+ printf("arg[%i] = \"%s\"\n", i, argv[i]);
+ for (int i=0; envp[i]; ++i)
+ printf("env[%i] = \"%s\"\n", i, envp[i]);
+ char *cwd = getcwd(NULL, 0);
+ printf("cwd = \"%s\"\n", cwd); // breakpoint 1
+ free(cwd);
+ cwd = NULL;
+ return 0; // breakpoint 2
+}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
new file mode 100644
index 000000000000..c66c6bb7af6b
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/lldbvscode_testcase.py
@@ -0,0 +1,288 @@
+from __future__ import print_function
+
+from lldbsuite.test.lldbtest import *
+import os
+import vscode
+
+
+class VSCodeTestCaseBase(TestBase):
+
+ def create_debug_adaptor(self):
+ '''Create the Visual Studio Code debug adaptor'''
+ self.assertTrue(os.path.exists(self.lldbVSCodeExec),
+ 'lldb-vscode must exist')
+ self.vscode = vscode.DebugAdaptor(executable=self.lldbVSCodeExec)
+
+ def build_and_create_debug_adaptor(self):
+ self.build()
+ self.create_debug_adaptor()
+
+ def set_source_breakpoints(self, source_path, lines, condition=None,
+ hitCondition=None):
+ '''Sets source breakpoints and returns an array of strings containing
+ the breakpoint location IDs ("1.1", "1.2") for each breakpoint
+ that was set.
+ '''
+ response = self.vscode.request_setBreakpoints(
+ source_path, lines, condition=condition, hitCondition=hitCondition)
+ if response is None:
+ return []
+ breakpoints = response['body']['breakpoints']
+ breakpoint_ids = []
+ for breakpoint in breakpoints:
+ response_id = breakpoint['id']
+ bp_id = response_id >> 32
+ bp_loc_id = response_id & 0xffffffff
+ breakpoint_ids.append('%i.%i' % (bp_id, bp_loc_id))
+ return breakpoint_ids
+
+ def set_function_breakpoints(self, functions, condition=None,
+ hitCondition=None):
+ '''Sets breakpoints by function name given an array of function names
+ and returns an array of strings containing the breakpoint location
+ IDs ("1.1", "1.2") for each breakpoint that was set.
+ '''
+ response = self.vscode.request_setFunctionBreakpoints(
+ functions, condition=condition, hitCondition=hitCondition)
+ if response is None:
+ return []
+ breakpoints = response['body']['breakpoints']
+ breakpoint_ids = []
+ for breakpoint in breakpoints:
+ response_id = breakpoint['id']
+ bp_id = response_id >> 32
+ bp_loc_id = response_id & 0xffffffff
+ breakpoint_ids.append('%i.%i' % (bp_id, bp_loc_id))
+ return breakpoint_ids
+
+ def verify_breakpoint_hit(self, breakpoint_ids):
+ '''Wait for the process we are debugging to stop, and verify we hit
+ any breakpoint location in the "breakpoint_ids" array.
+ "breakpoint_ids" should be a list of breakpoint location ID strings
+ (["1.1", "2.1"]). The return value from
+ self.set_source_breakpoints() can be passed to this function'''
+ stopped_events = self.vscode.wait_for_stopped()
+ for stopped_event in stopped_events:
+ if 'body' in stopped_event:
+ body = stopped_event['body']
+ if 'reason' not in body:
+ continue
+ if body['reason'] != 'breakpoint':
+ continue
+ if 'description' not in body:
+ continue
+ # Description is "breakpoint 1.1", so look for any location id
+ # ("1.1") in the description field as verification that one of
+ # the breakpoint locations was hit
+ description = body['description']
+ for breakpoint_id in breakpoint_ids:
+ if breakpoint_id in description:
+ return True
+ return False
+
+ def verify_exception_breakpoint_hit(self, filter_label):
+ '''Wait for the process we are debugging to stop, and verify the stop
+ reason is 'exception' and that the description matches
+ 'filter_label'
+ '''
+ stopped_events = self.vscode.wait_for_stopped()
+ for stopped_event in stopped_events:
+ if 'body' in stopped_event:
+ body = stopped_event['body']
+ if 'reason' not in body:
+ continue
+ if body['reason'] != 'exception':
+ continue
+ if 'description' not in body:
+ continue
+ description = body['description']
+ if filter_label == description:
+ return True
+ return False
+
+ def verify_commands(self, flavor, output, commands):
+ self.assertTrue(output and len(output) > 0, "expect console output")
+ lines = output.splitlines()
+ prefix = '(lldb) '
+ for cmd in commands:
+ found = False
+ for line in lines:
+ if line.startswith(prefix) and cmd in line:
+ found = True
+ break
+ self.assertTrue(found,
+ "verify '%s' found in console output for '%s'" % (
+ cmd, flavor))
+
+ def get_dict_value(self, d, key_path):
+ '''Verify each key in the key_path array is in contained in each
+ dictionary within "d". Assert if any key isn't in the
+ corresponding dictionary. This is handy for grabbing values from VS
+ Code response dictionary like getting
+ response['body']['stackFrames']
+ '''
+ value = d
+ for key in key_path:
+ if key in value:
+ value = value[key]
+ else:
+ self.assertTrue(key in value,
+ 'key "%s" from key_path "%s" not in "%s"' % (
+ key, key_path, d))
+ return value
+
+ def get_stackFrames(self, threadId=None, startFrame=None, levels=None,
+ dump=False):
+ response = self.vscode.request_stackTrace(threadId=threadId,
+ startFrame=startFrame,
+ levels=levels,
+ dump=dump)
+ if response:
+ return self.get_dict_value(response, ['body', 'stackFrames'])
+ return None
+
+ def get_source_and_line(self, threadId=None, frameIndex=0):
+ stackFrames = self.get_stackFrames(threadId=threadId,
+ startFrame=frameIndex,
+ levels=1)
+ if stackFrames is not None:
+ stackFrame = stackFrames[0]
+ ['source', 'path']
+ if 'source' in stackFrame:
+ source = stackFrame['source']
+ if 'path' in source:
+ if 'line' in stackFrame:
+ return (source['path'], stackFrame['line'])
+ return ('', 0)
+
+ def get_stdout(self, timeout=0.0):
+ return self.vscode.get_output('stdout', timeout=timeout)
+
+ def get_console(self, timeout=0.0):
+ return self.vscode.get_output('console', timeout=timeout)
+
+ def get_local_as_int(self, name, threadId=None):
+ value = self.vscode.get_local_variable_value(name, threadId=threadId)
+ if value.startswith('0x'):
+ return int(value, 16)
+ elif value.startswith('0'):
+ return int(value, 8)
+ else:
+ return int(value)
+
+ def set_local(self, name, value, id=None):
+ '''Set a top level local variable only.'''
+ return self.vscode.request_setVariable(1, name, str(value), id=id)
+
+ def set_global(self, name, value, id=None):
+ '''Set a top level global variable only.'''
+ return self.vscode.request_setVariable(2, name, str(value), id=id)
+
+ def stepIn(self, threadId=None, waitForStop=True):
+ self.vscode.request_stepIn(threadId=threadId)
+ if waitForStop:
+ return self.vscode.wait_for_stopped()
+ return None
+
+ def stepOver(self, threadId=None, waitForStop=True):
+ self.vscode.request_next(threadId=threadId)
+ if waitForStop:
+ return self.vscode.wait_for_stopped()
+ return None
+
+ def stepOut(self, threadId=None, waitForStop=True):
+ self.vscode.request_stepOut(threadId=threadId)
+ if waitForStop:
+ return self.vscode.wait_for_stopped()
+ return None
+
+ def continue_to_next_stop(self):
+ self.vscode.request_continue()
+ return self.vscode.wait_for_stopped()
+
+ def continue_to_breakpoints(self, breakpoint_ids):
+ self.vscode.request_continue()
+ self.verify_breakpoint_hit(breakpoint_ids)
+
+ def continue_to_exception_breakpoint(self, filter_label):
+ self.vscode.request_continue()
+ self.assertTrue(self.verify_exception_breakpoint_hit(filter_label),
+ 'verify we got "%s"' % (filter_label))
+
+ def continue_to_exit(self, exitCode=0):
+ self.vscode.request_continue()
+ stopped_events = self.vscode.wait_for_stopped()
+ self.assertTrue(len(stopped_events) == 1,
+ "expecting single 'exited' event")
+ self.assertTrue(stopped_events[0]['event'] == 'exited',
+ 'make sure program ran to completion')
+ self.assertTrue(stopped_events[0]['body']['exitCode'] == exitCode,
+ 'exitCode == %i' % (exitCode))
+
+ def attach(self, program=None, pid=None, waitFor=None, trace=None,
+ initCommands=None, preRunCommands=None, stopCommands=None,
+ exitCommands=None, attachCommands=None):
+ '''Build the default Makefile target, create the VSCode debug adaptor,
+ and attach to the process.
+ '''
+ # Make sure we disconnect and terminate the VSCode debug adaptor even
+ # if we throw an exception during the test case.
+ def cleanup():
+ self.vscode.request_disconnect(terminateDebuggee=True)
+ self.vscode.terminate()
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+ # Initialize and launch the program
+ self.vscode.request_initialize()
+ response = self.vscode.request_attach(
+ program=program, pid=pid, waitFor=waitFor, trace=trace,
+ initCommands=initCommands, preRunCommands=preRunCommands,
+ stopCommands=stopCommands, exitCommands=exitCommands,
+ attachCommands=attachCommands)
+ if not (response and response['success']):
+ self.assertTrue(response['success'],
+ 'attach failed (%s)' % (response['message']))
+
+ def build_and_launch(self, program, args=None, cwd=None, env=None,
+ stopOnEntry=False, disableASLR=True,
+ disableSTDIO=False, shellExpandArguments=False,
+ trace=False, initCommands=None, preRunCommands=None,
+ stopCommands=None, exitCommands=None,
+ sourcePath=None, debuggerRoot=None):
+ '''Build the default Makefile target, create the VSCode debug adaptor,
+ and launch the process.
+ '''
+ self.build_and_create_debug_adaptor()
+ self.assertTrue(os.path.exists(program), 'executable must exist')
+
+ # Make sure we disconnect and terminate the VSCode debug adaptor even
+ # if we throw an exception during the test case.
+ def cleanup():
+ self.vscode.request_disconnect(terminateDebuggee=True)
+ self.vscode.terminate()
+
+ # Execute the cleanup function during test case tear down.
+ self.addTearDownHook(cleanup)
+
+ # Initialize and launch the program
+ self.vscode.request_initialize()
+ response = self.vscode.request_launch(
+ program,
+ args=args,
+ cwd=cwd,
+ env=env,
+ stopOnEntry=stopOnEntry,
+ disableASLR=disableASLR,
+ disableSTDIO=disableSTDIO,
+ shellExpandArguments=shellExpandArguments,
+ trace=trace,
+ initCommands=initCommands,
+ preRunCommands=preRunCommands,
+ stopCommands=stopCommands,
+ exitCommands=exitCommands,
+ sourcePath=sourcePath,
+ debuggerRoot=debuggerRoot)
+ if not (response and response['success']):
+ self.assertTrue(response['success'],
+ 'launch failed (%s)' % (response['message']))
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile
new file mode 100644
index 000000000000..b09a579159d4
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py
new file mode 100644
index 000000000000..4bb061881c47
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/TestVSCode_stackTrace.py
@@ -0,0 +1,160 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+
+
+class TestVSCode_stackTrace(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+ name_key_path = ['name']
+ source_key_path = ['source', 'path']
+ line_key_path = ['line']
+
+ def verify_stackFrames(self, start_idx, stackFrames):
+ frame_idx = start_idx
+ for stackFrame in stackFrames:
+ # Don't care about frame above main
+ if frame_idx > 20:
+ return
+ self.verify_stackFrame(frame_idx, stackFrame)
+ frame_idx += 1
+
+ def verify_stackFrame(self, frame_idx, stackFrame):
+ frame_name = self.get_dict_value(stackFrame, self.name_key_path)
+ frame_source = self.get_dict_value(stackFrame, self.source_key_path)
+ frame_line = self.get_dict_value(stackFrame, self.line_key_path)
+ if frame_idx == 0:
+ expected_line = self.recurse_end
+ expected_name = 'recurse'
+ elif frame_idx < 20:
+ expected_line = self.recurse_call
+ expected_name = 'recurse'
+ else:
+ expected_line = self.recurse_invocation
+ expected_name = 'main'
+ self.assertTrue(frame_name == expected_name,
+ 'frame #%i name "%s" == "%s"' % (
+ frame_idx, frame_name, expected_name))
+ self.assertTrue(frame_source == self.source_path,
+ 'frame #%i source "%s" == "%s"' % (
+ frame_idx, frame_source, self.source_path))
+ self.assertTrue(frame_line == expected_line,
+ 'frame #%i line %i == %i' % (frame_idx, frame_line,
+ expected_line))
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_stackTrace(self):
+ '''
+ Tests the 'stackTrace' packet and all its variants.
+ '''
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = 'main.c'
+ self.source_path = os.path.join(os.getcwd(), source)
+ self.recurse_end = line_number(source, 'recurse end')
+ self.recurse_call = line_number(source, 'recurse call')
+ self.recurse_invocation = line_number(source, 'recurse invocation')
+
+ lines = [self.recurse_end]
+
+ # Set breakoint at a point of deepest recuusion
+ breakpoint_ids = self.set_source_breakpoints(source, lines)
+ self.assertTrue(len(breakpoint_ids) == len(lines),
+ "expect correct number of breakpoints")
+
+ self.continue_to_breakpoints(breakpoint_ids)
+ startFrame = 0
+ # Verify we get all stack frames with no arguments
+ stackFrames = self.get_stackFrames()
+ frameCount = len(stackFrames)
+ self.assertTrue(frameCount >= 20,
+ 'verify we get at least 20 frames for all frames')
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Verify all stack frames by specifying startFrame = 0 and levels not
+ # specified
+ stackFrames = self.get_stackFrames(startFrame=startFrame)
+ self.assertTrue(frameCount == len(stackFrames),
+ ('verify same number of frames with startFrame=%i') % (
+ startFrame))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Verify all stack frames by specifying startFrame = 0 and levels = 0
+ levels = 0
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(frameCount == len(stackFrames),
+ ('verify same number of frames with startFrame=%i and'
+ ' levels=%i') % (startFrame, levels))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Get only the first stack frame by sepcifying startFrame = 0 and
+ # levels = 1
+ levels = 1
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(levels == len(stackFrames),
+ ('verify one frame with startFrame=%i and'
+ ' levels=%i') % (startFrame, levels))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Get only the first 3 stack frames by sepcifying startFrame = 0 and
+ # levels = 3
+ levels = 3
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(levels == len(stackFrames),
+ ('verify %i frames with startFrame=%i and'
+ ' levels=%i') % (levels, startFrame, levels))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Get only the first 15 stack frames by sepcifying startFrame = 5 and
+ # levels = 16
+ startFrame = 5
+ levels = 16
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(levels == len(stackFrames),
+ ('verify %i frames with startFrame=%i and'
+ ' levels=%i') % (levels, startFrame, levels))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Verify we cap things correctly when we ask for too many frames
+ startFrame = 5
+ levels = 1000
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(len(stackFrames) == frameCount - startFrame,
+ ('verify less than 1000 frames with startFrame=%i and'
+ ' levels=%i') % (startFrame, levels))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Verify level=0 works with non-zerp start frame
+ startFrame = 5
+ levels = 0
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(len(stackFrames) == frameCount - startFrame,
+ ('verify less than 1000 frames with startFrame=%i and'
+ ' levels=%i') % (startFrame, levels))
+ self.verify_stackFrames(startFrame, stackFrames)
+
+ # Verify we get not frames when startFrame is too high
+ startFrame = 1000
+ levels = 1
+ stackFrames = self.get_stackFrames(startFrame=startFrame,
+ levels=levels)
+ self.assertTrue(0 == len(stackFrames),
+ 'verify zero frames with startFrame out of bounds')
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c
new file mode 100644
index 000000000000..85b41c492817
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/stackTrace/main.c
@@ -0,0 +1,13 @@
+#include <stdio.h>
+#include <unistd.h>
+
+int recurse(int x) {
+ if (x <= 1)
+ return 1; // recurse end
+ return recurse(x-1) + x; // recurse call
+}
+
+int main(int argc, char const *argv[]) {
+ recurse(20); // recurse invocation
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile
index 035413ff763d..f24bb9f4d267 100644
--- a/packages/Python/lldbsuite/test/functionalities/stop-hook/multiple_threads/Makefile
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/Makefile
@@ -1,6 +1,7 @@
LEVEL = ../../../make
-CXX_SOURCES := main.cpp
ENABLE_THREADS := YES
+CXX_SOURCES := main.cpp
+
include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py
new file mode 100644
index 000000000000..87ec71a513f6
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/TestVSCode_step.py
@@ -0,0 +1,79 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+
+
+class TestVSCode_step(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_step(self):
+ '''
+ Tests the stepping in/out/over in threads.
+ '''
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = 'main.cpp'
+ # source_path = os.path.join(os.getcwd(), source)
+ breakpoint1_line = line_number(source, '// breakpoint 1')
+ lines = [breakpoint1_line]
+ # Set breakoint in the thread function so we can step the threads
+ breakpoint_ids = self.set_source_breakpoints(source, lines)
+ self.assertTrue(len(breakpoint_ids) == len(lines),
+ "expect correct number of breakpoints")
+ self.continue_to_breakpoints(breakpoint_ids)
+ threads = self.vscode.get_threads()
+ for thread in threads:
+ if 'reason' in thread:
+ reason = thread['reason']
+ if reason == 'breakpoint':
+ # We have a thread that is stopped at our breakpoint.
+ # Get the value of "x" and get the source file and line.
+ # These will help us determine if we are stepping
+ # correctly. If we step a thread correctly we will verify
+ # the correct falue for x as it progresses through the
+ # program.
+ tid = thread['id']
+ x1 = self.get_local_as_int('x', threadId=tid)
+ (src1, line1) = self.get_source_and_line(threadId=tid)
+
+ # Now step into the "recurse()" function call again and
+ # verify, using the new value of "x" and the source file
+ # and line if we stepped correctly
+ self.stepIn(threadId=tid, waitForStop=True)
+ x2 = self.get_local_as_int('x', threadId=tid)
+ (src2, line2) = self.get_source_and_line(threadId=tid)
+ self.assertTrue(x1 == x2 + 1, 'verify step in variable')
+ self.assertTrue(line2 < line1, 'verify step in line')
+ self.assertTrue(src1 == src2, 'verify step in source')
+
+ # Now step out and verify
+ self.stepOut(threadId=tid, waitForStop=True)
+ x3 = self.get_local_as_int('x', threadId=tid)
+ (src3, line3) = self.get_source_and_line(threadId=tid)
+ self.assertTrue(x1 == x3, 'verify step out variable')
+ self.assertTrue(line3 >= line1, 'verify step out line')
+ self.assertTrue(src1 == src3, 'verify step in source')
+
+ # Step over and verify
+ self.stepOver(threadId=tid, waitForStop=True)
+ x4 = self.get_local_as_int('x', threadId=tid)
+ (src4, line4) = self.get_source_and_line(threadId=tid)
+ self.assertTrue(x4 == x3, 'verify step over variable')
+ self.assertTrue(line4 > line3, 'verify step over line')
+ self.assertTrue(src1 == src4, 'verify step over source')
+ # only step one thread that is at the breakpoint and stop
+ break
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp
new file mode 100644
index 000000000000..2fd063113875
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/step/main.cpp
@@ -0,0 +1,16 @@
+#include <thread>
+
+int function(int x) {
+ if ((x % 2) == 0)
+ return function(x-1) + x; // breakpoint 1
+ else
+ return x;
+}
+
+int main(int argc, char const *argv[]) {
+ std::thread thread1(function, 2);
+ std::thread thread2(function, 4);
+ thread1.join();
+ thread2.join();
+ return 0;
+}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile
new file mode 100644
index 000000000000..314f1cb2f077
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py
new file mode 100644
index 000000000000..0a8906f1c6c8
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/TestVSCode_variables.py
@@ -0,0 +1,225 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import os
+
+
+def make_buffer_verify_dict(start_idx, count, offset=0):
+ verify_dict = {}
+ for i in range(start_idx, start_idx + count):
+ verify_dict['[%i]' % (i)] = {'type': 'int', 'value': str(i+offset)}
+ return verify_dict
+
+
+class TestVSCode_variables(lldbvscode_testcase.VSCodeTestCaseBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def verify_values(self, verify_dict, actual, varref_dict=None):
+ if 'equals' in verify_dict:
+ verify = verify_dict['equals']
+ for key in verify:
+ verify_value = verify[key]
+ actual_value = actual[key]
+ self.assertTrue(verify_value == actual_value,
+ '"%s" keys don\'t match (%s != %s)' % (
+ key, actual_value, verify_value))
+ if 'startswith' in verify_dict:
+ verify = verify_dict['startswith']
+ for key in verify:
+ verify_value = verify[key]
+ actual_value = actual[key]
+ startswith = actual_value.startswith(verify_value)
+ self.assertTrue(startswith,
+ ('"%s" value "%s" doesn\'t start with'
+ ' "%s")') % (
+ key, actual_value,
+ verify_value))
+ hasVariablesReference = 'variablesReference' in actual
+ varRef = None
+ if hasVariablesReference:
+ # Remember variable references in case we want to test further
+ # by using the evaluate name.
+ varRef = actual['variablesReference']
+ if varRef != 0 and varref_dict is not None:
+ varref_dict[actual['evaluateName']] = varRef
+ if ('hasVariablesReference' in verify_dict and
+ verify_dict['hasVariablesReference']):
+ self.assertTrue(hasVariablesReference,
+ "verify variable reference")
+ if 'children' in verify_dict:
+ self.assertTrue(hasVariablesReference and varRef is not None and
+ varRef != 0,
+ ("children verify values specified for "
+ "variable without children"))
+
+ response = self.vscode.request_variables(varRef)
+ self.verify_variables(verify_dict['children'],
+ response['body']['variables'],
+ varref_dict)
+
+ def verify_variables(self, verify_dict, variables, varref_dict=None):
+ for variable in variables:
+ name = variable['name']
+ self.assertTrue(name in verify_dict,
+ 'variable "%s" in verify dictionary' % (name))
+ self.verify_values(verify_dict[name], variable, varref_dict)
+
+ @skipIfWindows
+ @skipIfDarwin # Skip this test for now until we can figure out why tings aren't working on build bots
+ @no_debug_info_test
+ def test_scopes_variables_setVariable_evaluate(self):
+ '''
+ Tests the "scopes", "variables", "setVariable", and "evaluate"
+ packets.
+ '''
+ program = self.getBuildArtifact("a.out")
+ self.build_and_launch(program)
+ source = 'main.cpp'
+ breakpoint1_line = line_number(source, '// breakpoint 1')
+ lines = [breakpoint1_line]
+ # Set breakoint in the thread function so we can step the threads
+ breakpoint_ids = self.set_source_breakpoints(source, lines)
+ self.assertTrue(len(breakpoint_ids) == len(lines),
+ "expect correct number of breakpoints")
+ self.continue_to_breakpoints(breakpoint_ids)
+ locals = self.vscode.get_local_variables()
+ globals = self.vscode.get_global_variables()
+ buffer_children = make_buffer_verify_dict(0, 32)
+ verify_locals = {
+ 'argc': {
+ 'equals': {'type': 'int', 'value': '1'}
+ },
+ 'argv': {
+ 'equals': {'type': 'const char **'},
+ 'startswith': {'value': '0x'},
+ 'hasVariablesReference': True
+ },
+ 'pt': {
+ 'equals': {'type': 'PointType'},
+ 'hasVariablesReference': True,
+ 'children': {
+ 'x': {'equals': {'type': 'int', 'value': '11'}},
+ 'y': {'equals': {'type': 'int', 'value': '22'}},
+ 'buffer': {'children': buffer_children}
+ }
+ }
+ }
+ verify_globals = {
+ 's_local': {
+ 'equals': {'type': 'float', 'value': '2.25'}
+ },
+ '::g_global': {
+ 'equals': {'type': 'int', 'value': '123'}
+ },
+ 's_global': {
+ 'equals': {'type': 'int', 'value': '234'}
+ },
+ }
+ varref_dict = {}
+ self.verify_variables(verify_locals, locals, varref_dict)
+ self.verify_variables(verify_globals, globals, varref_dict)
+ # pprint.PrettyPrinter(indent=4).pprint(varref_dict)
+ # We need to test the functionality of the "variables" request as it
+ # has optional parameters like "start" and "count" to limit the number
+ # of variables that are fetched
+ varRef = varref_dict['pt.buffer']
+ response = self.vscode.request_variables(varRef)
+ self.verify_variables(buffer_children, response['body']['variables'])
+ # Verify setting start=0 in the arguments still gets all children
+ response = self.vscode.request_variables(varRef, start=0)
+ self.verify_variables(buffer_children, response['body']['variables'])
+ # Verify setting count=0 in the arguments still gets all children.
+ # If count is zero, it means to get all children.
+ response = self.vscode.request_variables(varRef, count=0)
+ self.verify_variables(buffer_children, response['body']['variables'])
+ # Verify setting count to a value that is too large in the arguments
+ # still gets all children, and no more
+ response = self.vscode.request_variables(varRef, count=1000)
+ self.verify_variables(buffer_children, response['body']['variables'])
+ # Verify setting the start index and count gets only the children we
+ # want
+ response = self.vscode.request_variables(varRef, start=5, count=5)
+ self.verify_variables(make_buffer_verify_dict(5, 5),
+ response['body']['variables'])
+ # Verify setting the start index to a value that is out of range
+ # results in an empty list
+ response = self.vscode.request_variables(varRef, start=32, count=1)
+ self.assertTrue(len(response['body']['variables']) == 0,
+ 'verify we get no variable back for invalid start')
+
+ # Test evaluate
+ expressions = {
+ 'pt.x': {
+ 'equals': {'result': '11', 'type': 'int'},
+ 'hasVariablesReference': False
+ },
+ 'pt.buffer[2]': {
+ 'equals': {'result': '2', 'type': 'int'},
+ 'hasVariablesReference': False
+ },
+ 'pt': {
+ 'equals': {'type': 'PointType'},
+ 'startswith': {'result': 'PointType @ 0x'},
+ 'hasVariablesReference': True
+ },
+ 'pt.buffer': {
+ 'equals': {'type': 'int [32]'},
+ 'startswith': {'result': 'int [32] @ 0x'},
+ 'hasVariablesReference': True
+ },
+ 'argv': {
+ 'equals': {'type': 'const char **'},
+ 'startswith': {'result': '0x'},
+ 'hasVariablesReference': True
+ },
+ 'argv[0]': {
+ 'equals': {'type': 'const char *'},
+ 'startswith': {'result': '0x'},
+ 'hasVariablesReference': True
+ },
+ '2+3': {
+ 'equals': {'result': '5', 'type': 'int'},
+ 'hasVariablesReference': False
+ },
+ }
+ for expression in expressions:
+ response = self.vscode.request_evaluate(expression)
+ self.verify_values(expressions[expression], response['body'])
+
+ # Test setting variables
+ self.set_local('argc', 123)
+ argc = self.get_local_as_int('argc')
+ self.assertTrue(argc == 123,
+ 'verify argc was set to 123 (123 != %i)' % (argc))
+
+ self.set_local('argv', 0x1234)
+ argv = self.get_local_as_int('argv')
+ self.assertTrue(argv == 0x1234,
+ 'verify argv was set to 0x1234 (0x1234 != %#x)' % (
+ argv))
+
+ # Set a variable value whose name is synthetic, like a variable index
+ # and verify the value by reading it
+ self.vscode.request_setVariable(varRef, "[0]", 100)
+ response = self.vscode.request_variables(varRef, start=0, count=1)
+ self.verify_variables(make_buffer_verify_dict(0, 1, 100),
+ response['body']['variables'])
+
+ # Set a variable value whose name is a real child value, like "pt.x"
+ # and verify the value by reading it
+ varRef = varref_dict['pt']
+ self.vscode.request_setVariable(varRef, "x", 111)
+ response = self.vscode.request_variables(varRef, start=0, count=1)
+ value = response['body']['variables'][0]['value']
+ self.assertTrue(value == '111',
+ 'verify pt.x got set to 111 (111 != %s)' % (value))
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp
new file mode 100644
index 000000000000..0223bd0a75ea
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/variables/main.cpp
@@ -0,0 +1,18 @@
+
+#define BUFFER_SIZE 32
+struct PointType {
+ int x;
+ int y;
+ int buffer[BUFFER_SIZE];
+};
+
+int g_global = 123;
+static int s_global = 234;
+
+int main(int argc, char const *argv[]) {
+ static float s_local = 2.25;
+ PointType pt = { 11,22, {0}};
+ for (int i=0; i<BUFFER_SIZE; ++i)
+ pt.buffer[i] = i;
+ return s_global - g_global - pt.y; // breakpoint 1
+}
diff --git a/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py b/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
new file mode 100644
index 000000000000..066158d0877f
--- /dev/null
+++ b/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -0,0 +1,1084 @@
+#!/usr/bin/env python
+
+import binascii
+import json
+import optparse
+import os
+import pprint
+import socket
+import string
+import subprocess
+import sys
+import threading
+
+
+def dump_memory(base_addr, data, num_per_line, outfile):
+
+ data_len = len(data)
+ hex_string = binascii.hexlify(data)
+ addr = base_addr
+ ascii_str = ''
+ i = 0
+ while i < data_len:
+ outfile.write('0x%8.8x: ' % (addr + i))
+ bytes_left = data_len - i
+ if bytes_left >= num_per_line:
+ curr_data_len = num_per_line
+ else:
+ curr_data_len = bytes_left
+ hex_start_idx = i * 2
+ hex_end_idx = hex_start_idx + curr_data_len * 2
+ curr_hex_str = hex_string[hex_start_idx:hex_end_idx]
+ # 'curr_hex_str' now contains the hex byte string for the
+ # current line with no spaces between bytes
+ t = iter(curr_hex_str)
+ # Print hex bytes separated by space
+ outfile.write(' '.join(a + b for a, b in zip(t, t)))
+ # Print two spaces
+ outfile.write(' ')
+ # Calculate ASCII string for bytes into 'ascii_str'
+ ascii_str = ''
+ for j in range(i, i + curr_data_len):
+ ch = data[j]
+ if ch in string.printable and ch not in string.whitespace:
+ ascii_str += '%c' % (ch)
+ else:
+ ascii_str += '.'
+ # Print ASCII representation and newline
+ outfile.write(ascii_str)
+ i = i + curr_data_len
+ outfile.write('\n')
+
+
+def read_packet(f, verbose=False, trace_file=None):
+ '''Decode a JSON packet that starts with the content length and is
+ followed by the JSON bytes from a file 'f'
+ '''
+ line = f.readline()
+ if len(line) == 0:
+ return None
+
+ # Watch for line that starts with the prefix
+ prefix = 'Content-Length: '
+ if line.startswith(prefix):
+ # Decode length of JSON bytes
+ if verbose:
+ print('content: "%s"' % (line))
+ length = int(line[len(prefix):])
+ if verbose:
+ print('length: "%u"' % (length))
+ # Skip empty line
+ line = f.readline()
+ if verbose:
+ print('empty: "%s"' % (line))
+ # Read JSON bytes
+ json_str = f.read(length)
+ if verbose:
+ print('json: "%s"' % (json_str))
+ if trace_file:
+ trace_file.write('from adaptor:\n%s\n' % (json_str))
+ # Decode the JSON bytes into a python dictionary
+ return json.loads(json_str)
+
+ return None
+
+
+def packet_type_is(packet, packet_type):
+ return 'type' in packet and packet['type'] == packet_type
+
+
+def read_packet_thread(vs_comm):
+ done = False
+ while not done:
+ packet = read_packet(vs_comm.recv, trace_file=vs_comm.trace_file)
+ if packet:
+ done = not vs_comm.handle_recv_packet(packet)
+ else:
+ done = True
+
+
+class DebugCommunication(object):
+
+ def __init__(self, recv, send):
+ self.trace_file = None
+ self.send = send
+ self.recv = recv
+ self.recv_packets = []
+ self.recv_condition = threading.Condition()
+ self.recv_thread = threading.Thread(target=read_packet_thread,
+ args=(self,))
+ self.process_event_body = None
+ self.exit_status = None
+ self.initialize_body = None
+ self.thread_stop_reasons = {}
+ self.sequence = 1
+ self.threads = None
+ self.recv_thread.start()
+ self.output_condition = threading.Condition()
+ self.output = {}
+ self.configuration_done_sent = False
+ self.frame_scopes = {}
+
+ @classmethod
+ def encode_content(cls, s):
+ return "Content-Length: %u\r\n\r\n%s" % (len(s), s)
+
+ @classmethod
+ def validate_response(cls, command, response):
+ if command['command'] != response['command']:
+ raise ValueError('command mismatch in response')
+ if command['seq'] != response['request_seq']:
+ raise ValueError('seq mismatch in response')
+
+ def get_output(self, category, timeout=0.0, clear=True):
+ self.output_condition.acquire()
+ output = None
+ if category in self.output:
+ output = self.output[category]
+ if clear:
+ del self.output[category]
+ elif timeout != 0.0:
+ self.output_condition.wait(timeout)
+ if category in self.output:
+ output = self.output[category]
+ if clear:
+ del self.output[category]
+ self.output_condition.release()
+ return output
+
+ def handle_recv_packet(self, packet):
+ '''Called by the read thread that is waiting for all incoming packets
+ to store the incoming packet in "self.recv_packets" in a thread safe
+ way. This function will then signal the "self.recv_condition" to
+ indicate a new packet is available. Returns True if the caller
+ should keep calling this function for more packets.
+ '''
+ # Check the packet to see if is an event packet
+ keepGoing = True
+ packet_type = packet['type']
+ if packet_type == 'event':
+ event = packet['event']
+ body = None
+ if 'body' in packet:
+ body = packet['body']
+ # Handle the event packet and cache information from these packets
+ # as they come in
+ if event == 'output':
+ # Store any output we receive so clients can retrieve it later.
+ category = body['category']
+ output = body['output']
+ self.output_condition.acquire()
+ if category in self.output:
+ self.output[category] += output
+ else:
+ self.output[category] = output
+ self.output_condition.notify()
+ self.output_condition.release()
+ # no need to add 'output' packets to our packets list
+ return keepGoing
+ elif event == 'process':
+ # When a new process is attached or launched, remember the
+ # details that are available in the body of the event
+ self.process_event_body = body
+ elif event == 'stopped':
+ # Each thread that stops with a reason will send a
+ # 'stopped' event. We need to remember the thread stop
+ # reasons since the 'threads' command doesn't return
+ # that information.
+ self._process_stopped()
+ tid = body['threadId']
+ self.thread_stop_reasons[tid] = body
+ elif packet_type == 'response':
+ if packet['command'] == 'disconnect':
+ keepGoing = False
+ self.recv_condition.acquire()
+ self.recv_packets.append(packet)
+ self.recv_condition.notify()
+ self.recv_condition.release()
+ return keepGoing
+
+ def send_packet(self, command_dict, set_sequence=True):
+ '''Take the "command_dict" python dictionary and encode it as a JSON
+ string and send the contents as a packet to the VSCode debug
+ adaptor'''
+ # Set the sequence ID for this command automatically
+ if set_sequence:
+ command_dict['seq'] = self.sequence
+ self.sequence += 1
+ # Encode our command dictionary as a JSON string
+ json_str = json.dumps(command_dict, separators=(',', ':'))
+ if self.trace_file:
+ self.trace_file.write('to adaptor:\n%s\n' % (json_str))
+ length = len(json_str)
+ if length > 0:
+ # Send the encoded JSON packet and flush the 'send' file
+ self.send.write(self.encode_content(json_str))
+ self.send.flush()
+
+ def recv_packet(self, filter_type=None, filter_event=None, timeout=None):
+ '''Get a JSON packet from the VSCode debug adaptor. This function
+ assumes a thread that reads packets is running and will deliver
+ any received packets by calling handle_recv_packet(...). This
+ function will wait for the packet to arrive and return it when
+ it does.'''
+ while True:
+ self.recv_condition.acquire()
+ packet = None
+ while True:
+ for (i, curr_packet) in enumerate(self.recv_packets):
+ packet_type = curr_packet['type']
+ if filter_type is None or packet_type in filter_type:
+ if (filter_event is None or
+ (packet_type == 'event' and
+ curr_packet['event'] in filter_event)):
+ packet = self.recv_packets.pop(i)
+ break
+ if packet:
+ break
+ # Sleep until packet is received
+ len_before = len(self.recv_packets)
+ self.recv_condition.wait(timeout)
+ len_after = len(self.recv_packets)
+ if len_before == len_after:
+ return None # Timed out
+ self.recv_condition.release()
+ return packet
+
+ return None
+
+ def send_recv(self, command):
+ '''Send a command python dictionary as JSON and receive the JSON
+ response. Validates that the response is the correct sequence and
+ command in the reply. Any events that are received are added to the
+ events list in this object'''
+ self.send_packet(command)
+ done = False
+ while not done:
+ response = self.recv_packet(filter_type='response')
+ if response is None:
+ desc = 'no response for "%s"' % (command['command'])
+ raise ValueError(desc)
+ self.validate_response(command, response)
+ return response
+ return None
+
+ def wait_for_event(self, filter=None, timeout=None):
+ while True:
+ return self.recv_packet(filter_type='event', filter_event=filter,
+ timeout=timeout)
+ return None
+
+ def wait_for_stopped(self, timeout=None):
+ stopped_events = []
+ stopped_event = self.wait_for_event(filter=['stopped', 'exited'],
+ timeout=timeout)
+ exited = False
+ while stopped_event:
+ stopped_events.append(stopped_event)
+ # If we exited, then we are done
+ if stopped_event['event'] == 'exited':
+ self.exit_status = stopped_event['body']['exitCode']
+ exited = True
+ break
+ # Otherwise we stopped and there might be one or more 'stopped'
+ # events for each thread that stopped with a reason, so keep
+ # checking for more 'stopped' events and return all of them
+ stopped_event = self.wait_for_event(filter='stopped', timeout=0.25)
+ if exited:
+ self.threads = []
+ return stopped_events
+
+ def wait_for_exited(self):
+ event_dict = self.wait_for_event('exited')
+ if event_dict is None:
+ raise ValueError("didn't get stopped event")
+ return event_dict
+
+ def get_initialize_value(self, key):
+ '''Get a value for the given key if it there is a key/value pair in
+ the "initialize" request response body.
+ '''
+ if self.initialize_body and key in self.initialize_body:
+ return self.initialize_body[key]
+ return None
+
+ def get_threads(self):
+ if self.threads is None:
+ self.request_threads()
+ return self.threads
+
+ def get_thread_id(self, threadIndex=0):
+ '''Utility function to get the first thread ID in the thread list.
+ If the thread list is empty, then fetch the threads.
+ '''
+ if self.threads is None:
+ self.request_threads()
+ if self.threads and threadIndex < len(self.threads):
+ return self.threads[threadIndex]['id']
+ return None
+
+ def get_stackFrame(self, frameIndex=0, threadId=None):
+ '''Get a single "StackFrame" object from a "stackTrace" request and
+ return the "StackFrame as a python dictionary, or None on failure
+ '''
+ if threadId is None:
+ threadId = self.get_thread_id()
+ if threadId is None:
+ print('invalid threadId')
+ return None
+ response = self.request_stackTrace(threadId, startFrame=frameIndex,
+ levels=1)
+ if response:
+ return response['body']['stackFrames'][0]
+ print('invalid response')
+ return None
+
+ def get_scope_variables(self, scope_name, frameIndex=0, threadId=None):
+ stackFrame = self.get_stackFrame(frameIndex=frameIndex,
+ threadId=threadId)
+ if stackFrame is None:
+ return []
+ frameId = stackFrame['id']
+ if frameId in self.frame_scopes:
+ frame_scopes = self.frame_scopes[frameId]
+ else:
+ scopes_response = self.request_scopes(frameId)
+ frame_scopes = scopes_response['body']['scopes']
+ self.frame_scopes[frameId] = frame_scopes
+ for scope in frame_scopes:
+ if scope['name'] == scope_name:
+ varRef = scope['variablesReference']
+ variables_response = self.request_variables(varRef)
+ if variables_response:
+ if 'body' in variables_response:
+ body = variables_response['body']
+ if 'variables' in body:
+ vars = body['variables']
+ return vars
+ return []
+
+ def get_global_variables(self, frameIndex=0, threadId=None):
+ return self.get_scope_variables('Globals', frameIndex=frameIndex,
+ threadId=threadId)
+
+ def get_local_variables(self, frameIndex=0, threadId=None):
+ return self.get_scope_variables('Locals', frameIndex=frameIndex,
+ threadId=threadId)
+
+ def get_local_variable(self, name, frameIndex=0, threadId=None):
+ locals = self.get_local_variables(frameIndex=frameIndex,
+ threadId=threadId)
+ for local in locals:
+ if 'name' in local and local['name'] == name:
+ return local
+ return None
+
+ def get_local_variable_value(self, name, frameIndex=0, threadId=None):
+ variable = self.get_local_variable(name, frameIndex=frameIndex,
+ threadId=threadId)
+ if variable and 'value' in variable:
+ return variable['value']
+ return None
+
+ def replay_packets(self, replay_file_path):
+ f = open(replay_file_path, 'r')
+ mode = 'invalid'
+ set_sequence = False
+ command_dict = None
+ while mode != 'eof':
+ if mode == 'invalid':
+ line = f.readline()
+ if line.startswith('to adapter:'):
+ mode = 'send'
+ elif line.startswith('from adapter:'):
+ mode = 'recv'
+ elif mode == 'send':
+ command_dict = read_packet(f)
+ # Skip the end of line that follows the JSON
+ f.readline()
+ if command_dict is None:
+ raise ValueError('decode packet failed from replay file')
+ print('Sending:')
+ pprint.PrettyPrinter(indent=2).pprint(command_dict)
+ # raw_input('Press ENTER to send:')
+ self.send_packet(command_dict, set_sequence)
+ mode = 'invalid'
+ elif mode == 'recv':
+ print('Replay response:')
+ replay_response = read_packet(f)
+ # Skip the end of line that follows the JSON
+ f.readline()
+ pprint.PrettyPrinter(indent=2).pprint(replay_response)
+ actual_response = self.recv_packet()
+ if actual_response:
+ type = actual_response['type']
+ print('Actual response:')
+ if type == 'response':
+ self.validate_response(command_dict, actual_response)
+ pprint.PrettyPrinter(indent=2).pprint(actual_response)
+ else:
+ print("error: didn't get a valid response")
+ mode = 'invalid'
+
+ def request_attach(self, program=None, pid=None, waitFor=None, trace=None,
+ initCommands=None, preRunCommands=None,
+ stopCommands=None, exitCommands=None,
+ attachCommands=None):
+ args_dict = {}
+ if pid is not None:
+ args_dict['pid'] = pid
+ if program is not None:
+ args_dict['program'] = program
+ if waitFor is not None:
+ args_dict['waitFor'] = waitFor
+ if trace:
+ args_dict['trace'] = trace
+ if initCommands:
+ args_dict['initCommands'] = initCommands
+ if preRunCommands:
+ args_dict['preRunCommands'] = preRunCommands
+ if stopCommands:
+ args_dict['stopCommands'] = stopCommands
+ if exitCommands:
+ args_dict['exitCommands'] = exitCommands
+ if attachCommands:
+ args_dict['attachCommands'] = attachCommands
+ command_dict = {
+ 'command': 'attach',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_configurationDone(self):
+ command_dict = {
+ 'command': 'configurationDone',
+ 'type': 'request',
+ 'arguments': {}
+ }
+ response = self.send_recv(command_dict)
+ if response:
+ self.configuration_done_sent = True
+ return response
+
+ def _process_stopped(self):
+ self.threads = None
+ self.frame_scopes = {}
+
+ def request_continue(self, threadId=None):
+ if self.exit_status is not None:
+ raise ValueError('request_continue called after process exited')
+ # If we have launched or attached, then the first continue is done by
+ # sending the 'configurationDone' request
+ if not self.configuration_done_sent:
+ return self.request_configurationDone()
+ args_dict = {}
+ if threadId is None:
+ threadId = self.get_thread_id()
+ args_dict['threadId'] = threadId
+ command_dict = {
+ 'command': 'continue',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ response = self.send_recv(command_dict)
+ recv_packets = []
+ self.recv_condition.acquire()
+ for event in self.recv_packets:
+ if event['event'] != 'stopped':
+ recv_packets.append(event)
+ self.recv_packets = recv_packets
+ self.recv_condition.release()
+ return response
+
+ def request_disconnect(self, terminateDebuggee=None):
+ args_dict = {}
+ if terminateDebuggee is not None:
+ if terminateDebuggee:
+ args_dict['terminateDebuggee'] = True
+ else:
+ args_dict['terminateDebuggee'] = False
+ command_dict = {
+ 'command': 'disconnect',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_evaluate(self, expression, frameIndex=0, threadId=None):
+ stackFrame = self.get_stackFrame(frameIndex=frameIndex,
+ threadId=threadId)
+ if stackFrame is None:
+ return []
+ args_dict = {
+ 'expression': expression,
+ 'frameId': stackFrame['id'],
+ }
+ command_dict = {
+ 'command': 'evaluate',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_initialize(self):
+ command_dict = {
+ 'command': 'initialize',
+ 'type': 'request',
+ 'arguments': {
+ 'adapterID': 'lldb-native',
+ 'clientID': 'vscode',
+ 'columnsStartAt1': True,
+ 'linesStartAt1': True,
+ 'locale': 'en-us',
+ 'pathFormat': 'path',
+ 'supportsRunInTerminalRequest': True,
+ 'supportsVariablePaging': True,
+ 'supportsVariableType': True
+ }
+ }
+ response = self.send_recv(command_dict)
+ if response:
+ if 'body' in response:
+ self.initialize_body = response['body']
+ return response
+
+ def request_launch(self, program, args=None, cwd=None, env=None,
+ stopOnEntry=False, disableASLR=True,
+ disableSTDIO=False, shellExpandArguments=False,
+ trace=False, initCommands=None, preRunCommands=None,
+ stopCommands=None, exitCommands=None, sourcePath=None,
+ debuggerRoot=None):
+ args_dict = {
+ 'program': program
+ }
+ if args:
+ args_dict['args'] = args
+ if cwd:
+ args_dict['cwd'] = cwd
+ if env:
+ args_dict['env'] = env
+ if stopOnEntry:
+ args_dict['stopOnEntry'] = stopOnEntry
+ if disableASLR:
+ args_dict['disableASLR'] = disableASLR
+ if disableSTDIO:
+ args_dict['disableSTDIO'] = disableSTDIO
+ if shellExpandArguments:
+ args_dict['shellExpandArguments'] = shellExpandArguments
+ if trace:
+ args_dict['trace'] = trace
+ if initCommands:
+ args_dict['initCommands'] = initCommands
+ if preRunCommands:
+ args_dict['preRunCommands'] = preRunCommands
+ if stopCommands:
+ args_dict['stopCommands'] = stopCommands
+ if exitCommands:
+ args_dict['exitCommands'] = exitCommands
+ if sourcePath:
+ args_dict['sourcePath'] = sourcePath
+ if debuggerRoot:
+ args_dict['debuggerRoot'] = debuggerRoot
+ command_dict = {
+ 'command': 'launch',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ response = self.send_recv(command_dict)
+
+ # Wait for a 'process' and 'initialized' event in any order
+ self.wait_for_event(filter=['process', 'initialized'])
+ self.wait_for_event(filter=['process', 'initialized'])
+ return response
+
+ def request_next(self, threadId):
+ if self.exit_status is not None:
+ raise ValueError('request_continue called after process exited')
+ args_dict = {'threadId': threadId}
+ command_dict = {
+ 'command': 'next',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_stepIn(self, threadId):
+ if self.exit_status is not None:
+ raise ValueError('request_continue called after process exited')
+ args_dict = {'threadId': threadId}
+ command_dict = {
+ 'command': 'stepIn',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_stepOut(self, threadId):
+ if self.exit_status is not None:
+ raise ValueError('request_continue called after process exited')
+ args_dict = {'threadId': threadId}
+ command_dict = {
+ 'command': 'stepOut',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_pause(self, threadId=None):
+ if self.exit_status is not None:
+ raise ValueError('request_continue called after process exited')
+ if threadId is None:
+ threadId = self.get_thread_id()
+ args_dict = {'threadId': threadId}
+ command_dict = {
+ 'command': 'pause',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_scopes(self, frameId):
+ args_dict = {'frameId': frameId}
+ command_dict = {
+ 'command': 'scopes',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_setBreakpoints(self, file_path, line_array, condition=None,
+ hitCondition=None):
+ (dir, base) = os.path.split(file_path)
+ breakpoints = []
+ for line in line_array:
+ bp = {'line': line}
+ if condition is not None:
+ bp['condition'] = condition
+ if hitCondition is not None:
+ bp['hitCondition'] = hitCondition
+ breakpoints.append(bp)
+ source_dict = {
+ 'name': base,
+ 'path': file_path
+ }
+ args_dict = {
+ 'source': source_dict,
+ 'breakpoints': breakpoints,
+ 'lines': '%s' % (line_array),
+ 'sourceModified': False,
+ }
+ command_dict = {
+ 'command': 'setBreakpoints',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_setExceptionBreakpoints(self, filters):
+ args_dict = {'filters': filters}
+ command_dict = {
+ 'command': 'setExceptionBreakpoints',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_setFunctionBreakpoints(self, names, condition=None,
+ hitCondition=None):
+ breakpoints = []
+ for name in names:
+ bp = {'name': name}
+ if condition is not None:
+ bp['condition'] = condition
+ if hitCondition is not None:
+ bp['hitCondition'] = hitCondition
+ breakpoints.append(bp)
+ args_dict = {'breakpoints': breakpoints}
+ command_dict = {
+ 'command': 'setFunctionBreakpoints',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_stackTrace(self, threadId=None, startFrame=None, levels=None,
+ dump=False):
+ if threadId is None:
+ threadId = self.get_thread_id()
+ args_dict = {'threadId': threadId}
+ if startFrame is not None:
+ args_dict['startFrame'] = startFrame
+ if levels is not None:
+ args_dict['levels'] = levels
+ command_dict = {
+ 'command': 'stackTrace',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ response = self.send_recv(command_dict)
+ if dump:
+ for (idx, frame) in enumerate(response['body']['stackFrames']):
+ name = frame['name']
+ if 'line' in frame and 'source' in frame:
+ source = frame['source']
+ if 'sourceReference' not in source:
+ if 'name' in source:
+ source_name = source['name']
+ line = frame['line']
+ print("[%3u] %s @ %s:%u" % (idx, name, source_name,
+ line))
+ continue
+ print("[%3u] %s" % (idx, name))
+ return response
+
+ def request_threads(self):
+ '''Request a list of all threads and combine any information from any
+ "stopped" events since those contain more information about why a
+ thread actually stopped. Returns an array of thread dictionaries
+ with information about all threads'''
+ command_dict = {
+ 'command': 'threads',
+ 'type': 'request',
+ 'arguments': {}
+ }
+ response = self.send_recv(command_dict)
+ body = response['body']
+ # Fill in "self.threads" correctly so that clients that call
+ # self.get_threads() or self.get_thread_id(...) can get information
+ # on threads when the process is stopped.
+ if 'threads' in body:
+ self.threads = body['threads']
+ for thread in self.threads:
+ # Copy the thread dictionary so we can add key/value pairs to
+ # it without affecfting the original info from the "threads"
+ # command.
+ tid = thread['id']
+ if tid in self.thread_stop_reasons:
+ thread_stop_info = self.thread_stop_reasons[tid]
+ copy_keys = ['reason', 'description', 'text']
+ for key in copy_keys:
+ if key in thread_stop_info:
+ thread[key] = thread_stop_info[key]
+ else:
+ self.threads = None
+ return response
+
+ def request_variables(self, variablesReference, start=None, count=None):
+ args_dict = {'variablesReference': variablesReference}
+ if start is not None:
+ args_dict['start'] = start
+ if count is not None:
+ args_dict['count'] = count
+ command_dict = {
+ 'command': 'variables',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_setVariable(self, containingVarRef, name, value, id=None):
+ args_dict = {
+ 'variablesReference': containingVarRef,
+ 'name': name,
+ 'value': str(value)
+ }
+ if id is not None:
+ args_dict['id'] = id
+ command_dict = {
+ 'command': 'setVariable',
+ 'type': 'request',
+ 'arguments': args_dict
+ }
+ return self.send_recv(command_dict)
+
+ def request_testGetTargetBreakpoints(self):
+ '''A request packet used in the LLDB test suite to get all currently
+ set breakpoint infos for all breakpoints currently set in the
+ target.
+ '''
+ command_dict = {
+ 'command': '_testGetTargetBreakpoints',
+ 'type': 'request',
+ 'arguments': {}
+ }
+ return self.send_recv(command_dict)
+
+ def terminate(self):
+ self.send.close()
+ # self.recv.close()
+
+
+class DebugAdaptor(DebugCommunication):
+ def __init__(self, executable=None, port=None):
+ self.process = None
+ if executable is not None:
+ self.process = subprocess.Popen([executable],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ DebugCommunication.__init__(self, self.process.stdout,
+ self.process.stdin)
+ elif port is not None:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(('127.0.0.1', port))
+ DebugCommunication.__init__(self, s.makefile('r'), s.makefile('w'))
+
+ def get_pid(self):
+ if self.process:
+ return self.process.pid
+ return -1
+
+ def terminate(self):
+ super(DebugAdaptor, self).terminate()
+ if self.process is not None:
+ self.process.terminate()
+ self.process.wait()
+ self.process = None
+
+
+def attach_options_specified(options):
+ if options.pid is not None:
+ return True
+ if options.waitFor:
+ return True
+ if options.attach:
+ return True
+ if options.attachCmds:
+ return True
+ return False
+
+
+def run_vscode(dbg, args, options):
+ dbg.request_initialize()
+ if attach_options_specified(options):
+ response = dbg.request_attach(program=options.program,
+ pid=options.pid,
+ waitFor=options.waitFor,
+ attachCommands=options.attachCmds,
+ initCommands=options.initCmds,
+ preRunCommands=options.preRunCmds,
+ stopCommands=options.stopCmds,
+ exitCommands=options.exitCmds)
+ else:
+ response = dbg.request_launch(options.program,
+ args=args,
+ env=options.envs,
+ cwd=options.workingDir,
+ debuggerRoot=options.debuggerRoot,
+ sourcePath=options.sourcePath,
+ initCommands=options.initCmds,
+ preRunCommands=options.preRunCmds,
+ stopCommands=options.stopCmds,
+ exitCommands=options.exitCmds)
+
+ if response['success']:
+ if options.sourceBreakpoints:
+ source_to_lines = {}
+ for file_line in options.sourceBreakpoints:
+ (path, line) = file_line.split(':')
+ if len(path) == 0 or len(line) == 0:
+ print('error: invalid source with line "%s"' %
+ (file_line))
+
+ else:
+ if path in source_to_lines:
+ source_to_lines[path].append(int(line))
+ else:
+ source_to_lines[path] = [int(line)]
+ for source in source_to_lines:
+ dbg.request_setBreakpoints(source, source_to_lines[source])
+ if options.funcBreakpoints:
+ dbg.request_setFunctionBreakpoints(options.funcBreakpoints)
+ dbg.request_configurationDone()
+ dbg.wait_for_stopped()
+ else:
+ if 'message' in response:
+ print(response['message'])
+ dbg.request_disconnect(terminateDebuggee=True)
+
+
+def main():
+ parser = optparse.OptionParser(
+ description=('A testing framework for the Visual Studio Code Debug '
+ 'Adaptor protocol'))
+
+ parser.add_option(
+ '--vscode',
+ type='string',
+ dest='vscode_path',
+ help=('The path to the command line program that implements the '
+ 'Visual Studio Code Debug Adaptor protocol.'),
+ default=None)
+
+ parser.add_option(
+ '--program',
+ type='string',
+ dest='program',
+ help='The path to the program to debug.',
+ default=None)
+
+ parser.add_option(
+ '--workingDir',
+ type='string',
+ dest='workingDir',
+ default=None,
+ help='Set the working directory for the process we launch.')
+
+ parser.add_option(
+ '--sourcePath',
+ type='string',
+ dest='sourcePath',
+ default=None,
+ help=('Set the relative source root for any debug info that has '
+ 'relative paths in it.'))
+
+ parser.add_option(
+ '--debuggerRoot',
+ type='string',
+ dest='debuggerRoot',
+ default=None,
+ help=('Set the working directory for lldb-vscode for any object files '
+ 'with relative paths in the Mach-o debug map.'))
+
+ parser.add_option(
+ '-r', '--replay',
+ type='string',
+ dest='replay',
+ help=('Specify a file containing a packet log to replay with the '
+ 'current Visual Studio Code Debug Adaptor executable.'),
+ default=None)
+
+ parser.add_option(
+ '-g', '--debug',
+ action='store_true',
+ dest='debug',
+ default=False,
+ help='Pause waiting for a debugger to attach to the debug adaptor')
+
+ parser.add_option(
+ '--port',
+ type='int',
+ dest='port',
+ help="Attach a socket to a port instead of using STDIN for VSCode",
+ default=None)
+
+ parser.add_option(
+ '--pid',
+ type='int',
+ dest='pid',
+ help="The process ID to attach to",
+ default=None)
+
+ parser.add_option(
+ '--attach',
+ action='store_true',
+ dest='attach',
+ default=False,
+ help=('Specify this option to attach to a process by name. The '
+ 'process name is the basanme of the executable specified with '
+ 'the --program option.'))
+
+ parser.add_option(
+ '-f', '--function-bp',
+ type='string',
+ action='append',
+ dest='funcBreakpoints',
+ help=('Specify the name of a function to break at. '
+ 'Can be specified more than once.'),
+ default=[])
+
+ parser.add_option(
+ '-s', '--source-bp',
+ type='string',
+ action='append',
+ dest='sourceBreakpoints',
+ default=[],
+ help=('Specify source breakpoints to set in the format of '
+ '<source>:<line>. '
+ 'Can be specified more than once.'))
+
+ parser.add_option(
+ '--attachCommand',
+ type='string',
+ action='append',
+ dest='attachCmds',
+ default=[],
+ help=('Specify a LLDB command that will attach to a process. '
+ 'Can be specified more than once.'))
+
+ parser.add_option(
+ '--initCommand',
+ type='string',
+ action='append',
+ dest='initCmds',
+ default=[],
+ help=('Specify a LLDB command that will be executed before the target '
+ 'is created. Can be specified more than once.'))
+
+ parser.add_option(
+ '--preRunCommand',
+ type='string',
+ action='append',
+ dest='preRunCmds',
+ default=[],
+ help=('Specify a LLDB command that will be executed after the target '
+ 'has been created. Can be specified more than once.'))
+
+ parser.add_option(
+ '--stopCommand',
+ type='string',
+ action='append',
+ dest='stopCmds',
+ default=[],
+ help=('Specify a LLDB command that will be executed each time the'
+ 'process stops. Can be specified more than once.'))
+
+ parser.add_option(
+ '--exitCommand',
+ type='string',
+ action='append',
+ dest='exitCmds',
+ default=[],
+ help=('Specify a LLDB command that will be executed when the process '
+ 'exits. Can be specified more than once.'))
+
+ parser.add_option(
+ '--env',
+ type='string',
+ action='append',
+ dest='envs',
+ default=[],
+ help=('Specify environment variables to pass to the launched '
+ 'process.'))
+
+ parser.add_option(
+ '--waitFor',
+ action='store_true',
+ dest='waitFor',
+ default=False,
+ help=('Wait for the next process to be launched whose name matches '
+ 'the basename of the program specified with the --program '
+ 'option'))
+
+ (options, args) = parser.parse_args(sys.argv[1:])
+
+ if options.vscode_path is None and options.port is None:
+ print('error: must either specify a path to a Visual Studio Code '
+ 'Debug Adaptor vscode executable path using the --vscode '
+ 'option, or a port to attach to for an existing lldb-vscode '
+ 'using the --port option')
+ return
+ dbg = DebugAdaptor(executable=options.vscode_path, port=options.port)
+ if options.debug:
+ raw_input('Waiting for debugger to attach pid "%i"' % (
+ dbg.get_pid()))
+ if options.replay:
+ dbg.replay_packets(options.replay)
+ else:
+ run_vscode(dbg, args, options)
+ dbg.terminate()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/resources/LLDB-Info.plist.in b/resources/LLDB-Info.plist.in
new file mode 100644
index 000000000000..93af4df68cc3
--- /dev/null
+++ b/resources/LLDB-Info.plist.in
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>LLDB</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_FRAMEWORK_IDENTIFIER}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>FMWK</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_FRAMEWORK_SHORT_VERSION_STRING}</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_FRAMEWORK_BUNDLE_VERSION}</string>
+ <key>CFBundleName</key>
+ <string>LLDB</string>
+</dict>
+</plist>
diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt
index be5c3db53556..3598247dd619 100644
--- a/scripts/CMakeLists.txt
+++ b/scripts/CMakeLists.txt
@@ -11,31 +11,14 @@ set(SWIG_HEADERS
include(FindPythonInterp)
-if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
- set(SWIG_PYTHON_DIR
- ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
-else()
- set(SWIG_PYTHON_DIR ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX}/site-packages)
-endif()
-
-set(SWIG_INSTALL_DIR lib${LLVM_LIBDIR_SUFFIX})
-
-# Generating the LLDB framework correctly is a bit complicated because the
-# framework depends on the swig output.
if(LLDB_BUILD_FRAMEWORK)
set(framework_arg --framework --target-platform Darwin)
- set(SWIG_PYTHON_DIR
- ${LLDB_PYTHON_TARGET_DIR}/${LLDB_FRAMEWORK_RESOURCE_DIR}/Python)
- set(SWIG_INSTALL_DIR
- ${LLDB_FRAMEWORK_INSTALL_DIR}/${LLDB_FRAMEWORK_RESOURCE_DIR})
endif()
-get_filename_component(CFGBLDDIR ${LLDB_WRAP_PYTHON} DIRECTORY)
-
find_package(SWIG REQUIRED)
add_custom_command(
- OUTPUT ${LLDB_WRAP_PYTHON}
- OUTPUT ${LLDB_PYTHON_TARGET_DIR}/lldb.py
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapPython.cpp
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lldb.py
DEPENDS ${SWIG_SOURCES}
DEPENDS ${SWIG_INTERFACES}
DEPENDS ${SWIG_HEADERS}
@@ -44,19 +27,31 @@ add_custom_command(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/prepare_bindings.py
${framework_arg}
--srcRoot=${LLDB_SOURCE_DIR}
- --targetDir=${LLDB_PYTHON_TARGET_DIR}
- --cfgBldDir=${CFGBLDDIR}
+ --targetDir=${CMAKE_CURRENT_BINARY_DIR}
+ --cfgBldDir=${CMAKE_CURRENT_BINARY_DIR}
--prefix=${CMAKE_BINARY_DIR}
--swigExecutable=${SWIG_EXECUTABLE}
VERBATIM
COMMENT "Python script building LLDB Python wrapper")
-add_custom_target(swig_wrapper ALL DEPENDS ${LLDB_WRAP_PYTHON})
-set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lldb.py PROPERTIES GENERATED 1)
+add_custom_target(swig_wrapper ALL DEPENDS
+ ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapPython.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/lldb.py
+)
+
+if(NOT LLDB_BUILD_FRAMEWORK)
+ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
+ set(swig_python_subdir site-packages)
+ else()
+ set(swig_python_subdir python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
+ endif()
+ set(SWIG_PYTHON_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${swig_python_subdir})
+ set(SWIG_INSTALL_DIR lib${LLVM_LIBDIR_SUFFIX})
-# Install the LLDB python module
-install(DIRECTORY ${SWIG_PYTHON_DIR} DESTINATION ${SWIG_INSTALL_DIR})
+ # Install the LLDB python module
+ install(DIRECTORY ${SWIG_PYTHON_DIR} DESTINATION ${SWIG_INSTALL_DIR})
+endif()
# build Python modules
add_subdirectory(Python/modules)
diff --git a/scripts/Python/python-extensions.swig b/scripts/Python/python-extensions.swig
index 5543bee95d47..892e1af4bae5 100644
--- a/scripts/Python/python-extensions.swig
+++ b/scripts/Python/python-extensions.swig
@@ -1,5 +1,6 @@
%extend lldb::SBAddress {
+ %nothreadallow;
PyObject *lldb::SBAddress::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -12,8 +13,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBBlock {
+ %nothreadallow;
PyObject *lldb::SBBlock::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -26,8 +29,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBBreakpoint {
+ %nothreadallow;
PyObject *lldb::SBBreakpoint::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -40,6 +45,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -57,6 +63,7 @@
}
%extend lldb::SBBreakpointLocation {
+ %nothreadallow;
PyObject *lldb::SBBreakpointLocation::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelFull);
@@ -69,9 +76,11 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBBreakpointName {
+ %nothreadallow;
PyObject *lldb::SBBreakpointName::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -84,6 +93,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBBroadcaster {
@@ -103,6 +113,7 @@
}
%extend lldb::SBCommandReturnObject {
+ %nothreadallow;
PyObject *lldb::SBCommandReturnObject::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -115,6 +126,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
/* the write() and flush() calls are not part of the SB API proper, and are solely for Python usage
they are meant to make an SBCommandReturnObject into a file-like object so that instructions of the sort
@@ -130,6 +142,7 @@
{}
}
%extend lldb::SBCompileUnit {
+ %nothreadallow;
PyObject *lldb::SBCompileUnit::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -142,6 +155,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -157,6 +171,7 @@
%}
}
%extend lldb::SBData {
+ %nothreadallow;
PyObject *lldb::SBData::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -169,8 +184,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBDebugger {
+ %nothreadallow;
PyObject *lldb::SBDebugger::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -183,8 +200,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBDeclaration {
+ %nothreadallow;
PyObject *lldb::SBDeclaration::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -197,6 +216,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -214,6 +234,7 @@
}
%extend lldb::SBError {
+ %nothreadallow;
PyObject *lldb::SBError::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -226,8 +247,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBFileSpec {
+ %nothreadallow;
PyObject *lldb::SBFileSpec::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -240,8 +263,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBFrame {
+ %nothreadallow;
PyObject *lldb::SBFrame::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -254,8 +279,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBFunction {
+ %nothreadallow;
PyObject *lldb::SBFunction::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -268,6 +295,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -285,6 +313,7 @@
}
%extend lldb::SBInstruction {
+ %nothreadallow;
PyObject *lldb::SBInstruction::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -297,8 +326,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBInstructionList {
+ %nothreadallow;
PyObject *lldb::SBInstructionList::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -311,8 +342,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBLineEntry {
+ %nothreadallow;
PyObject *lldb::SBLineEntry::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -325,6 +358,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -342,6 +376,7 @@
}
%extend lldb::SBMemoryRegionInfo {
+ %nothreadallow;
PyObject *lldb::SBMemoryRegionInfo::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -354,9 +389,11 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBModule {
+ %nothreadallow;
PyObject *lldb::SBModule::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -369,6 +406,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -386,6 +424,7 @@
}
%extend lldb::SBModuleSpec {
+ %nothreadallow;
PyObject *lldb::SBModuleSpec::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -398,9 +437,11 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBModuleSpecList {
+ %nothreadallow;
PyObject *lldb::SBModuleSpecList::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -413,9 +454,11 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBProcess {
+ %nothreadallow;
PyObject *lldb::SBProcess::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -428,8 +471,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBSection {
+ %nothreadallow;
PyObject *lldb::SBSection::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -442,6 +487,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -472,6 +518,7 @@
{}
}
%extend lldb::SBSymbol {
+ %nothreadallow;
PyObject *lldb::SBSymbol::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -484,6 +531,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -499,6 +547,7 @@
%}
}
%extend lldb::SBSymbolContext {
+ %nothreadallow;
PyObject *lldb::SBSymbolContext::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -511,8 +560,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBSymbolContextList {
+ %nothreadallow;
PyObject *lldb::SBSymbolContextList::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -525,9 +576,11 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTarget {
+ %nothreadallow;
PyObject *lldb::SBTarget::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -540,6 +593,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
@@ -557,6 +611,7 @@
}
%extend lldb::SBType {
+ %nothreadallow;
PyObject *lldb::SBType::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -569,8 +624,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTypeCategory {
+ %nothreadallow;
PyObject *lldb::SBTypeCategory::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -583,8 +640,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTypeFilter {
+ %nothreadallow;
PyObject *lldb::SBTypeFilter::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -597,6 +656,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -612,6 +672,7 @@
%}
}
%extend lldb::SBTypeFormat {
+ %nothreadallow;
PyObject *lldb::SBTypeFormat::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -624,8 +685,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTypeMember {
+ %nothreadallow;
PyObject *lldb::SBTypeMember::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -638,8 +701,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTypeMemberFunction {
+ %nothreadallow;
PyObject *lldb::SBTypeMemberFunction::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -652,8 +717,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTypeEnumMember {
+ %nothreadallow;
PyObject *lldb::SBTypeEnumMember::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -666,8 +733,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBTypeNameSpecifier {
+ %nothreadallow;
PyObject *lldb::SBTypeNameSpecifier::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -680,6 +749,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -695,6 +765,7 @@
%}
}
%extend lldb::SBTypeSummary {
+ %nothreadallow;
PyObject *lldb::SBTypeSummary::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -707,6 +778,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -722,6 +794,7 @@
%}
}
%extend lldb::SBTypeSynthetic {
+ %nothreadallow;
PyObject *lldb::SBTypeSynthetic::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelBrief);
@@ -734,6 +807,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -749,6 +823,7 @@
%}
}
%extend lldb::SBThread {
+ %nothreadallow;
PyObject *lldb::SBThread::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -761,6 +836,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
%pythoncode %{
def __eq__(self, rhs):
if not isinstance(rhs, type(self)):
@@ -776,6 +852,7 @@
%}
}
%extend lldb::SBValue {
+ %nothreadallow;
PyObject *lldb::SBValue::__str__ (){
lldb::SBStream description;
$self->GetDescription (description);
@@ -788,8 +865,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBValueList {
+ %nothreadallow;
PyObject *lldb::SBValueList::__str__ (){
lldb::SBStream description;
const size_t n = $self->GetSize();
@@ -811,8 +890,10 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
%extend lldb::SBWatchpoint {
+ %nothreadallow;
PyObject *lldb::SBWatchpoint::__str__ (){
lldb::SBStream description;
$self->GetDescription (description, lldb::eDescriptionLevelVerbose);
@@ -825,6 +906,7 @@
else
return lldb_private::PythonString("").release();
}
+ %clearnothreadallow;
}
diff --git a/scripts/Python/python-swigsafecast.swig b/scripts/Python/python-swigsafecast.swig
index ffd7546323a0..d5cafbfa67cb 100644
--- a/scripts/Python/python-swigsafecast.swig
+++ b/scripts/Python/python-swigsafecast.swig
@@ -27,15 +27,6 @@ SBTypeToSWIGWrapper (PyObject* py_object)
template <>
PyObject*
-SBTypeToSWIGWrapper (const char* c_str)
-{
- if (c_str)
- return PyString_FromString(c_str);
- return NULL;
-}
-
-template <>
-PyObject*
SBTypeToSWIGWrapper (unsigned int* c_int)
{
if (!c_int)
@@ -147,3 +138,17 @@ SBTypeToSWIGWrapper (lldb::SBTypeSummaryOptions* summary_options_sb)
{
return SWIG_NewPointerObj((void *) summary_options_sb, SWIGTYPE_p_lldb__SBTypeSummaryOptions, 0);
}
+
+template <>
+PyObject*
+SBTypeToSWIGWrapper (lldb::SBStructuredData* structured_data_sb)
+{
+ return SWIG_NewPointerObj((void *) structured_data_sb, SWIGTYPE_p_lldb__SBStructuredData, 0);
+}
+
+template <>
+PyObject*
+SBTypeToSWIGWrapper (lldb::SBSymbolContext* sym_ctx_sb)
+{
+ return SWIG_NewPointerObj((void *) sym_ctx_sb, SWIGTYPE_p_lldb__SBSymbolContext, 0);
+}
diff --git a/scripts/Python/python-typemaps.swig b/scripts/Python/python-typemaps.swig
index 29e5d9b156df..56cab6c58163 100644
--- a/scripts/Python/python-typemaps.swig
+++ b/scripts/Python/python-typemaps.swig
@@ -77,6 +77,26 @@
}
}
+%typemap(in) lldb::StateType {
+ using namespace lldb_private;
+ if (PythonInteger::Check($input))
+ {
+ PythonInteger py_int(PyRefType::Borrowed, $input);
+ int64_t state_type_value = py_int.GetInteger() ;
+
+ if (state_type_value > lldb::StateType::kLastStateType) {
+ PyErr_SetString(PyExc_ValueError, "Not a valid StateType value");
+ return nullptr;
+ }
+ $1 = static_cast<lldb::StateType>(state_type_value);
+ }
+ else
+ {
+ PyErr_SetString(PyExc_ValueError, "Expecting an integer");
+ return nullptr;
+ }
+}
+
/* Typemap definitions to allow SWIG to properly handle char buffer. */
// typemap for a char buffer
@@ -119,30 +139,9 @@
// typemap for an outgoing buffer
// See also SBEvent::SBEvent(uint32_t event, const char *cstr, uint32_t cstr_len).
-%typemap(in) (const char *cstr, uint32_t cstr_len) {
- using namespace lldb_private;
- if (PythonString::Check($input)) {
- PythonString str(PyRefType::Borrowed, $input);
- $1 = (char*)str.GetString().data();
- $2 = str.GetSize();
- }
- else if(PythonByteArray::Check($input)) {
- PythonByteArray bytearray(PyRefType::Borrowed, $input);
- $1 = (char*)bytearray.GetBytes().data();
- $2 = bytearray.GetSize();
- }
- else if (PythonBytes::Check($input)) {
- PythonBytes bytes(PyRefType::Borrowed, $input);
- $1 = (char*)bytes.GetBytes().data();
- $2 = bytes.GetSize();
- }
- else {
- PyErr_SetString(PyExc_ValueError, "Expecting a string");
- return NULL;
- }
-}
// Ditto for SBProcess::PutSTDIN(const char *src, size_t src_len).
-%typemap(in) (const char *src, size_t src_len) {
+%typemap(in) (const char *cstr, uint32_t cstr_len),
+ (const char *src, size_t src_len) {
using namespace lldb_private;
if (PythonString::Check($input)) {
PythonString str(PyRefType::Borrowed, $input);
@@ -164,32 +163,9 @@
return NULL;
}
}
-// And SBProcess::WriteMemory.
-%typemap(in) (const void *buf, size_t size) {
- using namespace lldb_private;
- if (PythonString::Check($input)) {
- PythonString str(PyRefType::Borrowed, $input);
- $1 = (void*)str.GetString().data();
- $2 = str.GetSize();
- }
- else if(PythonByteArray::Check($input)) {
- PythonByteArray bytearray(PyRefType::Borrowed, $input);
- $1 = (void*)bytearray.GetBytes().data();
- $2 = bytearray.GetSize();
- }
- else if (PythonBytes::Check($input)) {
- PythonBytes bytes(PyRefType::Borrowed, $input);
- $1 = (void*)bytes.GetBytes().data();
- $2 = bytes.GetSize();
- }
- else {
- PyErr_SetString(PyExc_ValueError, "Expecting a buffer");
- return NULL;
- }
-}
-
-// For SBDebugger::DispatchInput
-%typemap(in) (const void *data, size_t data_len) {
+// For SBProcess::WriteMemory, SBTarget::GetInstructions and SBDebugger::DispatchInput.
+%typemap(in) (const void *buf, size_t size),
+ (const void *data, size_t data_len) {
using namespace lldb_private;
if (PythonString::Check($input)) {
PythonString str(PyRefType::Borrowed, $input);
@@ -244,142 +220,70 @@
free($1);
}
-// these typemaps allow Python users to pass list objects
-// and have them turn into C++ arrays (this is useful, for instance
-// when creating SBData objects from lists of numbers)
-%typemap(in) (uint64_t* array, size_t array_len) {
- /* Check if is a list */
- if (PyList_Check($input)) {
- int size = PyList_Size($input);
- int i = 0;
- $2 = size;
- $1 = (uint64_t*) malloc(size * sizeof(uint64_t));
- for (i = 0; i < size; i++) {
- PyObject *o = PyList_GetItem($input,i);
- if (PyInt_Check(o)) {
- $1[i] = PyInt_AsLong(o);
- }
- else if (PyLong_Check(o)) {
- $1[i] = PyLong_AsUnsignedLongLong(o);
- }
- else {
- PyErr_SetString(PyExc_TypeError,"list must contain numbers");
- free($1);
- return NULL;
- }
-
- if (PyErr_Occurred()) {
- free($1);
- return NULL;
- }
- }
- } else if ($input == Py_None) {
- $1 = NULL;
- $2 = 0;
- } else {
- PyErr_SetString(PyExc_TypeError,"not a list");
- return NULL;
- }
+%{
+namespace {
+template <class T>
+T PyLongAsT(PyObject *obj) {
+ static_assert(true, "unsupported type");
}
-%typemap(freearg) (uint64_t* array, size_t array_len) {
- free($1);
+template <> uint64_t PyLongAsT<uint64_t>(PyObject *obj) {
+ return static_cast<uint64_t>(PyLong_AsUnsignedLongLong(obj));
}
-%typemap(in) (uint32_t* array, size_t array_len) {
- /* Check if is a list */
- if (PyList_Check($input)) {
- int size = PyList_Size($input);
- int i = 0;
- $2 = size;
- $1 = (uint32_t*) malloc(size * sizeof(uint32_t));
- for (i = 0; i < size; i++) {
- PyObject *o = PyList_GetItem($input,i);
- if (PyInt_Check(o)) {
- $1[i] = PyInt_AsLong(o);
- }
- else if (PyLong_Check(o)) {
- $1[i] = PyLong_AsUnsignedLong(o);
- }
- else {
- PyErr_SetString(PyExc_TypeError,"list must contain numbers");
- free($1);
- return NULL;
- }
+template <> uint32_t PyLongAsT<uint32_t>(PyObject *obj) {
+ return static_cast<uint32_t>(PyLong_AsUnsignedLong(obj));
+}
- if (PyErr_Occurred()) {
- free($1);
- return NULL;
- }
- }
- } else if ($input == Py_None) {
- $1 = NULL;
- $2 = 0;
- } else {
- PyErr_SetString(PyExc_TypeError,"not a list");
- return NULL;
- }
+template <> int64_t PyLongAsT<int64_t>(PyObject *obj) {
+ return static_cast<int64_t>(PyLong_AsLongLong(obj));
}
-%typemap(freearg) (uint32_t* array, size_t array_len) {
- free($1);
+template <> int32_t PyLongAsT<int32_t>(PyObject *obj) {
+ return static_cast<int32_t>(PyLong_AsLong(obj));
}
-%typemap(in) (int64_t* array, size_t array_len) {
- /* Check if is a list */
- if (PyList_Check($input)) {
- int size = PyList_Size($input);
- int i = 0;
- $2 = size;
- $1 = (int64_t*) malloc(size * sizeof(int64_t));
- for (i = 0; i < size; i++) {
- PyObject *o = PyList_GetItem($input,i);
- if (PyInt_Check(o)) {
- $1[i] = PyInt_AsLong(o);
- }
- else if (PyLong_Check(o)) {
- $1[i] = PyLong_AsLongLong(o);
- }
- else {
- PyErr_SetString(PyExc_TypeError,"list must contain numbers");
- free($1);
- return NULL;
- }
+template <class T>
+bool SetNumberFromPyObject(T &number, PyObject *obj) {
+ if (PyInt_Check(obj))
+ number = static_cast<T>(PyInt_AsLong(obj));
+ else if (PyLong_Check(obj))
+ number = PyLongAsT<T>(obj);
+ else return false;
- if (PyErr_Occurred()) {
- free($1);
- return NULL;
- }
- }
- } else if ($input == Py_None) {
- $1 = NULL;
- $2 = 0;
- } else {
- PyErr_SetString(PyExc_TypeError,"not a list");
- return NULL;
- }
+ return true;
}
-%typemap(freearg) (int64_t* array, size_t array_len) {
- free($1);
+template <>
+bool SetNumberFromPyObject<double>(double &number, PyObject *obj) {
+ if (PyFloat_Check(obj)) {
+ number = PyFloat_AsDouble(obj);
+ return true;
+ }
+
+ return false;
}
-%typemap(in) (int32_t* array, size_t array_len) {
+} // namespace
+%}
+
+// these typemaps allow Python users to pass list objects
+// and have them turn into C++ arrays (this is useful, for instance
+// when creating SBData objects from lists of numbers)
+%typemap(in) (uint64_t* array, size_t array_len),
+ (uint32_t* array, size_t array_len),
+ (int64_t* array, size_t array_len),
+ (int32_t* array, size_t array_len),
+ (double* array, size_t array_len) {
/* Check if is a list */
if (PyList_Check($input)) {
int size = PyList_Size($input);
int i = 0;
$2 = size;
- $1 = (int32_t*) malloc(size * sizeof(int32_t));
+ $1 = ($1_type) malloc(size * sizeof($*1_type));
for (i = 0; i < size; i++) {
PyObject *o = PyList_GetItem($input,i);
- if (PyInt_Check(o)) {
- $1[i] = PyInt_AsLong(o);
- }
- else if (PyLong_Check(o)) {
- $1[i] = PyLong_AsLong(o);
- }
- else {
+ if (!SetNumberFromPyObject($1[i], o)) {
PyErr_SetString(PyExc_TypeError,"list must contain numbers");
free($1);
return NULL;
@@ -399,38 +303,11 @@
}
}
-%typemap(freearg) (int32_t* array, size_t array_len) {
- free($1);
-}
-
-%typemap(in) (double* array, size_t array_len) {
- /* Check if is a list */
- if (PyList_Check($input)) {
- int size = PyList_Size($input);
- int i = 0;
- $2 = size;
- $1 = (double*) malloc(size * sizeof(double));
- for (i = 0; i < size; i++) {
- PyObject *o = PyList_GetItem($input,i);
- if (PyFloat_Check(o)) {
- $1[i] = PyFloat_AsDouble(o);
- }
- else {
- PyErr_SetString(PyExc_TypeError,"list must contain floating-point numbers");
- free($1);
- return NULL;
- }
- }
- } else if ($input == Py_None) {
- $1 = NULL;
- $2 = 0;
- } else {
- PyErr_SetString(PyExc_TypeError,"not a list");
- return NULL;
- }
-}
-
-%typemap(freearg) (double* array, size_t array_len) {
+%typemap(freearg) (uint64_t* array, size_t array_len),
+ (uint32_t* array, size_t array_len),
+ (int64_t* array, size_t array_len),
+ (int32_t* array, size_t array_len),
+ (double* array, size_t array_len) {
free($1);
}
diff --git a/scripts/Python/python-wrapper.swig b/scripts/Python/python-wrapper.swig
index 96b8dda80f82..8509899df27b 100644
--- a/scripts/Python/python-wrapper.swig
+++ b/scripts/Python/python-wrapper.swig
@@ -333,6 +333,101 @@ LLDBSWIGPythonCallThreadPlan
return false;
}
+SWIGEXPORT void *
+LLDBSwigPythonCreateScriptedBreakpointResolver
+(
+ const char *python_class_name,
+ const char *session_dictionary_name,
+ lldb_private::StructuredDataImpl *args_impl,
+ lldb::BreakpointSP &breakpoint_sp
+)
+{
+ using namespace lldb_private;
+
+ if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
+ Py_RETURN_NONE;
+
+ PyErr_Cleaner py_err_cleaner(true);
+
+ auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
+ auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
+
+ if (!pfunc.IsAllocated())
+ return nullptr;
+
+ lldb::SBBreakpoint *bkpt_value = new lldb::SBBreakpoint(breakpoint_sp);
+
+ PythonObject bkpt_arg(PyRefType::Owned, SBTypeToSWIGWrapper(bkpt_value));
+
+ lldb::SBStructuredData *args_value = new lldb::SBStructuredData(args_impl);
+ PythonObject args_arg(PyRefType::Owned, SBTypeToSWIGWrapper(args_value));
+
+ PythonObject result = pfunc(bkpt_arg, args_arg, dict);
+ // FIXME: At this point we should check that the class we found supports all the methods
+ // that we need.
+
+ if (result.IsAllocated())
+ {
+ // Check that __callback__ is defined:
+ auto callback_func = result.ResolveName<PythonCallable>("__callback__");
+ if (callback_func.IsAllocated())
+ return result.release();
+ else
+ result.release();
+ }
+ Py_RETURN_NONE;
+}
+
+SWIGEXPORT unsigned int
+LLDBSwigPythonCallBreakpointResolver
+(
+ void *implementor,
+ const char *method_name,
+ lldb_private::SymbolContext *sym_ctx
+)
+{
+ using namespace lldb_private;
+
+ PyErr_Cleaner py_err_cleaner(false);
+ PythonObject self(PyRefType::Borrowed, static_cast<PyObject*>(implementor));
+ auto pfunc = self.ResolveName<PythonCallable>(method_name);
+
+ if (!pfunc.IsAllocated())
+ return 0;
+
+ PythonObject result;
+ if (sym_ctx != nullptr) {
+ lldb::SBSymbolContext sb_sym_ctx(sym_ctx);
+ PythonObject sym_ctx_arg(PyRefType::Owned, SBTypeToSWIGWrapper(sb_sym_ctx));
+ result = pfunc(sym_ctx_arg);
+ } else
+ result = pfunc();
+
+ if (PyErr_Occurred())
+ {
+ PyErr_Print();
+ return 0;
+ }
+
+ // The callback will return a bool, but we're need to also return ints
+ // so we're squirrelling the bool through as an int... And if you return
+ // nothing, we'll continue.
+ if (strcmp(method_name, "__callback__") == 0) {
+ if (result.get() == Py_False)
+ return 0;
+ else
+ return 1;
+ }
+
+ PythonInteger int_result = result.AsType<PythonInteger>();
+ if (!int_result.IsAllocated())
+ return 0;
+
+ unsigned int ret_val = int_result.GetInteger();
+
+ return ret_val;
+}
+
// wrapper that calls an optional instance member of an object taking no arguments
static PyObject*
LLDBSwigPython_CallOptionalMember
@@ -690,6 +785,54 @@ LLDBSWIGPythonCreateOSPlugin
}
SWIGEXPORT void*
+LLDBSWIGPython_CreateFrameRecognizer
+(
+ const char *python_class_name,
+ const char *session_dictionary_name
+)
+{
+ using namespace lldb_private;
+
+ if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name)
+ Py_RETURN_NONE;
+
+ PyErr_Cleaner py_err_cleaner(true);
+
+ auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(session_dictionary_name);
+ auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(python_class_name, dict);
+
+ if (!pfunc.IsAllocated())
+ Py_RETURN_NONE;
+
+ auto result = pfunc();
+
+ if (result.IsAllocated())
+ return result.release();
+
+ Py_RETURN_NONE;
+}
+
+SWIGEXPORT PyObject*
+LLDBSwigPython_GetRecognizedArguments
+(
+ PyObject *implementor,
+ const lldb::StackFrameSP& frame_sp
+)
+{
+ using namespace lldb_private;
+
+ static char callee_name[] = "get_recognized_arguments";
+
+ lldb::SBFrame frame_sb(frame_sp);
+ PyObject *arg = SBTypeToSWIGWrapper(frame_sb);
+
+ PythonString str(callee_name);
+ PyObject* result = PyObject_CallMethodObjArgs(implementor, str.get(), arg,
+ NULL);
+ return result;
+}
+
+SWIGEXPORT void*
LLDBSWIGPython_GetDynamicSetting (void* module, const char* setting, const lldb::TargetSP& target_sp)
{
using namespace lldb_private;
diff --git a/scripts/Xcode/lldbbuild.py b/scripts/Xcode/lldbbuild.py
index e70fe1bf803f..43481c4a0f87 100644
--- a/scripts/Xcode/lldbbuild.py
+++ b/scripts/Xcode/lldbbuild.py
@@ -190,4 +190,4 @@ def package_build_path():
return os.path.join(
llvm_build_dirtree(),
os.environ["LLVM_CONFIGURATION"],
- os.environ["CURRENT_ARCH"])
+ "x86_64")
diff --git a/scripts/Xcode/package-clang-headers.py b/scripts/Xcode/package-clang-headers.py
index 37f99919f866..32f84bc0894b 100644
--- a/scripts/Xcode/package-clang-headers.py
+++ b/scripts/Xcode/package-clang-headers.py
@@ -37,6 +37,9 @@ if not os.path.isdir(llvm_build_dir):
llvm_build_dir = re.sub("-appletvos-", "-watchos-", llvm_build_dir)
if not os.path.isdir(llvm_build_dir):
+ llvm_build_dir = re.sub("-watchos-", "-bridgeos-", llvm_build_dir)
+
+if not os.path.isdir(llvm_build_dir):
print llvm_build_dir + " doesn't exist"
sys.exit(1)
diff --git a/scripts/analyze-project-deps.py b/scripts/analyze-project-deps.py
index 52a880d3b3c8..b7f6e6803d02 100644
--- a/scripts/analyze-project-deps.py
+++ b/scripts/analyze-project-deps.py
@@ -90,7 +90,7 @@ def is_existing_cycle(path, cycles):
# at the end), then A -> B -> C is also a cycle. This is an important
# optimization which reduces the search space by multiple orders of
# magnitude.
- for i in xrange(0,len(path)):
+ for i in range(0,len(path)):
if any(is_sublist(x, path) for x in cycles):
return True
path = [path[-1]] + path[0:-1]
@@ -129,23 +129,23 @@ def expand(path_queue, path_lengths, cycles, src_map):
cycles = []
-path_queue = [[x] for x in src_map.iterkeys()]
+path_queue = [[x] for x in iter(src_map)]
path_lens = [1] * len(path_queue)
-items = list(src_map.iteritems())
-items.sort(lambda A, B : cmp(A[0], B[0]))
+items = list(src_map.items())
+items.sort(key = lambda A : A[0])
for (path, deps) in items:
- print path + ":"
- sorted_deps = list(deps.iteritems())
+ print(path + ":")
+ sorted_deps = list(deps.items())
if args.show_counts:
- sorted_deps.sort(lambda A, B: cmp(A[1], B[1]))
+ sorted_deps.sort(key = lambda A: (A[1], A[0]))
for dep in sorted_deps:
- print "\t{} [{}]".format(dep[0], dep[1])
+ print("\t{} [{}]".format(dep[0], dep[1]))
else:
- sorted_deps.sort(lambda A, B: cmp(A[0], B[0]))
+ sorted_deps.sort(key = lambda A: A[0])
for dep in sorted_deps:
- print "\t{}".format(dep[0])
+ print("\t{}".format(dep[0]))
def iter_cycles(cycles):
global src_map
@@ -161,16 +161,16 @@ def iter_cycles(cycles):
yield (total, smallest, result)
if args.discover_cycles:
- print "Analyzing cycles..."
+ print("Analyzing cycles...")
expand(path_queue, path_lens, cycles, src_map)
average = sum([len(x)+1 for x in cycles]) / len(cycles)
- print "Found {} cycles. Average cycle length = {}.".format(len(cycles), average)
+ print("Found {} cycles. Average cycle length = {}.".format(len(cycles), average))
counted = list(iter_cycles(cycles))
if args.show_counts:
- counted.sort(lambda A, B: cmp(A[0], B[0]))
+ counted.sort(key = lambda A: A[0])
for (total, smallest, cycle) in counted:
sys.stdout.write("{} deps to break: ".format(total))
sys.stdout.write(cycle[0][0])
@@ -180,9 +180,9 @@ if args.discover_cycles:
else:
for cycle in cycles:
cycle.append(cycle[0])
- print " -> ".join(cycle)
+ print(" -> ".join(cycle))
- print "Analyzing islands..."
+ print("Analyzing islands...")
islands = []
outgoing_counts = defaultdict(int)
incoming_counts = defaultdict(int)
@@ -195,14 +195,14 @@ if args.discover_cycles:
disjoints = [x for x in islands if this_cycle.isdisjoint(x)]
overlaps = [x for x in islands if not this_cycle.isdisjoint(x)]
islands = disjoints + [set.union(this_cycle, *overlaps)]
- print "Found {} disjoint cycle islands...".format(len(islands))
+ print("Found {} disjoint cycle islands...".format(len(islands)))
for island in islands:
- print "Island ({} elements)".format(len(island))
+ print("Island ({} elements)".format(len(island)))
sorted = []
for node in island:
sorted.append((node, incoming_counts[node], outgoing_counts[node]))
- sorted.sort(lambda x, y: cmp(x[1]+x[2], y[1]+y[2]))
+ sorted.sort(key = lambda x: x[1]+x[2])
for (node, inc, outg) in sorted:
- print " {} [{} in, {} out]".format(node, inc, outg)
+ print(" {} [{} in, {} out]".format(node, inc, outg))
sys.stdout.flush()
pass
diff --git a/scripts/framework-header-fix.sh b/scripts/framework-header-fix.sh
index c09d1458ff82..3459dd91c9ec 100755
--- a/scripts/framework-header-fix.sh
+++ b/scripts/framework-header-fix.sh
@@ -1,13 +1,17 @@
#!/bin/sh
# Usage: framework-header-fix.sh <source header dir> <LLDB Version>
+
+set -e
+
for file in `find $1 -name "*.h"`
do
- sed -i '' 's/\(#include\)[ ]*"lldb\/\(API\/\)\{0,1\}\(.*\)"/\1 <LLDB\/\3>/1' "$file"
- sed -i '' 's|<LLDB/Utility|<LLDB|' "$file"
+ /usr/bin/sed -i.bak 's/\(#include\)[ ]*"lldb\/\(API\/\)\{0,1\}\(.*\)"/\1 <LLDB\/\3>/1' "$file"
+ /usr/bin/sed -i.bak 's|<LLDB/Utility|<LLDB|' "$file"
LLDB_VERSION=`echo $2 | /usr/bin/sed -E 's/^([0-9]+).([0-9]+).([0-9]+)(.[0-9]+)?$/\\1/g'`
LLDB_REVISION=`echo $2 | /usr/bin/sed -E 's/^([0-9]+).([0-9]+).([0-9]+)(.[0-9]+)?$/\\3/g'`
LLDB_VERSION_STRING=`echo $2`
- sed -i '' "s|//#define LLDB_VERSION$|#define LLDB_VERSION $LLDB_VERSION |" "$file"
- sed -i '' "s|//#define LLDB_REVISION|#define LLDB_REVISION $LLDB_REVISION |" "$file"
- sed -i '' "s|//#define LLDB_VERSION_STRING|#define LLDB_VERSION_STRING \"$LLDB_VERSION_STRING\" |" "$file"
+ /usr/bin/sed -i.bak "s|//#define LLDB_VERSION$|#define LLDB_VERSION $LLDB_VERSION |" "$file"
+ /usr/bin/sed -i.bak "s|//#define LLDB_REVISION|#define LLDB_REVISION $LLDB_REVISION |" "$file"
+ /usr/bin/sed -i.bak "s|//#define LLDB_VERSION_STRING|#define LLDB_VERSION_STRING \"$LLDB_VERSION_STRING\" |" "$file"
+ rm -f "$file.bak"
done
diff --git a/scripts/interface/SBBreakpoint.i b/scripts/interface/SBBreakpoint.i
index 525797ad91f1..1383f3848e2a 100644
--- a/scripts/interface/SBBreakpoint.i
+++ b/scripts/interface/SBBreakpoint.i
@@ -226,6 +226,10 @@ public:
bool
GetDescription(lldb::SBStream &description, bool include_locations);
+ // Can only be called from a ScriptedBreakpointResolver...
+ SBError
+ AddLocation(SBAddress &address);
+
bool
operator == (const lldb::SBBreakpoint& rhs);
@@ -247,6 +251,9 @@ public:
static uint32_t
GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp);
+ bool
+ IsHardware ();
+
%pythoncode %{
class locations_access(object):
diff --git a/scripts/interface/SBCommandInterpreter.i b/scripts/interface/SBCommandInterpreter.i
index 09e7c9df736a..a34515a9b1a8 100644
--- a/scripts/interface/SBCommandInterpreter.i
+++ b/scripts/interface/SBCommandInterpreter.i
@@ -219,6 +219,13 @@ public:
int max_return_elements,
lldb::SBStringList &matches);
+ int
+ HandleCompletionWithDescriptions (const char *current_line,
+ uint32_t cursor_pos,
+ int match_start_point,
+ int max_return_elements,
+ lldb::SBStringList &matches,
+ lldb::SBStringList &descriptions);
bool
IsActive ();
diff --git a/scripts/interface/SBDebugger.i b/scripts/interface/SBDebugger.i
index 8ac2c51e12fe..fde3d7b6b88e 100644
--- a/scripts/interface/SBDebugger.i
+++ b/scripts/interface/SBDebugger.i
@@ -28,7 +28,7 @@ def disassemble_instructions (insts):
# Create a new debugger instance
debugger = lldb.SBDebugger.Create()
-# When we step or continue, don't return from the function until the process
+# When we step or continue, don't return from the function until the process
# stops. We do this by setting the async mode to false.
debugger.SetAsync (False)
@@ -46,7 +46,7 @@ if target:
# Launch the process. Since we specified synchronous mode, we won't return
# from this function until we hit the breakpoint at main
process = target.LaunchSimple (None, None, os.getcwd())
-
+
# Make sure the launch went ok
if process:
# Print some simple process info
@@ -122,10 +122,13 @@ public:
static void
Initialize();
-
+
+ static void
+ Initialize(lldb::SBInitializerOptions& options);
+
static void
Terminate();
-
+
static lldb::SBDebugger
Create();
@@ -155,8 +158,8 @@ public:
void
SetAsync (bool b);
-
- bool
+
+ bool
GetAsync ();
void
@@ -248,7 +251,7 @@ public:
lldb::SBPlatform
GetSelectedPlatform();
-
+
void
SetSelectedPlatform(lldb::SBPlatform &platform);
@@ -287,7 +290,7 @@ public:
// SBPlatform from this class.
lldb::SBError
SetCurrentPlatform (const char *platform_name);
-
+
bool
SetCurrentPlatformSDKRoot (const char *sysroot);
@@ -295,8 +298,8 @@ public:
// an interface to the Set/Get UseExternalEditor.
bool
SetUseExternalEditor (bool input);
-
- bool
+
+ bool
GetUseExternalEditor ();
bool
@@ -342,7 +345,7 @@ public:
void
DispatchInputEndOfFile ();
-
+
const char *
GetInstanceName ();
@@ -366,14 +369,17 @@ public:
lldb::user_id_t
GetID ();
-
+
const char *
GetPrompt() const;
void
SetPrompt (const char *prompt);
-
- lldb::ScriptLanguage
+
+ const char *
+ GetReproducerPath() const;
+
+ lldb::ScriptLanguage
GetScriptLanguage() const;
void
@@ -381,31 +387,31 @@ public:
bool
GetCloseInputOnEOF () const;
-
+
void
SetCloseInputOnEOF (bool b);
-
+
lldb::SBTypeCategory
GetCategory (const char* category_name);
-
+
SBTypeCategory
GetCategory (lldb::LanguageType lang_type);
-
+
lldb::SBTypeCategory
CreateCategory (const char* category_name);
-
+
bool
DeleteCategory (const char* category_name);
-
+
uint32_t
GetNumCategories ();
-
+
lldb::SBTypeCategory
GetCategoryAtIndex (uint32_t);
-
+
lldb::SBTypeCategory
GetDefaultCategory();
-
+
lldb::SBTypeFormat
GetFormatForType (lldb::SBTypeNameSpecifier);
@@ -425,7 +431,7 @@ public:
int &num_errors,
bool &quit_requested,
bool &stopped_for_crash);
-
+
lldb::SBError
RunREPL (lldb::LanguageType language, const char *repl_options);
}; // class SBDebugger
diff --git a/scripts/interface/SBExpressionOptions.i b/scripts/interface/SBExpressionOptions.i
index cb61dd9d9632..8687dde49f99 100644
--- a/scripts/interface/SBExpressionOptions.i
+++ b/scripts/interface/SBExpressionOptions.i
@@ -132,6 +132,14 @@ public:
void
SetTopLevel(bool b = true);
+
+ %feature("docstring", "Gets whether to JIT an expression if it cannot be interpreted.") GetAllowJIT;
+ bool
+ GetAllowJIT();
+
+ %feature("docstring", "Sets whether to JIT an expression if it cannot be interpreted.") SetAllowJIT;
+ void
+ SetAllowJIT(bool allow);
protected:
diff --git a/scripts/interface/SBFrame.i b/scripts/interface/SBFrame.i
index b8654cb0eb60..1ba2c2ebcd97 100644
--- a/scripts/interface/SBFrame.i
+++ b/scripts/interface/SBFrame.i
@@ -154,6 +154,17 @@ public:
IsInlined() const;
%feature("docstring", "
+ /// Return true if this frame is artificial (e.g a frame synthesized to
+ /// capture a tail call). Local variables may not be available in an artificial
+ /// frame.
+ ") IsArtificial;
+ bool
+ IsArtificial();
+
+ bool
+ IsArtificial() const;
+
+ %feature("docstring", "
/// The version that doesn't supply a 'use_dynamic' value will use the
/// target's default.
") EvaluateExpression;
diff --git a/scripts/interface/SBInitializerOptions.i b/scripts/interface/SBInitializerOptions.i
new file mode 100644
index 000000000000..9478642ebd6f
--- /dev/null
+++ b/scripts/interface/SBInitializerOptions.i
@@ -0,0 +1,24 @@
+//===-- SWIG Interface for SBInitializerOptions -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+namespace lldb {
+
+class SBInitializerOptions
+{
+public:
+ SBInitializerOptions ();
+ SBInitializerOptions (const lldb::SBInitializerOptions &rhs);
+ ~SBInitializerOptions();
+
+ void SetCaptureReproducer(bool b);
+ void SetReplayReproducer(bool b);
+ void SetReproducerPath(const char* path);
+};
+
+} // namespace lldb
diff --git a/scripts/interface/SBMemoryRegionInfo.i b/scripts/interface/SBMemoryRegionInfo.i
index d68770802618..c331fbd85599 100644
--- a/scripts/interface/SBMemoryRegionInfo.i
+++ b/scripts/interface/SBMemoryRegionInfo.i
@@ -44,6 +44,9 @@ public:
bool
IsMapped ();
+ const char *
+ GetName ();
+
bool
operator == (const lldb::SBMemoryRegionInfo &rhs) const;
diff --git a/scripts/interface/SBModule.i b/scripts/interface/SBModule.i
index adda954e5bfb..32b771c4d02d 100644
--- a/scripts/interface/SBModule.i
+++ b/scripts/interface/SBModule.i
@@ -332,6 +332,9 @@ public:
lldb::SBAddress
GetObjectFileHeaderAddress() const;
+ lldb::SBAddress
+ GetObjectFileEntryPointAddress() const;
+
bool
operator == (const lldb::SBModule &rhs) const;
diff --git a/scripts/interface/SBStructuredData.i b/scripts/interface/SBStructuredData.i
index 4e54cdd7b405..d30179c4d48b 100644
--- a/scripts/interface/SBStructuredData.i
+++ b/scripts/interface/SBStructuredData.i
@@ -38,6 +38,8 @@ namespace lldb {
size_t GetSize() const;
+ bool GetKeys(lldb::SBStringList &keys) const;
+
lldb::SBStructuredData GetValueForKey(const char *key) const;
lldb::SBStructuredData GetItemAtIndex(size_t idx) const;
diff --git a/scripts/interface/SBTarget.i b/scripts/interface/SBTarget.i
index 08fb268c08bf..1cc806db8386 100644
--- a/scripts/interface/SBTarget.i
+++ b/scripts/interface/SBTarget.i
@@ -373,6 +373,14 @@ public:
lldb::SBFileSpec
GetExecutable ();
+ %feature("docstring", "
+ /// Append the path mapping (from -> to) to the target's paths mapping list.
+ ") AppendImageSearchPath;
+ void
+ AppendImageSearchPath (const char *from,
+ const char *to,
+ SBError &error);
+
bool
AddModule (lldb::SBModule &module);
@@ -616,6 +624,11 @@ public:
lldb::addr_t offset, SBFileSpecList &module_list);
lldb::SBBreakpoint
+ BreakpointCreateByLocation (const lldb::SBFileSpec &file_spec, uint32_t line,
+ uint32_t column, lldb::addr_t offset,
+ SBFileSpecList &module_list);
+
+ lldb::SBBreakpoint
BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL);
lldb::SBBreakpoint
@@ -718,6 +731,74 @@ public:
lldb::SBBreakpoint
BreakpointCreateBySBAddress (SBAddress &sb_address);
+
+ %feature("docstring", "
+ //------------------------------------------------------------------
+ /// Create a breakpoint using a scripted resolver.
+ ///
+ /// @param[in] class_name
+ /// This is the name of the class that implements a scripted resolver.
+ /// The class should have the following signature:
+ /// class Resolver:
+ /// def __init__(self, bkpt, extra_args):
+ /// # bkpt - the breakpoint for which this is the resolver. When
+ /// # the resolver finds an interesting address, call AddLocation
+ /// # on this breakpoint to add it.
+ /// #
+ /// # extra_args - an SBStructuredData that can be used to
+ /// # parametrize this instance. Same as the extra_args passed
+ /// # to BreakpointCreateFromScript.
+ ///
+ /// def __get_depth__ (self):
+ /// # This is optional, but if defined, you should return the
+ /// # depth at which you want the callback to be called. The
+ /// # available options are:
+ /// # lldb.eSearchDepthModule
+ /// # lldb.eSearchDepthCompUnit
+ /// # The default if you don't implement this method is
+ /// # eSearchDepthModule.
+ ///
+ /// def __callback__(self, sym_ctx):
+ /// # sym_ctx - an SBSymbolContext that is the cursor in the
+ /// # search through the program to resolve breakpoints.
+ /// # The sym_ctx will be filled out to the depth requested in
+ /// # __get_depth__.
+ /// # Look in this sym_ctx for new breakpoint locations,
+ /// # and if found use bkpt.AddLocation to add them.
+ /// # Note, you will only get called for modules/compile_units that
+ /// # pass the SearchFilter provided by the module_list & file_list
+ /// # passed into BreakpointCreateFromScript.
+ ///
+ /// def get_short_help(self):
+ /// # Optional, but if implemented return a short string that will
+ /// # be printed at the beginning of the break list output for the
+ /// # breakpoint.
+ ///
+ /// @param[in] extra_args
+ /// This is an SBStructuredData object that will get passed to the
+ /// constructor of the class in class_name. You can use this to
+ /// reuse the same class, parametrizing it with entries from this
+ /// dictionary.
+ ///
+ /// @param module_list
+ /// If this is non-empty, this will be used as the module filter in the
+ /// SearchFilter created for this breakpoint.
+ ///
+ /// @param file_list
+ /// If this is non-empty, this will be used as the comp unit filter in the
+ /// SearchFilter created for this breakpoint.
+ ///
+ /// @return
+ /// An SBBreakpoint that will set locations based on the logic in the
+ /// resolver's search callback.
+ //------------------------------------------------------------------
+ ") BreakpointCreateFromScript;
+ lldb::SBBreakpoint BreakpointCreateFromScript(
+ const char *class_name,
+ SBStructuredData &extra_args,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &file_list,
+ bool request_hardware = false);
uint32_t
GetNumBreakpoints () const;
@@ -938,6 +1019,10 @@ public:
void
SetLaunchInfo (const lldb::SBLaunchInfo &launch_info);
+ void SetCollectingStats(bool v);
+
+ bool GetCollectingStats();
+
lldb::SBStructuredData GetStatistics();
bool
diff --git a/scripts/interface/SBThread.i b/scripts/interface/SBThread.i
index 60d77c783bb9..c12f176e42ed 100644
--- a/scripts/interface/SBThread.i
+++ b/scripts/interface/SBThread.i
@@ -397,6 +397,24 @@ public:
") GetExtendedBacktraceOriginatingIndexID;
uint32_t
GetExtendedBacktraceOriginatingIndexID();
+
+ %feature("autodoc","
+ Returns an SBValue object represeting the current exception for the thread,
+ if there is any. Currently, this works for Obj-C code and returns an SBValue
+ representing the NSException object at the throw site or that's currently
+ being processes.
+ ") GetCurrentException;
+ lldb::SBValue
+ GetCurrentException();
+
+ %feature("autodoc","
+ Returns a historical (fake) SBThread representing the stack trace of an
+ exception, if there is one for the thread. Currently, this works for Obj-C
+ code, and can retrieve the throw-site backtrace of an NSException object
+ even when the program is no longer at the throw site.
+ ") GetCurrentExceptionBacktrace;
+ lldb::SBThread
+ GetCurrentExceptionBacktrace();
%feature("autodoc","
Takes no arguments, returns a bool.
diff --git a/scripts/interface/SBThreadPlan.i b/scripts/interface/SBThreadPlan.i
index 9910314e873b..89291b39b2a9 100644
--- a/scripts/interface/SBThreadPlan.i
+++ b/scripts/interface/SBThreadPlan.i
@@ -106,6 +106,9 @@ public:
SBThreadPlan
QueueThreadPlanForRunToAddress (SBAddress address);
+ SBThreadPlan
+ QueueThreadPlanForStepScripted(const char *script_class_name);
+
protected:
friend class SBBreakpoint;
diff --git a/scripts/interface/SBVariablesOptions.i b/scripts/interface/SBVariablesOptions.i
index 3941a58d7bc9..8ce74140e63e 100644
--- a/scripts/interface/SBVariablesOptions.i
+++ b/scripts/interface/SBVariablesOptions.i
@@ -26,7 +26,13 @@ public:
void
SetIncludeArguments (bool);
-
+
+ bool
+ GetIncludeRecognizedArguments (const lldb::SBTarget &) const;
+
+ void
+ SetIncludeRecognizedArguments (bool);
+
bool
GetIncludeLocals () const;
diff --git a/scripts/lldb.swig b/scripts/lldb.swig
index dc987040e768..e8553d075d46 100644
--- a/scripts/lldb.swig
+++ b/scripts/lldb.swig
@@ -41,12 +41,12 @@ Older swig versions will simply ignore this setting.
*/
%define MODULEIMPORT
"try:
- # Try a relative import first
- from . import $module
+ # Try an absolute import first. If we're being loaded from lldb,
+ # _lldb should be a built-in module.
+ import $module
except ImportError:
- # Maybe absolute import will work (if we're being loaded from lldb, it
- # should).
- import $module"
+ # Relative import should work if we are being loaded by Python.
+ from . import $module"
%enddef
// These versions will not generate working python modules, so error out early.
#if SWIG_VERSION >= 0x030009 && SWIG_VERSION < 0x030011
@@ -187,6 +187,7 @@ import six
%include "./interface/SBFrame.i"
%include "./interface/SBFunction.i"
%include "./interface/SBHostOS.i"
+%include "./interface/SBInitializerOptions.i"
%include "./interface/SBInstruction.i"
%include "./interface/SBInstructionList.i"
%include "./interface/SBLanguageRuntime.i"
diff --git a/scripts/utilsOsType.py b/scripts/utilsOsType.py
index 5595541e1a19..dfc5cec340d4 100644
--- a/scripts/utilsOsType.py
+++ b/scripts/utilsOsType.py
@@ -35,8 +35,9 @@ if sys.version_info.major >= 3:
FreeBSD = 2
Linux = 3
NetBSD = 4
- Windows = 5
- kFreeBSD = 6
+ OpenBSD = 5
+ Windows = 6
+ kFreeBSD = 7
else:
class EnumOsType(object):
values = ["Unknown",
diff --git a/source/API/CMakeLists.txt b/source/API/CMakeLists.txt
index be9d4115cecc..e4ec64e537af 100644
--- a/source/API/CMakeLists.txt
+++ b/source/API/CMakeLists.txt
@@ -4,6 +4,11 @@ endif()
get_property(LLDB_ALL_PLUGINS GLOBAL PROPERTY LLDB_PLUGINS)
+if(NOT LLDB_DISABLE_PYTHON)
+ get_target_property(lldb_scripts_dir swig_wrapper BINARY_DIR)
+ set(lldb_python_wrapper ${lldb_scripts_dir}/LLDBWrapPython.cpp)
+endif()
+
add_lldb_library(liblldb SHARED
SBAddress.cpp
SBAttachInfo.cpp
@@ -29,6 +34,7 @@ add_lldb_library(liblldb SHARED
SBFrame.cpp
SBFunction.cpp
SBHostOS.cpp
+ SBInitializerOptions.cpp
SBInstruction.cpp
SBInstructionList.cpp
SBLanguageRuntime.cpp
@@ -72,7 +78,7 @@ add_lldb_library(liblldb SHARED
SBWatchpoint.cpp
SBUnixSignals.cpp
SystemInitializerFull.cpp
- ${LLDB_WRAP_PYTHON}
+ ${lldb_python_wrapper}
LINK_LIBS
lldbBase
@@ -91,24 +97,26 @@ add_lldb_library(liblldb SHARED
Support
)
-add_dependencies(lldb-suite liblldb)
+if(lldb_python_wrapper)
+ add_dependencies(liblldb swig_wrapper)
-if (MSVC)
- set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING PROPERTY COMPILE_FLAGS " /W0")
-else()
- set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING PROPERTY COMPILE_FLAGS " -w")
-endif()
+ if (MSVC)
+ set_property(SOURCE ${lldb_python_wrapper} APPEND_STRING PROPERTY COMPILE_FLAGS " /W0")
+ else()
+ set_property(SOURCE ${lldb_python_wrapper} APPEND_STRING PROPERTY COMPILE_FLAGS " -w")
+ endif()
-set_source_files_properties(${LLDB_WRAP_PYTHON} PROPERTIES GENERATED 1)
-if (CLANG_CL)
- set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING
- PROPERTY COMPILE_FLAGS " -Wno-unused-function")
+ set_source_files_properties(${lldb_python_wrapper} PROPERTIES GENERATED ON)
+ if (CLANG_CL)
+ set_property(SOURCE ${lldb_python_wrapper} APPEND_STRING
+ PROPERTY COMPILE_FLAGS " -Wno-unused-function")
+ endif()
+ if (LLVM_COMPILER_IS_GCC_COMPATIBLE AND
+ NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
+ set_property(SOURCE ${lldb_python_wrapper} APPEND_STRING
+ PROPERTY COMPILE_FLAGS " -Wno-sequence-point -Wno-cast-qual")
+ endif ()
endif()
-if (LLVM_COMPILER_IS_GCC_COMPATIBLE AND
- NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
- set_property(SOURCE ${LLDB_WRAP_PYTHON} APPEND_STRING
- PROPERTY COMPILE_FLAGS " -Wno-sequence-point -Wno-cast-qual")
-endif ()
set_target_properties(liblldb
PROPERTIES
@@ -143,6 +151,6 @@ else()
)
endif()
-if (LLDB_WRAP_PYTHON)
- add_dependencies(liblldb swig_wrapper)
+if(LLDB_BUILD_FRAMEWORK)
+ include(LLDBFramework)
endif()
diff --git a/source/API/SBAddress.cpp b/source/API/SBAddress.cpp
index d12197e66ddd..09ec6c3f10db 100644
--- a/source/API/SBAddress.cpp
+++ b/source/API/SBAddress.cpp
@@ -62,7 +62,7 @@ bool lldb::operator==(const SBAddress &lhs, const SBAddress &rhs) {
}
bool SBAddress::IsValid() const {
- return m_opaque_ap.get() != NULL && m_opaque_ap->IsValid();
+ return m_opaque_ap != NULL && m_opaque_ap->IsValid();
}
void SBAddress::Clear() { m_opaque_ap.reset(new Address()); }
@@ -156,7 +156,7 @@ Address *SBAddress::operator->() { return m_opaque_ap.get(); }
const Address *SBAddress::operator->() const { return m_opaque_ap.get(); }
Address &SBAddress::ref() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new Address());
return *m_opaque_ap;
}
@@ -198,8 +198,9 @@ SBModule SBAddress::GetModule() {
SBSymbolContext SBAddress::GetSymbolContext(uint32_t resolve_scope) {
SBSymbolContext sb_sc;
+ SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
if (m_opaque_ap->IsValid())
- m_opaque_ap->CalculateSymbolContext(&sb_sc.ref(), resolve_scope);
+ m_opaque_ap->CalculateSymbolContext(&sb_sc.ref(), scope);
return sb_sc;
}
diff --git a/source/API/SBAttachInfo.cpp b/source/API/SBAttachInfo.cpp
index d6cb212dedf8..a74487a70fe3 100644
--- a/source/API/SBAttachInfo.cpp
+++ b/source/API/SBAttachInfo.cpp
@@ -26,16 +26,14 @@ SBAttachInfo::SBAttachInfo(lldb::pid_t pid)
SBAttachInfo::SBAttachInfo(const char *path, bool wait_for)
: m_opaque_sp(new ProcessAttachInfo()) {
if (path && path[0])
- m_opaque_sp->GetExecutableFile().SetFile(path, false,
- FileSpec::Style::native);
+ m_opaque_sp->GetExecutableFile().SetFile(path, FileSpec::Style::native);
m_opaque_sp->SetWaitForLaunch(wait_for);
}
SBAttachInfo::SBAttachInfo(const char *path, bool wait_for, bool async)
: m_opaque_sp(new ProcessAttachInfo()) {
if (path && path[0])
- m_opaque_sp->GetExecutableFile().SetFile(path, false,
- FileSpec::Style::native);
+ m_opaque_sp->GetExecutableFile().SetFile(path, FileSpec::Style::native);
m_opaque_sp->SetWaitForLaunch(wait_for);
m_opaque_sp->SetAsync(async);
}
@@ -79,8 +77,7 @@ void SBAttachInfo::SetProcessPluginName(const char *plugin_name) {
void SBAttachInfo::SetExecutable(const char *path) {
if (path && path[0])
- m_opaque_sp->GetExecutableFile().SetFile(path, false,
- FileSpec::Style::native);
+ m_opaque_sp->GetExecutableFile().SetFile(path, FileSpec::Style::native);
else
m_opaque_sp->GetExecutableFile().Clear();
}
diff --git a/source/API/SBBreakpoint.cpp b/source/API/SBBreakpoint.cpp
index 6a0ff9536c2c..b6720071e17c 100644
--- a/source/API/SBBreakpoint.cpp
+++ b/source/API/SBBreakpoint.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBBreakpointLocation.h"
#include "lldb/API/SBDebugger.h"
@@ -23,6 +19,8 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/Debugger.h"
@@ -487,6 +485,40 @@ bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) {
return false;
}
+SBError
+SBBreakpoint::AddLocation(SBAddress &address) {
+ BreakpointSP bkpt_sp = GetSP();
+ SBError error;
+
+ if (!address.IsValid()) {
+ error.SetErrorString("Can't add an invalid address.");
+ return error;
+ }
+
+ if (!bkpt_sp) {
+ error.SetErrorString("No breakpoint to add a location to.");
+ return error;
+ }
+
+ if (!llvm::isa<BreakpointResolverScripted>(bkpt_sp->GetResolver().get())) {
+ error.SetErrorString("Only a scripted resolver can add locations.");
+ return error;
+ }
+
+ if (bkpt_sp->GetSearchFilter()->AddressPasses(address.ref()))
+ bkpt_sp->AddLocation(address.ref());
+ else
+ {
+ StreamString s;
+ address.get()->Dump(&s, &bkpt_sp->GetTarget(),
+ Address::DumpStyleModuleWithFileAddress);
+ error.SetErrorStringWithFormat("Address: %s didn't pass the filter.",
+ s.GetData());
+ }
+ return error;
+}
+
+
void SBBreakpoint
::SetCallback(SBBreakpointHitCallback callback,
void *baton) {
@@ -656,6 +688,13 @@ SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) {
return num_locations;
}
+bool SBBreakpoint::IsHardware() const {
+ BreakpointSP bkpt_sp = GetSP();
+ if (bkpt_sp)
+ return bkpt_sp->IsHardware();
+ return false;
+}
+
BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); }
// This is simple collection of breakpoint id's and their target.
diff --git a/source/API/SBBreakpointName.cpp b/source/API/SBBreakpointName.cpp
index a6742e3b89ec..47bddd752346 100644
--- a/source/API/SBBreakpointName.cpp
+++ b/source/API/SBBreakpointName.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBBreakpointName.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBError.h"
@@ -168,11 +164,11 @@ const SBBreakpointName &SBBreakpointName::operator=(const SBBreakpointName &rhs)
}
bool SBBreakpointName::operator==(const lldb::SBBreakpointName &rhs) {
- return *m_impl_up.get() == *rhs.m_impl_up.get();
+ return *m_impl_up == *rhs.m_impl_up;
}
bool SBBreakpointName::operator!=(const lldb::SBBreakpointName &rhs) {
- return *m_impl_up.get() != *rhs.m_impl_up.get();
+ return *m_impl_up != *rhs.m_impl_up;
}
bool SBBreakpointName::IsValid() const {
diff --git a/source/API/SBBreakpointOptionCommon.cpp b/source/API/SBBreakpointOptionCommon.cpp
index 569b860a4235..c0618adb238a 100644
--- a/source/API/SBBreakpointOptionCommon.cpp
+++ b/source/API/SBBreakpointOptionCommon.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBBreakpointName.h"
#include "lldb/API/SBBreakpointLocation.h"
#include "lldb/API/SBDebugger.h"
diff --git a/source/API/SBBroadcaster.cpp b/source/API/SBBroadcaster.cpp
index 278576b5ddcd..7868c38a818a 100644
--- a/source/API/SBBroadcaster.cpp
+++ b/source/API/SBBroadcaster.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Broadcaster.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Log.h"
#include "lldb/API/SBBroadcaster.h"
diff --git a/source/API/SBCommandInterpreter.cpp b/source/API/SBCommandInterpreter.cpp
index cbb514abb6fe..2a06e608c0b9 100644
--- a/source/API/SBCommandInterpreter.cpp
+++ b/source/API/SBCommandInterpreter.cpp
@@ -7,17 +7,13 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-types.h"
-#include "lldb/Core/Listener.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/Listener.h"
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandInterpreter.h"
@@ -71,6 +67,14 @@ void SBCommandInterpreterRunOptions::SetEchoCommands(bool echo_commands) {
m_opaque_up->SetEchoCommands(echo_commands);
}
+bool SBCommandInterpreterRunOptions::GetEchoCommentCommands() const {
+ return m_opaque_up->GetEchoCommentCommands();
+}
+
+void SBCommandInterpreterRunOptions::SetEchoCommentCommands(bool echo) {
+ m_opaque_up->SetEchoCommentCommands(echo);
+}
+
bool SBCommandInterpreterRunOptions::GetPrintResults() const {
return m_opaque_up->GetPrintResults();
}
@@ -94,7 +98,7 @@ SBCommandInterpreterRunOptions::get() const {
lldb_private::CommandInterpreterRunOptions &
SBCommandInterpreterRunOptions::ref() const {
- return *m_opaque_up.get();
+ return *m_opaque_up;
}
class CommandPluginInterfaceImplementation : public CommandObjectParsed {
@@ -269,6 +273,16 @@ void SBCommandInterpreter::HandleCommandsFromFile(
int SBCommandInterpreter::HandleCompletion(
const char *current_line, const char *cursor, const char *last_char,
int match_start_point, int max_return_elements, SBStringList &matches) {
+ SBStringList dummy_descriptions;
+ return HandleCompletionWithDescriptions(
+ current_line, cursor, last_char, match_start_point, max_return_elements,
+ matches, dummy_descriptions);
+}
+
+int SBCommandInterpreter::HandleCompletionWithDescriptions(
+ const char *current_line, const char *cursor, const char *last_char,
+ int match_start_point, int max_return_elements, SBStringList &matches,
+ SBStringList &descriptions) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
int num_completions = 0;
@@ -296,13 +310,15 @@ int SBCommandInterpreter::HandleCompletion(
match_start_point, max_return_elements);
if (IsValid()) {
- lldb_private::StringList lldb_matches;
+ lldb_private::StringList lldb_matches, lldb_descriptions;
num_completions = m_opaque_ptr->HandleCompletion(
current_line, cursor, last_char, match_start_point, max_return_elements,
- lldb_matches);
+ lldb_matches, lldb_descriptions);
- SBStringList temp_list(&lldb_matches);
- matches.AppendList(temp_list);
+ SBStringList temp_matches_list(&lldb_matches);
+ matches.AppendList(temp_matches_list);
+ SBStringList temp_descriptions_list(&lldb_descriptions);
+ descriptions.AppendList(temp_descriptions_list);
}
if (log)
log->Printf(
@@ -312,6 +328,17 @@ int SBCommandInterpreter::HandleCompletion(
return num_completions;
}
+int SBCommandInterpreter::HandleCompletionWithDescriptions(
+ const char *current_line, uint32_t cursor_pos, int match_start_point,
+ int max_return_elements, SBStringList &matches,
+ SBStringList &descriptions) {
+ const char *cursor = current_line + cursor_pos;
+ const char *last_char = current_line + strlen(current_line);
+ return HandleCompletionWithDescriptions(
+ current_line, cursor, last_char, match_start_point, max_return_elements,
+ matches, descriptions);
+}
+
int SBCommandInterpreter::HandleCompletion(const char *current_line,
uint32_t cursor_pos,
int match_start_point,
diff --git a/source/API/SBCommandReturnObject.cpp b/source/API/SBCommandReturnObject.cpp
index 5a8909b98e53..7bc02985a3ec 100644
--- a/source/API/SBCommandReturnObject.cpp
+++ b/source/API/SBCommandReturnObject.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBStream.h"
@@ -52,9 +48,7 @@ operator=(const SBCommandReturnObject &rhs) {
return *this;
}
-bool SBCommandReturnObject::IsValid() const {
- return m_opaque_ap.get() != nullptr;
-}
+bool SBCommandReturnObject::IsValid() const { return m_opaque_ap != nullptr; }
const char *SBCommandReturnObject::GetOutput() {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
diff --git a/source/API/SBCompileUnit.cpp b/source/API/SBCompileUnit.cpp
index 149d587913e9..4e2fc6af460a 100644
--- a/source/API/SBCompileUnit.cpp
+++ b/source/API/SBCompileUnit.cpp
@@ -135,17 +135,21 @@ uint32_t SBCompileUnit::GetNumSupportFiles() const {
lldb::SBTypeList SBCompileUnit::GetTypes(uint32_t type_mask) {
SBTypeList sb_type_list;
- if (m_opaque_ptr) {
- ModuleSP module_sp(m_opaque_ptr->GetModule());
- if (module_sp) {
- SymbolVendor *vendor = module_sp->GetSymbolVendor();
- if (vendor) {
- TypeList type_list;
- vendor->GetTypes(m_opaque_ptr, type_mask, type_list);
- sb_type_list.m_opaque_ap->Append(type_list);
- }
- }
- }
+ if (!m_opaque_ptr)
+ return sb_type_list;
+
+ ModuleSP module_sp(m_opaque_ptr->GetModule());
+ if (!module_sp)
+ return sb_type_list;
+
+ SymbolVendor *vendor = module_sp->GetSymbolVendor();
+ if (!vendor)
+ return sb_type_list;
+
+ TypeClass type_class = static_cast<TypeClass>(type_mask);
+ TypeList type_list;
+ vendor->GetTypes(m_opaque_ptr, type_class, type_list);
+ sb_type_list.m_opaque_ap->Append(type_list);
return sb_type_list;
}
diff --git a/source/API/SBData.cpp b/source/API/SBData.cpp
index a8ba5808d4f6..a30a778a19d2 100644
--- a/source/API/SBData.cpp
+++ b/source/API/SBData.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h> // PRIu64
+#include <inttypes.h>
#include "lldb/API/SBData.h"
#include "lldb/API/SBError.h"
diff --git a/source/API/SBDebugger.cpp b/source/API/SBDebugger.cpp
index a651141003a4..af343233c90e 100644
--- a/source/API/SBDebugger.cpp
+++ b/source/API/SBDebugger.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "SystemInitializerFull.h"
@@ -41,7 +37,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/DataFormatters/DataVisualization.h"
@@ -53,6 +48,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/State.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -90,7 +86,7 @@ static llvm::sys::DynamicLibrary LoadPlugin(const lldb::DebuggerSP &debugger_sp,
"lldb::PluginInitialize(lldb::SBDebugger)");
}
} else {
- if (spec.Exists())
+ if (FileSystem::Instance().Exists(spec))
error.SetErrorString("this file does not represent a loadable dylib");
else
error.SetErrorString("no such file");
@@ -129,13 +125,23 @@ SBDebugger &SBDebugger::operator=(const SBDebugger &rhs) {
}
void SBDebugger::Initialize() {
+ SBInitializerOptions options;
+ SBDebugger::Initialize(options);
+}
+
+lldb::SBError SBDebugger::Initialize(SBInitializerOptions &options) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
if (log)
log->Printf("SBDebugger::Initialize ()");
- g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerFull>(),
- LoadPlugin);
+ SBError error;
+ if (auto e = g_debugger_lifetime->Initialize(
+ llvm::make_unique<SystemInitializerFull>(), *options.m_opaque_up,
+ LoadPlugin)) {
+ error.SetError(Status(std::move(e)));
+ }
+ return error;
}
void SBDebugger::Terminate() { g_debugger_lifetime->Terminate(); }
@@ -558,7 +564,8 @@ lldb::SBTarget SBDebugger::CreateTarget(const char *filename,
platform_options.SetPlatformName(platform_name);
sb_error.ref() = m_opaque_sp->GetTargetList().CreateTarget(
- *m_opaque_sp, filename, target_triple, add_dependent_modules,
+ *m_opaque_sp, filename, target_triple,
+ add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo,
&platform_options, target_sp);
if (sb_error.Success())
@@ -587,7 +594,8 @@ SBDebugger::CreateTargetWithFileAndTargetTriple(const char *filename,
if (m_opaque_sp) {
const bool add_dependent_modules = true;
Status error(m_opaque_sp->GetTargetList().CreateTarget(
- *m_opaque_sp, filename, target_triple, add_dependent_modules, nullptr,
+ *m_opaque_sp, filename, target_triple,
+ add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
target_sp));
sb_target.SetSP(target_sp);
}
@@ -613,7 +621,8 @@ SBTarget SBDebugger::CreateTargetWithFileAndArch(const char *filename,
const bool add_dependent_modules = true;
error = m_opaque_sp->GetTargetList().CreateTarget(
- *m_opaque_sp, filename, arch_cstr, add_dependent_modules, nullptr,
+ *m_opaque_sp, filename, arch_cstr,
+ add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
target_sp);
if (error.Success()) {
@@ -638,7 +647,9 @@ SBTarget SBDebugger::CreateTarget(const char *filename) {
Status error;
const bool add_dependent_modules = true;
error = m_opaque_sp->GetTargetList().CreateTarget(
- *m_opaque_sp, filename, "", add_dependent_modules, nullptr, target_sp);
+ *m_opaque_sp, filename, "",
+ add_dependent_modules ? eLoadDependentsYes : eLoadDependentsNo, nullptr,
+ target_sp);
if (error.Success()) {
m_opaque_sp->GetTargetList().SetSelectedTarget(target_sp.get());
@@ -730,7 +741,7 @@ SBTarget SBDebugger::FindTargetWithFileAndArch(const char *filename,
m_opaque_sp->GetPlatformList().GetSelectedPlatform().get(), arch_name);
TargetSP target_sp(
m_opaque_sp->GetTargetList().FindTargetWithExecutableAndArchitecture(
- FileSpec(filename, false), arch_name ? &arch : nullptr));
+ FileSpec(filename), arch_name ? &arch : nullptr));
sb_target.SetSP(target_sp);
}
return sb_target;
@@ -1050,6 +1061,12 @@ void SBDebugger::SetPrompt(const char *prompt) {
m_opaque_sp->SetPrompt(llvm::StringRef::withNullAsEmpty(prompt));
}
+const char *SBDebugger::GetReproducerPath() const {
+ return (m_opaque_sp
+ ? ConstString(m_opaque_sp->GetReproducerPath()).GetCString()
+ : nullptr);
+}
+
ScriptLanguage SBDebugger::GetScriptLanguage() const {
return (m_opaque_sp ? m_opaque_sp->GetScriptLanguage() : eScriptLanguageNone);
}
diff --git a/source/API/SBDeclaration.cpp b/source/API/SBDeclaration.cpp
index d6e61e32582d..90e4db367d2a 100644
--- a/source/API/SBDeclaration.cpp
+++ b/source/API/SBDeclaration.cpp
@@ -75,7 +75,7 @@ uint32_t SBDeclaration::GetLine() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
uint32_t line = 0;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
line = m_opaque_ap->GetLine();
if (log)
@@ -86,7 +86,7 @@ uint32_t SBDeclaration::GetLine() const {
}
uint32_t SBDeclaration::GetColumn() const {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetColumn();
return 0;
}
@@ -126,7 +126,7 @@ const lldb_private::Declaration *SBDeclaration::operator->() const {
}
lldb_private::Declaration &SBDeclaration::ref() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new lldb_private::Declaration());
return *m_opaque_ap;
}
@@ -138,7 +138,7 @@ const lldb_private::Declaration &SBDeclaration::ref() const {
bool SBDeclaration::GetDescription(SBStream &description) {
Stream &strm = description.ref();
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
char file_path[PATH_MAX * 2];
m_opaque_ap->GetFile().GetPath(file_path, sizeof(file_path));
strm.Printf("%s:%u", file_path, GetLine());
diff --git a/source/API/SBError.cpp b/source/API/SBError.cpp
index b2811d0ac381..04433bb1aab0 100644
--- a/source/API/SBError.cpp
+++ b/source/API/SBError.cpp
@@ -28,7 +28,7 @@ SBError::~SBError() {}
const SBError &SBError::operator=(const SBError &rhs) {
if (rhs.IsValid()) {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
*m_opaque_ap = *rhs;
else
m_opaque_ap.reset(new Status(*rhs));
@@ -39,13 +39,13 @@ const SBError &SBError::operator=(const SBError &rhs) {
}
const char *SBError::GetCString() const {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->AsCString();
return NULL;
}
void SBError::Clear() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->Clear();
}
@@ -53,7 +53,7 @@ bool SBError::Fail() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
bool ret_value = false;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
ret_value = m_opaque_ap->Fail();
if (log)
@@ -66,7 +66,7 @@ bool SBError::Fail() const {
bool SBError::Success() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
bool ret_value = true;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
ret_value = m_opaque_ap->Success();
if (log)
@@ -80,7 +80,7 @@ uint32_t SBError::GetError() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
uint32_t err = 0;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
err = m_opaque_ap->GetError();
if (log)
@@ -93,7 +93,7 @@ uint32_t SBError::GetError() const {
ErrorType SBError::GetType() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
ErrorType err_type = eErrorTypeInvalid;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
err_type = m_opaque_ap->GetType();
if (log)
@@ -137,10 +137,10 @@ int SBError::SetErrorStringWithFormat(const char *format, ...) {
return num_chars;
}
-bool SBError::IsValid() const { return m_opaque_ap.get() != NULL; }
+bool SBError::IsValid() const { return m_opaque_ap != NULL; }
void SBError::CreateIfNeeded() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new Status());
}
@@ -159,7 +159,7 @@ const lldb_private::Status &SBError::operator*() const {
}
bool SBError::GetDescription(SBStream &description) {
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
if (m_opaque_ap->Success())
description.Printf("success");
else {
diff --git a/source/API/SBEvent.cpp b/source/API/SBEvent.cpp
index 65eb71c09285..0556f50f6544 100644
--- a/source/API/SBEvent.cpp
+++ b/source/API/SBEvent.cpp
@@ -12,11 +12,11 @@
#include "lldb/API/SBStream.h"
#include "lldb/Breakpoint/Breakpoint.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Stream.h"
using namespace lldb;
diff --git a/source/API/SBExpressionOptions.cpp b/source/API/SBExpressionOptions.cpp
index e26fa11651e5..76cec876a216 100644
--- a/source/API/SBExpressionOptions.cpp
+++ b/source/API/SBExpressionOptions.cpp
@@ -159,6 +159,15 @@ void SBExpressionOptions::SetTopLevel(bool b) {
: m_opaque_ap->default_execution_policy);
}
+bool SBExpressionOptions::GetAllowJIT() {
+ return m_opaque_ap->GetExecutionPolicy() != eExecutionPolicyNever;
+}
+
+void SBExpressionOptions::SetAllowJIT(bool allow) {
+ m_opaque_ap->SetExecutionPolicy(allow ? m_opaque_ap->default_execution_policy
+ : eExecutionPolicyNever);
+}
+
EvaluateExpressionOptions *SBExpressionOptions::get() const {
return m_opaque_ap.get();
}
diff --git a/source/API/SBFileSpec.cpp b/source/API/SBFileSpec.cpp
index 011b88225ef9..f136409d0b68 100644
--- a/source/API/SBFileSpec.cpp
+++ b/source/API/SBFileSpec.cpp
@@ -7,11 +7,12 @@
//
//===----------------------------------------------------------------------===//
-#include <inttypes.h> // PRIu64
+#include <inttypes.h>
#include <limits.h>
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBStream.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
@@ -31,11 +32,15 @@ SBFileSpec::SBFileSpec(const lldb_private::FileSpec &fspec)
: m_opaque_ap(new lldb_private::FileSpec(fspec)) {}
// Deprecated!!!
-SBFileSpec::SBFileSpec(const char *path)
- : m_opaque_ap(new FileSpec(path, true)) {}
+SBFileSpec::SBFileSpec(const char *path) : m_opaque_ap(new FileSpec(path)) {
+ FileSystem::Instance().Resolve(*m_opaque_ap);
+}
SBFileSpec::SBFileSpec(const char *path, bool resolve)
- : m_opaque_ap(new FileSpec(path, resolve)) {}
+ : m_opaque_ap(new FileSpec(path)) {
+ if (resolve)
+ FileSystem::Instance().Resolve(*m_opaque_ap);
+}
SBFileSpec::~SBFileSpec() {}
@@ -50,7 +55,7 @@ bool SBFileSpec::IsValid() const { return m_opaque_ap->operator bool(); }
bool SBFileSpec::Exists() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
- bool result = m_opaque_ap->Exists();
+ bool result = FileSystem::Instance().Exists(*m_opaque_ap);
if (log)
log->Printf("SBFileSpec(%p)::Exists () => %s",
@@ -61,13 +66,13 @@ bool SBFileSpec::Exists() const {
}
bool SBFileSpec::ResolveExecutableLocation() {
- return m_opaque_ap->ResolveExecutableLocation();
+ return FileSystem::Instance().ResolveExecutableLocation(*m_opaque_ap);
}
int SBFileSpec::ResolvePath(const char *src_path, char *dst_path,
size_t dst_len) {
llvm::SmallString<64> result(src_path);
- lldb_private::FileSpec::Resolve(result);
+ FileSystem::Instance().Resolve(result);
::snprintf(dst_path, dst_len, "%s", result.c_str());
return std::min(dst_len - 1, result.size());
}
@@ -143,12 +148,10 @@ const lldb_private::FileSpec *SBFileSpec::get() const {
}
const lldb_private::FileSpec &SBFileSpec::operator*() const {
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
-const lldb_private::FileSpec &SBFileSpec::ref() const {
- return *m_opaque_ap.get();
-}
+const lldb_private::FileSpec &SBFileSpec::ref() const { return *m_opaque_ap; }
void SBFileSpec::SetFileSpec(const lldb_private::FileSpec &fs) {
*m_opaque_ap = fs;
diff --git a/source/API/SBFileSpecList.cpp b/source/API/SBFileSpecList.cpp
index 67d28dcbe111..439859c3fd85 100644
--- a/source/API/SBFileSpecList.cpp
+++ b/source/API/SBFileSpecList.cpp
@@ -26,7 +26,7 @@ SBFileSpecList::SBFileSpecList() : m_opaque_ap(new FileSpecList()) {}
SBFileSpecList::SBFileSpecList(const SBFileSpecList &rhs) : m_opaque_ap() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
- if (rhs.m_opaque_ap.get())
+ if (rhs.m_opaque_ap)
m_opaque_ap.reset(new FileSpecList(*(rhs.get())));
if (log) {
@@ -78,17 +78,17 @@ const lldb_private::FileSpecList *SBFileSpecList::get() const {
}
const lldb_private::FileSpecList &SBFileSpecList::operator*() const {
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
const lldb_private::FileSpecList &SBFileSpecList::ref() const {
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
bool SBFileSpecList::GetDescription(SBStream &description) const {
Stream &strm = description.ref();
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
uint32_t num_files = m_opaque_ap->GetSize();
strm.Printf("%d files: ", num_files);
for (uint32_t i = 0; i < num_files; i++) {
diff --git a/source/API/SBFrame.cpp b/source/API/SBFrame.cpp
index 5762a75f33d6..44dcfd806be5 100644
--- a/source/API/SBFrame.cpp
+++ b/source/API/SBFrame.cpp
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <algorithm>
#include <set>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/API/SBFrame.h"
#include "lldb/lldb-types.h"
@@ -36,6 +32,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StackID.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -112,7 +109,7 @@ SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const {
SBSymbolContext sb_sym_ctx;
std::unique_lock<std::recursive_mutex> lock;
ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
-
+ SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
StackFrame *frame = nullptr;
Target *target = exe_ctx.GetTargetPtr();
Process *process = exe_ctx.GetProcessPtr();
@@ -121,7 +118,7 @@ SBSymbolContext SBFrame::GetSymbolContext(uint32_t resolve_scope) const {
if (stop_locker.TryLock(&process->GetRunLock())) {
frame = exe_ctx.GetFramePtr();
if (frame) {
- sb_sym_ctx.SetSymbolContext(&frame->GetSymbolContext(resolve_scope));
+ sb_sym_ctx.SetSymbolContext(&frame->GetSymbolContext(scope));
} else {
if (log)
log->Printf("SBFrame::GetVariables () => error: could not "
@@ -666,28 +663,10 @@ SBValue SBFrame::FindVariable(const char *name,
if (stop_locker.TryLock(&process->GetRunLock())) {
frame = exe_ctx.GetFramePtr();
if (frame) {
- VariableList variable_list;
- SymbolContext sc(frame->GetSymbolContext(eSymbolContextBlock));
-
- if (sc.block) {
- const bool can_create = true;
- const bool get_parent_variables = true;
- const bool stop_if_block_is_inlined_function = true;
+ value_sp = frame->FindVariable(ConstString(name));
- if (sc.block->AppendVariables(
- can_create, get_parent_variables,
- stop_if_block_is_inlined_function,
- [frame](Variable *v) { return v->IsInScope(frame); },
- &variable_list)) {
- var_sp = variable_list.FindVariable(ConstString(name));
- }
- }
-
- if (var_sp) {
- value_sp =
- frame->GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
+ if (value_sp)
sb_value.SetSP(value_sp, use_dynamic);
- }
} else {
if (log)
log->Printf("SBFrame::FindVariable () => error: could not "
@@ -978,6 +957,8 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
const bool statics = options.GetIncludeStatics();
const bool arguments = options.GetIncludeArguments();
+ const bool recognized_arguments =
+ options.GetIncludeRecognizedArguments(SBTarget(exe_ctx.GetTargetSP()));
const bool locals = options.GetIncludeLocals();
const bool in_scope_only = options.GetInScopeOnly();
const bool include_runtime_support_values =
@@ -985,10 +966,11 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
const lldb::DynamicValueType use_dynamic = options.GetUseDynamic();
if (log)
- log->Printf("SBFrame::GetVariables (arguments=%i, locals=%i, statics=%i, "
- "in_scope_only=%i runtime=%i dynamic=%i)",
- arguments, locals, statics, in_scope_only,
- include_runtime_support_values, use_dynamic);
+ log->Printf(
+ "SBFrame::GetVariables (arguments=%i, recognized_arguments=%i, "
+ "locals=%i, statics=%i, in_scope_only=%i runtime=%i dynamic=%i)",
+ arguments, recognized_arguments, locals, statics, in_scope_only,
+ include_runtime_support_values, use_dynamic);
std::set<VariableSP> variable_set;
Process *process = exe_ctx.GetProcessPtr();
@@ -1050,6 +1032,20 @@ SBValueList SBFrame::GetVariables(const lldb::SBVariablesOptions &options) {
}
}
}
+ if (recognized_arguments) {
+ auto recognized_frame = frame->GetRecognizedFrame();
+ if (recognized_frame) {
+ ValueObjectListSP recognized_arg_list =
+ recognized_frame->GetRecognizedArguments();
+ if (recognized_arg_list) {
+ for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
+ SBValue value_sb;
+ value_sb.SetSP(rec_value_sp, use_dynamic);
+ value_list.Append(value_sb);
+ }
+ }
+ }
+ }
} else {
if (log)
log->Printf("SBFrame::GetVariables () => error: could not "
@@ -1366,6 +1362,21 @@ bool SBFrame::IsInlined() const {
return false;
}
+bool SBFrame::IsArtificial() {
+ return static_cast<const SBFrame *>(this)->IsArtificial();
+}
+
+bool SBFrame::IsArtificial() const {
+ std::unique_lock<std::recursive_mutex> lock;
+ ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
+
+ StackFrame *frame = exe_ctx.GetFramePtr();
+ if (frame)
+ return frame->IsArtificial();
+
+ return false;
+}
+
const char *SBFrame::GetFunctionName() {
return static_cast<const SBFrame *>(this)->GetFunctionName();
}
diff --git a/source/API/SBHostOS.cpp b/source/API/SBHostOS.cpp
index e56951df43be..ac6ab40bda41 100644
--- a/source/API/SBHostOS.cpp
+++ b/source/API/SBHostOS.cpp
@@ -11,8 +11,9 @@
#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
#endif
-#include "lldb/API/SBHostOS.h"
#include "lldb/API/SBError.h"
+#include "lldb/API/SBHostOS.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostNativeThread.h"
@@ -86,7 +87,8 @@ SBFileSpec SBHostOS::GetUserHomeDirectory() {
llvm::SmallString<64> home_dir_path;
llvm::sys::path::home_directory(home_dir_path);
- FileSpec homedir(home_dir_path.c_str(), true);
+ FileSpec homedir(home_dir_path.c_str());
+ FileSystem::Instance().Resolve(homedir);
sb_fspec.SetFileSpec(homedir);
return sb_fspec;
diff --git a/source/API/SBInitializerOptions.cpp b/source/API/SBInitializerOptions.cpp
new file mode 100644
index 000000000000..8d8ec28190ec
--- /dev/null
+++ b/source/API/SBInitializerOptions.cpp
@@ -0,0 +1,49 @@
+//===-- SBInitializerOptions.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBInitializerOptions.h"
+#include "lldb/Initialization/SystemInitializer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+SBInitializerOptions::SBInitializerOptions(const SBInitializerOptions &rhs) {
+ m_opaque_up.reset(new InitializerOptions());
+ *(m_opaque_up.get()) = rhs.ref();
+}
+
+const SBInitializerOptions &SBInitializerOptions::
+operator=(const SBInitializerOptions &rhs) {
+ if (this != &rhs) {
+ this->ref() = rhs.ref();
+ }
+ return *this;
+}
+
+SBInitializerOptions::~SBInitializerOptions() {}
+
+SBInitializerOptions::SBInitializerOptions() {
+ m_opaque_up.reset(new InitializerOptions());
+}
+
+void SBInitializerOptions::SetCaptureReproducer(bool b) {
+ m_opaque_up->reproducer_capture = b;
+}
+
+void SBInitializerOptions::SetReplayReproducer(bool b) {
+ m_opaque_up->reproducer_replay = b;
+}
+
+void SBInitializerOptions::SetReproducerPath(const char *path) {
+ m_opaque_up->reproducer_path = path;
+}
+
+InitializerOptions &SBInitializerOptions::ref() const {
+ return *(m_opaque_up.get());
+}
diff --git a/source/API/SBLaunchInfo.cpp b/source/API/SBLaunchInfo.cpp
index aa1759ab3d00..b1bbfa55d5c1 100644
--- a/source/API/SBLaunchInfo.cpp
+++ b/source/API/SBLaunchInfo.cpp
@@ -128,7 +128,7 @@ const char *SBLaunchInfo::GetWorkingDirectory() const {
}
void SBLaunchInfo::SetWorkingDirectory(const char *working_dir) {
- m_opaque_sp->SetWorkingDirectory(FileSpec{working_dir, false});
+ m_opaque_sp->SetWorkingDirectory(FileSpec(working_dir));
}
uint32_t SBLaunchInfo::GetLaunchFlags() {
@@ -155,7 +155,7 @@ const char *SBLaunchInfo::GetShell() {
}
void SBLaunchInfo::SetShell(const char *path) {
- m_opaque_sp->SetShell(FileSpec(path, false));
+ m_opaque_sp->SetShell(FileSpec(path));
}
bool SBLaunchInfo::GetShellExpandArguments() {
@@ -184,8 +184,7 @@ bool SBLaunchInfo::AddDuplicateFileAction(int fd, int dup_fd) {
bool SBLaunchInfo::AddOpenFileAction(int fd, const char *path, bool read,
bool write) {
- return m_opaque_sp->AppendOpenFileAction(fd, FileSpec{path, false}, read,
- write);
+ return m_opaque_sp->AppendOpenFileAction(fd, FileSpec(path), read, write);
}
bool SBLaunchInfo::AddSuppressFileAction(int fd, bool read, bool write) {
diff --git a/source/API/SBLineEntry.cpp b/source/API/SBLineEntry.cpp
index 7341d3603dfe..6f59fe3407e8 100644
--- a/source/API/SBLineEntry.cpp
+++ b/source/API/SBLineEntry.cpp
@@ -50,7 +50,7 @@ SBLineEntry::~SBLineEntry() {}
SBAddress SBLineEntry::GetStartAddress() const {
SBAddress sb_address;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
sb_address.SetAddress(&m_opaque_ap->range.GetBaseAddress());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
@@ -70,7 +70,7 @@ SBAddress SBLineEntry::GetStartAddress() const {
SBAddress SBLineEntry::GetEndAddress() const {
SBAddress sb_address;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
sb_address.SetAddress(&m_opaque_ap->range.GetBaseAddress());
sb_address.OffsetAddress(m_opaque_ap->range.GetByteSize());
}
@@ -114,7 +114,7 @@ uint32_t SBLineEntry::GetLine() const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
uint32_t line = 0;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
line = m_opaque_ap->line;
if (log)
@@ -125,7 +125,7 @@ uint32_t SBLineEntry::GetLine() const {
}
uint32_t SBLineEntry::GetColumn() const {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->column;
return 0;
}
@@ -165,7 +165,7 @@ const lldb_private::LineEntry *SBLineEntry::operator->() const {
}
lldb_private::LineEntry &SBLineEntry::ref() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new lldb_private::LineEntry());
return *m_opaque_ap;
}
@@ -175,7 +175,7 @@ const lldb_private::LineEntry &SBLineEntry::ref() const { return *m_opaque_ap; }
bool SBLineEntry::GetDescription(SBStream &description) {
Stream &strm = description.ref();
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
char file_path[PATH_MAX * 2];
m_opaque_ap->file.GetPath(file_path, sizeof(file_path));
strm.Printf("%s:%u", file_path, GetLine());
diff --git a/source/API/SBListener.cpp b/source/API/SBListener.cpp
index 50fed4e1ee7b..e671d9f2ce8c 100644
--- a/source/API/SBListener.cpp
+++ b/source/API/SBListener.cpp
@@ -12,9 +12,9 @@
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBStream.h"
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Listener.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Listener.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
diff --git a/source/API/SBMemoryRegionInfoList.cpp b/source/API/SBMemoryRegionInfoList.cpp
index fff4044f73e0..1cefc9dcc044 100644
--- a/source/API/SBMemoryRegionInfoList.cpp
+++ b/source/API/SBMemoryRegionInfoList.cpp
@@ -32,31 +32,47 @@ public:
return *this;
}
- uint32_t GetSize() { return m_regions.size(); }
+ size_t GetSize() const { return m_regions.size(); }
- void Append(const lldb::SBMemoryRegionInfo &sb_region) {
+ void Reserve(size_t capacity) { return m_regions.reserve(capacity); }
+
+ void Append(const MemoryRegionInfo &sb_region) {
m_regions.push_back(sb_region);
}
void Append(const MemoryRegionInfoListImpl &list) {
- for (auto val : list.m_regions)
+ Reserve(GetSize() + list.GetSize());
+
+ for (const auto &val : list.m_regions)
Append(val);
}
void Clear() { m_regions.clear(); }
- bool GetMemoryRegionInfoAtIndex(uint32_t index,
- SBMemoryRegionInfo &region_info) {
+ bool GetMemoryRegionInfoAtIndex(size_t index,
+ MemoryRegionInfo &region_info) {
if (index >= GetSize())
return false;
region_info = m_regions[index];
return true;
}
+ MemoryRegionInfos &Ref() { return m_regions; }
+
+ const MemoryRegionInfos &Ref() const { return m_regions; }
+
private:
- std::vector<lldb::SBMemoryRegionInfo> m_regions;
+ MemoryRegionInfos m_regions;
};
+MemoryRegionInfos &SBMemoryRegionInfoList::ref() {
+ return m_opaque_ap->Ref();
+}
+
+const MemoryRegionInfos &SBMemoryRegionInfoList::ref() const {
+ return m_opaque_ap->Ref();
+}
+
SBMemoryRegionInfoList::SBMemoryRegionInfoList()
: m_opaque_ap(new MemoryRegionInfoListImpl()) {}
@@ -82,7 +98,7 @@ bool SBMemoryRegionInfoList::GetMemoryRegionAtIndex(
uint32_t idx, SBMemoryRegionInfo &region_info) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
- bool result = m_opaque_ap->GetMemoryRegionInfoAtIndex(idx, region_info);
+ bool result = m_opaque_ap->GetMemoryRegionInfoAtIndex(idx, region_info.ref());
if (log) {
SBStream sstr;
@@ -100,7 +116,7 @@ bool SBMemoryRegionInfoList::GetMemoryRegionAtIndex(
void SBMemoryRegionInfoList::Clear() { m_opaque_ap->Clear(); }
void SBMemoryRegionInfoList::Append(SBMemoryRegionInfo &sb_region) {
- m_opaque_ap->Append(sb_region);
+ m_opaque_ap->Append(sb_region.ref());
}
void SBMemoryRegionInfoList::Append(SBMemoryRegionInfoList &sb_region_list) {
@@ -113,5 +129,5 @@ const MemoryRegionInfoListImpl *SBMemoryRegionInfoList::operator->() const {
const MemoryRegionInfoListImpl &SBMemoryRegionInfoList::operator*() const {
assert(m_opaque_ap.get());
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
diff --git a/source/API/SBModule.cpp b/source/API/SBModule.cpp
index 3dd99d5321b4..31980793bce0 100644
--- a/source/API/SBModule.cpp
+++ b/source/API/SBModule.cpp
@@ -217,9 +217,9 @@ SBModule::ResolveSymbolContextForAddress(const SBAddress &addr,
uint32_t resolve_scope) {
SBSymbolContext sb_sc;
ModuleSP module_sp(GetSP());
+ SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
if (module_sp && addr.IsValid())
- module_sp->ResolveSymbolContextForAddress(addr.ref(), resolve_scope,
- *sb_sc);
+ module_sp->ResolveSymbolContextForAddress(addr.ref(), scope, *sb_sc);
return sb_sc;
}
@@ -365,8 +365,9 @@ lldb::SBSymbolContextList SBModule::FindFunctions(const char *name,
const bool append = true;
const bool symbols_ok = true;
const bool inlines_ok = true;
- module_sp->FindFunctions(ConstString(name), NULL, name_type_mask,
- symbols_ok, inlines_ok, append, *sb_sc_list);
+ FunctionNameType type = static_cast<FunctionNameType>(name_type_mask);
+ module_sp->FindFunctions(ConstString(name), NULL, type, symbols_ok,
+ inlines_ok, append, *sb_sc_list);
}
return sb_sc_list;
}
@@ -439,13 +440,12 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) {
ModuleSP module_sp(GetSP());
if (type && module_sp) {
- SymbolContext sc;
TypeList type_list;
const bool exact_match = false;
ConstString name(type);
llvm::DenseSet<SymbolFile *> searched_symbol_files;
const uint32_t num_matches = module_sp->FindTypes(
- sc, name, exact_match, UINT32_MAX, searched_symbol_files, type_list);
+ name, exact_match, UINT32_MAX, searched_symbol_files, type_list);
if (num_matches > 0) {
for (size_t idx = 0; idx < num_matches; idx++) {
@@ -484,14 +484,16 @@ lldb::SBTypeList SBModule::GetTypes(uint32_t type_mask) {
SBTypeList sb_type_list;
ModuleSP module_sp(GetSP());
- if (module_sp) {
- SymbolVendor *vendor = module_sp->GetSymbolVendor();
- if (vendor) {
- TypeList type_list;
- vendor->GetTypes(NULL, type_mask, type_list);
- sb_type_list.m_opaque_ap->Append(type_list);
- }
- }
+ if (!module_sp)
+ return sb_type_list;
+ SymbolVendor *vendor = module_sp->GetSymbolVendor();
+ if (!vendor)
+ return sb_type_list;
+
+ TypeClass type_class = static_cast<TypeClass>(type_mask);
+ TypeList type_list;
+ vendor->GetTypes(NULL, type_class, type_list);
+ sb_type_list.m_opaque_ap->Append(type_list);
return sb_type_list;
}
@@ -584,7 +586,18 @@ lldb::SBAddress SBModule::GetObjectFileHeaderAddress() const {
if (module_sp) {
ObjectFile *objfile_ptr = module_sp->GetObjectFile();
if (objfile_ptr)
- sb_addr.ref() = objfile_ptr->GetHeaderAddress();
+ sb_addr.ref() = objfile_ptr->GetBaseAddress();
+ }
+ return sb_addr;
+}
+
+lldb::SBAddress SBModule::GetObjectFileEntryPointAddress() const {
+ lldb::SBAddress sb_addr;
+ ModuleSP module_sp(GetSP());
+ if (module_sp) {
+ ObjectFile *objfile_ptr = module_sp->GetObjectFile();
+ if (objfile_ptr)
+ sb_addr.ref() = objfile_ptr->GetEntryPointAddress();
}
return sb_addr;
}
diff --git a/source/API/SBModuleSpec.cpp b/source/API/SBModuleSpec.cpp
index afabd9ace2b9..65492f58b015 100644
--- a/source/API/SBModuleSpec.cpp
+++ b/source/API/SBModuleSpec.cpp
@@ -114,7 +114,8 @@ SBModuleSpecList::~SBModuleSpecList() {}
SBModuleSpecList SBModuleSpecList::GetModuleSpecifications(const char *path) {
SBModuleSpecList specs;
- FileSpec file_spec(path, true);
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
Host::ResolveExecutableInBundle(file_spec);
ObjectFile::GetModuleSpecifications(file_spec, 0, 0, *specs.m_opaque_ap);
return specs;
diff --git a/source/API/SBPlatform.cpp b/source/API/SBPlatform.cpp
index 5f29f0033988..aedad871cd20 100644
--- a/source/API/SBPlatform.cpp
+++ b/source/API/SBPlatform.cpp
@@ -244,9 +244,9 @@ bool SBPlatform::SetWorkingDirectory(const char *path) {
PlatformSP platform_sp(GetSP());
if (platform_sp) {
if (path)
- platform_sp->SetWorkingDirectory(FileSpec{path, false});
+ platform_sp->SetWorkingDirectory(FileSpec(path));
else
- platform_sp->SetWorkingDirectory(FileSpec{});
+ platform_sp->SetWorkingDirectory(FileSpec());
return true;
}
return false;
@@ -364,9 +364,9 @@ SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {
return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
if (src.Exists()) {
- uint32_t permissions = src.ref().GetPermissions();
+ uint32_t permissions = FileSystem::Instance().GetPermissions(src.ref());
if (permissions == 0) {
- if (llvm::sys::fs::is_directory(src.ref().GetPath()))
+ if (FileSystem::Instance().IsDirectory(src.ref()))
permissions = eFilePermissionsDirectoryDefault;
else
permissions = eFilePermissionsFileDefault;
@@ -406,7 +406,7 @@ SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
if (working_dir)
shell_command.SetWorkingDirectory(working_dir);
}
- return platform_sp->RunShellCommand(command, FileSpec{working_dir, false},
+ return platform_sp->RunShellCommand(command, FileSpec(working_dir),
&shell_command.m_opaque_ptr->m_status,
&shell_command.m_opaque_ptr->m_signo,
&shell_command.m_opaque_ptr->m_output,
@@ -449,7 +449,7 @@ SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {
PlatformSP platform_sp(GetSP());
if (platform_sp) {
sb_error.ref() =
- platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions);
+ platform_sp->MakeDirectory(FileSpec(path), file_permissions);
} else {
sb_error.SetErrorString("invalid platform");
}
@@ -460,7 +460,7 @@ uint32_t SBPlatform::GetFilePermissions(const char *path) {
PlatformSP platform_sp(GetSP());
if (platform_sp) {
uint32_t file_permissions = 0;
- platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions);
+ platform_sp->GetFilePermissions(FileSpec(path), file_permissions);
return file_permissions;
}
return 0;
@@ -471,8 +471,8 @@ SBError SBPlatform::SetFilePermissions(const char *path,
SBError sb_error;
PlatformSP platform_sp(GetSP());
if (platform_sp) {
- sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false},
- file_permissions);
+ sb_error.ref() =
+ platform_sp->SetFilePermissions(FileSpec(path), file_permissions);
} else {
sb_error.SetErrorString("invalid platform");
}
diff --git a/source/API/SBProcess.cpp b/source/API/SBProcess.cpp
index 4d5ddc86ccf9..cb1124607ec0 100644
--- a/source/API/SBProcess.cpp
+++ b/source/API/SBProcess.cpp
@@ -9,7 +9,6 @@
#include "lldb/API/SBProcess.h"
-// C Includes
#include <inttypes.h>
#include "lldb/lldb-defines.h"
@@ -18,7 +17,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
@@ -28,9 +26,9 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
-// Project includes
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBCommandReturnObject.h"
@@ -130,10 +128,9 @@ bool SBProcess::RemoteLaunch(char const **argv, char const **envp,
if (process_sp->GetState() == eStateConnected) {
if (stop_at_entry)
launch_flags |= eLaunchFlagStopAtEntry;
- ProcessLaunchInfo launch_info(
- FileSpec{stdin_path, false}, FileSpec{stdout_path, false},
- FileSpec{stderr_path, false}, FileSpec{working_directory, false},
- launch_flags);
+ ProcessLaunchInfo launch_info(FileSpec(stdin_path), FileSpec(stdout_path),
+ FileSpec(stderr_path),
+ FileSpec(working_directory), launch_flags);
Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer();
if (exe_module)
launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
@@ -1351,7 +1348,7 @@ lldb::SBError SBProcess::SaveCore(const char *file_name) {
return error;
}
- FileSpec core_file(file_name, false);
+ FileSpec core_file(file_name);
error.ref() = PluginManager::SaveCore(process_sp, core_file);
return error;
}
@@ -1361,18 +1358,14 @@ SBProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
SBMemoryRegionInfo &sb_region_info) {
lldb::SBError sb_error;
ProcessSP process_sp(GetSP());
- MemoryRegionInfoSP region_info_sp =
- std::make_shared<lldb_private::MemoryRegionInfo>();
if (process_sp) {
Process::StopLocker stop_locker;
if (stop_locker.TryLock(&process_sp->GetRunLock())) {
std::lock_guard<std::recursive_mutex> guard(
process_sp->GetTarget().GetAPIMutex());
+
sb_error.ref() =
- process_sp->GetMemoryRegionInfo(load_addr, *region_info_sp);
- if (sb_error.Success()) {
- sb_region_info.ref() = *region_info_sp;
- }
+ process_sp->GetMemoryRegionInfo(load_addr, sb_region_info.ref());
} else {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
if (log)
@@ -1388,35 +1381,23 @@ SBProcess::GetMemoryRegionInfo(lldb::addr_t load_addr,
}
lldb::SBMemoryRegionInfoList SBProcess::GetMemoryRegions() {
- lldb::SBError sb_error;
lldb::SBMemoryRegionInfoList sb_region_list;
+
ProcessSP process_sp(GetSP());
- if (process_sp) {
- Process::StopLocker stop_locker;
- if (stop_locker.TryLock(&process_sp->GetRunLock())) {
- std::lock_guard<std::recursive_mutex> guard(
- process_sp->GetTarget().GetAPIMutex());
- std::vector<MemoryRegionInfoSP> region_list;
- sb_error.ref() = process_sp->GetMemoryRegions(region_list);
- if (sb_error.Success()) {
- std::vector<MemoryRegionInfoSP>::iterator end = region_list.end();
- for (std::vector<MemoryRegionInfoSP>::iterator it = region_list.begin();
- it != end; it++) {
- SBMemoryRegionInfo sb_region_info(it->get());
- sb_region_list.Append(sb_region_info);
- }
- }
- } else {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
- if (log)
- log->Printf(
- "SBProcess(%p)::GetMemoryRegionInfo() => error: process is running",
- static_cast<void *>(process_sp.get()));
- sb_error.SetErrorString("process is running");
- }
+ Process::StopLocker stop_locker;
+ if (process_sp && stop_locker.TryLock(&process_sp->GetRunLock())) {
+ std::lock_guard<std::recursive_mutex> guard(
+ process_sp->GetTarget().GetAPIMutex());
+
+ process_sp->GetMemoryRegions(sb_region_list.ref());
} else {
- sb_error.SetErrorString("SBProcess is invalid");
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ if (log)
+ log->Printf(
+ "SBProcess(%p)::GetMemoryRegionInfo() => error: process is running",
+ static_cast<void *>(process_sp.get()));
}
+
return sb_region_list;
}
diff --git a/source/API/SBProcessInfo.cpp b/source/API/SBProcessInfo.cpp
index 38f6c1d1e699..2b3ebfb2465f 100644
--- a/source/API/SBProcessInfo.cpp
+++ b/source/API/SBProcessInfo.cpp
@@ -36,7 +36,7 @@ SBProcessInfo &SBProcessInfo::operator=(const SBProcessInfo &rhs) {
}
ProcessInstanceInfo &SBProcessInfo::ref() {
- if (m_opaque_ap.get() == nullptr) {
+ if (m_opaque_ap == nullptr) {
m_opaque_ap.reset(new ProcessInstanceInfo());
}
return *m_opaque_ap;
@@ -46,7 +46,7 @@ void SBProcessInfo::SetProcessInfo(const ProcessInstanceInfo &proc_info_ref) {
ref() = proc_info_ref;
}
-bool SBProcessInfo::IsValid() const { return m_opaque_ap.get() != nullptr; }
+bool SBProcessInfo::IsValid() const { return m_opaque_ap != nullptr; }
const char *SBProcessInfo::GetName() {
const char *name = nullptr;
diff --git a/source/API/SBQueue.cpp b/source/API/SBQueue.cpp
index 5f852111e077..b4a3cd0c52fb 100644
--- a/source/API/SBQueue.cpp
+++ b/source/API/SBQueue.cpp
@@ -107,7 +107,7 @@ public:
}
void FetchThreads() {
- if (m_thread_list_fetched == false) {
+ if (!m_thread_list_fetched) {
lldb::QueueSP queue_sp = m_queue_wp.lock();
if (queue_sp) {
Process::StopLocker stop_locker;
@@ -127,7 +127,7 @@ public:
}
void FetchItems() {
- if (m_pending_items_fetched == false) {
+ if (!m_pending_items_fetched) {
QueueSP queue_sp = m_queue_wp.lock();
if (queue_sp) {
Process::StopLocker stop_locker;
@@ -178,7 +178,7 @@ public:
uint32_t result = 0;
QueueSP queue_sp = m_queue_wp.lock();
- if (m_pending_items_fetched == false && queue_sp) {
+ if (!m_pending_items_fetched && queue_sp) {
result = queue_sp->GetNumPendingWorkItems();
} else {
result = m_pending_items.size();
diff --git a/source/API/SBSection.cpp b/source/API/SBSection.cpp
index 9da5d170da9e..7193857d1281 100644
--- a/source/API/SBSection.cpp
+++ b/source/API/SBSection.cpp
@@ -14,7 +14,6 @@
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/DataBuffer.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -166,7 +165,7 @@ SBData SBSection::GetSectionData(uint64_t offset, uint64_t size) {
else
file_size = 0;
}
- auto data_buffer_sp = DataBufferLLVM::CreateSliceFromPath(
+ auto data_buffer_sp = FileSystem::Instance().CreateDataBuffer(
objfile->GetFileSpec().GetPath(), file_size, file_offset);
if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0) {
DataExtractorSP data_extractor_sp(
diff --git a/source/API/SBSourceManager.cpp b/source/API/SBSourceManager.cpp
index 5804c22bacb8..1d47cc034e35 100644
--- a/source/API/SBSourceManager.cpp
+++ b/source/API/SBSourceManager.cpp
@@ -107,7 +107,7 @@ size_t SBSourceManager::DisplaySourceLinesWithLineNumbersAndColumn(
const SBFileSpec &file, uint32_t line, uint32_t column,
uint32_t context_before, uint32_t context_after,
const char *current_line_cstr, SBStream &s) {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
return 0;
return m_opaque_ap->DisplaySourceLinesWithLineNumbers(
diff --git a/source/API/SBStream.cpp b/source/API/SBStream.cpp
index d1af77a40fa3..876ef02170d2 100644
--- a/source/API/SBStream.cpp
+++ b/source/API/SBStream.cpp
@@ -10,6 +10,7 @@
#include "lldb/API/SBStream.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
@@ -24,12 +25,12 @@ SBStream::SBStream(SBStream &&rhs)
SBStream::~SBStream() {}
-bool SBStream::IsValid() const { return (m_opaque_ap.get() != NULL); }
+bool SBStream::IsValid() const { return (m_opaque_ap != NULL); }
// If this stream is not redirected to a file, it will maintain a local cache
// for the stream data which can be accessed using this accessor.
const char *SBStream::GetData() {
- if (m_is_file || m_opaque_ap.get() == NULL)
+ if (m_is_file || m_opaque_ap == NULL)
return NULL;
return static_cast<StreamString *>(m_opaque_ap.get())->GetData();
@@ -38,7 +39,7 @@ const char *SBStream::GetData() {
// If this stream is not redirected to a file, it will maintain a local cache
// for the stream output whose length can be accessed using this accessor.
size_t SBStream::GetSize() {
- if (m_is_file || m_opaque_ap.get() == NULL)
+ if (m_is_file || m_opaque_ap == NULL)
return 0;
return static_cast<StreamString *>(m_opaque_ap.get())->GetSize();
@@ -58,7 +59,7 @@ void SBStream::RedirectToFile(const char *path, bool append) {
return;
std::string local_data;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
// See if we have any locally backed data. If so, copy it so we can then
// redirect it to the file so we don't lose the data
if (!m_is_file)
@@ -70,12 +71,12 @@ void SBStream::RedirectToFile(const char *path, bool append) {
open_options |= File::eOpenOptionAppend;
else
open_options |= File::eOpenOptionTruncate;
- stream_file->GetFile().Open(path, open_options,
- lldb::eFilePermissionsFileDefault);
+ FileSystem::Instance().Open(stream_file->GetFile(), FileSpec(path),
+ open_options);
m_opaque_ap.reset(stream_file);
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
m_is_file = true;
// If we had any data locally in our StreamString, then pass that along to
@@ -91,7 +92,7 @@ void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
return;
std::string local_data;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
// See if we have any locally backed data. If so, copy it so we can then
// redirect it to the file so we don't lose the data
if (!m_is_file)
@@ -99,7 +100,7 @@ void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
}
m_opaque_ap.reset(new StreamFile(fh, transfer_fh_ownership));
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
m_is_file = true;
// If we had any data locally in our StreamString, then pass that along to
@@ -112,7 +113,7 @@ void SBStream::RedirectToFileHandle(FILE *fh, bool transfer_fh_ownership) {
void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
std::string local_data;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
// See if we have any locally backed data. If so, copy it so we can then
// redirect it to the file so we don't lose the data
if (!m_is_file)
@@ -120,7 +121,7 @@ void SBStream::RedirectToFileDescriptor(int fd, bool transfer_fh_ownership) {
}
m_opaque_ap.reset(new StreamFile(::fdopen(fd, "w"), transfer_fh_ownership));
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
m_is_file = true;
// If we had any data locally in our StreamString, then pass that along to
@@ -136,13 +137,13 @@ lldb_private::Stream *SBStream::operator->() { return m_opaque_ap.get(); }
lldb_private::Stream *SBStream::get() { return m_opaque_ap.get(); }
lldb_private::Stream &SBStream::ref() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new StreamString());
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
void SBStream::Clear() {
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
// See if we have any locally backed data. If so, copy it so we can then
// redirect it to the file so we don't lose the data
if (m_is_file)
diff --git a/source/API/SBStringList.cpp b/source/API/SBStringList.cpp
index 9ac69b15ebb7..6ed4d4b7fb82 100644
--- a/source/API/SBStringList.cpp
+++ b/source/API/SBStringList.cpp
@@ -47,7 +47,7 @@ const lldb_private::StringList &SBStringList::operator*() const {
return *m_opaque_ap;
}
-bool SBStringList::IsValid() const { return (m_opaque_ap.get() != NULL); }
+bool SBStringList::IsValid() const { return (m_opaque_ap != NULL); }
void SBStringList::AppendString(const char *str) {
if (str != NULL) {
diff --git a/source/API/SBStructuredData.cpp b/source/API/SBStructuredData.cpp
index d506410f6d80..277193424e99 100644
--- a/source/API/SBStructuredData.cpp
+++ b/source/API/SBStructuredData.cpp
@@ -10,9 +10,10 @@
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBStream.h"
-#include "lldb/Core/Event.h"
+#include "lldb/API/SBStringList.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Target/StructuredDataPlugin.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StructuredData.h"
@@ -31,6 +32,9 @@ SBStructuredData::SBStructuredData(const lldb::SBStructuredData &rhs)
SBStructuredData::SBStructuredData(const lldb::EventSP &event_sp)
: m_impl_up(new StructuredDataImpl(event_sp)) {}
+SBStructuredData::SBStructuredData(lldb_private::StructuredDataImpl *impl)
+ : m_impl_up(impl) {}
+
SBStructuredData::~SBStructuredData() {}
SBStructuredData &SBStructuredData::
@@ -76,6 +80,33 @@ size_t SBStructuredData::GetSize() const {
return (m_impl_up ? m_impl_up->GetSize() : 0);
}
+bool SBStructuredData::GetKeys(lldb::SBStringList &keys) const {
+ if (!m_impl_up)
+ return false;
+
+ if (GetType() != eStructuredDataTypeDictionary)
+ return false;
+
+ StructuredData::ObjectSP obj_sp = m_impl_up->GetObjectSP();
+ if (!obj_sp)
+ return false;
+
+ StructuredData::Dictionary *dict = obj_sp->GetAsDictionary();
+ // We claimed we were a dictionary, so this can't be null.
+ assert(dict);
+ // The return kind of GetKeys is an Array:
+ StructuredData::ObjectSP array_sp = dict->GetKeys();
+ StructuredData::Array *key_arr = array_sp->GetAsArray();
+ assert(key_arr);
+
+ key_arr->ForEach([&keys] (StructuredData::Object *object) -> bool {
+ llvm::StringRef key = object->GetStringValue("");
+ keys.AppendString(key.str().c_str());
+ return true;
+ });
+ return true;
+}
+
lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const {
if (!m_impl_up)
return SBStructuredData();
diff --git a/source/API/SBSymbolContext.cpp b/source/API/SBSymbolContext.cpp
index 45dfffd916e7..ab70c6f6ca68 100644
--- a/source/API/SBSymbolContext.cpp
+++ b/source/API/SBSymbolContext.cpp
@@ -27,7 +27,7 @@ SBSymbolContext::SBSymbolContext(const SymbolContext *sc_ptr) : m_opaque_ap() {
SBSymbolContext::SBSymbolContext(const SBSymbolContext &rhs) : m_opaque_ap() {
if (rhs.IsValid()) {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
*m_opaque_ap = *rhs.m_opaque_ap;
else
ref() = *rhs.m_opaque_ap;
@@ -39,32 +39,31 @@ SBSymbolContext::~SBSymbolContext() {}
const SBSymbolContext &SBSymbolContext::operator=(const SBSymbolContext &rhs) {
if (this != &rhs) {
if (rhs.IsValid())
- m_opaque_ap.reset(
- new lldb_private::SymbolContext(*rhs.m_opaque_ap.get()));
+ m_opaque_ap.reset(new lldb_private::SymbolContext(*rhs.m_opaque_ap));
}
return *this;
}
void SBSymbolContext::SetSymbolContext(const SymbolContext *sc_ptr) {
if (sc_ptr) {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
*m_opaque_ap = *sc_ptr;
else
m_opaque_ap.reset(new SymbolContext(*sc_ptr));
} else {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->Clear(true);
}
}
-bool SBSymbolContext::IsValid() const { return m_opaque_ap.get() != NULL; }
+bool SBSymbolContext::IsValid() const { return m_opaque_ap != NULL; }
SBModule SBSymbolContext::GetModule() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
SBModule sb_module;
ModuleSP module_sp;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
module_sp = m_opaque_ap->module_sp;
sb_module.SetSP(module_sp);
}
@@ -81,7 +80,7 @@ SBModule SBSymbolContext::GetModule() {
}
SBCompileUnit SBSymbolContext::GetCompileUnit() {
- return SBCompileUnit(m_opaque_ap.get() ? m_opaque_ap->comp_unit : NULL);
+ return SBCompileUnit(m_opaque_ap ? m_opaque_ap->comp_unit : NULL);
}
SBFunction SBSymbolContext::GetFunction() {
@@ -89,7 +88,7 @@ SBFunction SBSymbolContext::GetFunction() {
Function *function = NULL;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
function = m_opaque_ap->function;
SBFunction sb_function(function);
@@ -103,14 +102,14 @@ SBFunction SBSymbolContext::GetFunction() {
}
SBBlock SBSymbolContext::GetBlock() {
- return SBBlock(m_opaque_ap.get() ? m_opaque_ap->block : NULL);
+ return SBBlock(m_opaque_ap ? m_opaque_ap->block : NULL);
}
SBLineEntry SBSymbolContext::GetLineEntry() {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
SBLineEntry sb_line_entry;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
sb_line_entry.SetLineEntry(m_opaque_ap->line_entry);
if (log) {
@@ -127,7 +126,7 @@ SBSymbol SBSymbolContext::GetSymbol() {
Symbol *symbol = NULL;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
symbol = m_opaque_ap->symbol;
SBSymbol sb_symbol(symbol);
@@ -173,19 +172,19 @@ lldb_private::SymbolContext *SBSymbolContext::operator->() const {
const lldb_private::SymbolContext &SBSymbolContext::operator*() const {
assert(m_opaque_ap.get());
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
lldb_private::SymbolContext &SBSymbolContext::operator*() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new SymbolContext);
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
lldb_private::SymbolContext &SBSymbolContext::ref() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new SymbolContext);
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
lldb_private::SymbolContext *SBSymbolContext::get() const {
@@ -195,7 +194,7 @@ lldb_private::SymbolContext *SBSymbolContext::get() const {
bool SBSymbolContext::GetDescription(SBStream &description) {
Stream &strm = description.ref();
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
m_opaque_ap->GetDescription(&strm, lldb::eDescriptionLevelFull, NULL);
} else
strm.PutCString("No value");
diff --git a/source/API/SBSymbolContextList.cpp b/source/API/SBSymbolContextList.cpp
index 8cc29c3422d0..b07ab2afd554 100644
--- a/source/API/SBSymbolContextList.cpp
+++ b/source/API/SBSymbolContextList.cpp
@@ -31,14 +31,14 @@ operator=(const SBSymbolContextList &rhs) {
}
uint32_t SBSymbolContextList::GetSize() const {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetSize();
return 0;
}
SBSymbolContext SBSymbolContextList::GetContextAtIndex(uint32_t idx) {
SBSymbolContext sb_sc;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
SymbolContext sc;
if (m_opaque_ap->GetContextAtIndex(idx, sc)) {
sb_sc.SetSymbolContext(&sc);
@@ -48,7 +48,7 @@ SBSymbolContext SBSymbolContextList::GetContextAtIndex(uint32_t idx) {
}
void SBSymbolContextList::Clear() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->Clear();
}
@@ -62,7 +62,7 @@ void SBSymbolContextList::Append(SBSymbolContextList &sc_list) {
m_opaque_ap->Append(*sc_list);
}
-bool SBSymbolContextList::IsValid() const { return m_opaque_ap.get() != NULL; }
+bool SBSymbolContextList::IsValid() const { return m_opaque_ap != NULL; }
lldb_private::SymbolContextList *SBSymbolContextList::operator->() const {
return m_opaque_ap.get();
@@ -70,12 +70,12 @@ lldb_private::SymbolContextList *SBSymbolContextList::operator->() const {
lldb_private::SymbolContextList &SBSymbolContextList::operator*() const {
assert(m_opaque_ap.get());
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
bool SBSymbolContextList::GetDescription(lldb::SBStream &description) {
Stream &strm = description.ref();
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
m_opaque_ap->GetDescription(&strm, lldb::eDescriptionLevelFull, NULL);
return true;
}
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 550d336906d3..98587e7d7677 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -202,6 +202,21 @@ SBStructuredData SBTarget::GetStatistics() {
return data;
}
+void SBTarget::SetCollectingStats(bool v) {
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return;
+ return target_sp->SetCollectingStats(v);
+}
+
+bool SBTarget::GetCollectingStats() {
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return false;
+ return target_sp->GetCollectingStats();
+}
+
+
SBProcess SBTarget::LoadCore(const char *core_file) {
lldb::SBError error; // Ignored
return LoadCore(core_file, error);
@@ -211,7 +226,8 @@ SBProcess SBTarget::LoadCore(const char *core_file, lldb::SBError &error) {
SBProcess sb_process;
TargetSP target_sp(GetSP());
if (target_sp) {
- FileSpec filespec(core_file, true);
+ FileSpec filespec(core_file);
+ FileSystem::Instance().Resolve(filespec);
ProcessSP process_sp(target_sp->CreateProcess(
target_sp->GetDebugger().GetListener(), "", &filespec));
if (process_sp) {
@@ -310,10 +326,9 @@ SBProcess SBTarget::Launch(SBListener &listener, char const **argv,
if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO"))
launch_flags |= eLaunchFlagDisableSTDIO;
- ProcessLaunchInfo launch_info(
- FileSpec{stdin_path, false}, FileSpec{stdout_path, false},
- FileSpec{stderr_path, false}, FileSpec{working_directory, false},
- launch_flags);
+ ProcessLaunchInfo launch_info(FileSpec(stdin_path), FileSpec(stdout_path),
+ FileSpec(stderr_path),
+ FileSpec(working_directory), launch_flags);
Module *exe_module = target_sp->GetExecutableModulePointer();
if (exe_module)
@@ -501,8 +516,7 @@ lldb::SBProcess SBTarget::AttachToProcessWithName(
if (name && target_sp) {
ProcessAttachInfo attach_info;
- attach_info.GetExecutableFile().SetFile(name, false,
- FileSpec::Style::native);
+ attach_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
attach_info.SetWaitForLaunch(wait_for);
if (listener.IsValid())
attach_info.SetListener(listener.GetSP());
@@ -645,11 +659,12 @@ SBSymbolContext
SBTarget::ResolveSymbolContextForAddress(const SBAddress &addr,
uint32_t resolve_scope) {
SBSymbolContext sc;
+ SymbolContextItem scope = static_cast<SymbolContextItem>(resolve_scope);
if (addr.IsValid()) {
TargetSP target_sp(GetSP());
if (target_sp)
- target_sp->GetImages().ResolveSymbolContextForAddress(
- addr.ref(), resolve_scope, sc.ref());
+ target_sp->GetImages().ResolveSymbolContextForAddress(addr.ref(), scope,
+ sc.ref());
}
return sc;
}
@@ -693,6 +708,13 @@ SBBreakpoint
SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
uint32_t line, lldb::addr_t offset,
SBFileSpecList &sb_module_list) {
+ return BreakpointCreateByLocation(sb_file_spec, line, 0, offset,
+ sb_module_list);
+}
+
+SBBreakpoint SBTarget::BreakpointCreateByLocation(
+ const SBFileSpec &sb_file_spec, uint32_t line, uint32_t column,
+ lldb::addr_t offset, SBFileSpecList &sb_module_list) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
SBBreakpoint sb_bp;
@@ -710,8 +732,8 @@ SBTarget::BreakpointCreateByLocation(const SBFileSpec &sb_file_spec,
module_list = sb_module_list.get();
}
sb_bp = target_sp->CreateBreakpoint(
- module_list, *sb_file_spec, line, offset, check_inlines, skip_prologue,
- internal, hardware, move_to_nearest_code);
+ module_list, *sb_file_spec, line, column, offset, check_inlines,
+ skip_prologue, internal, hardware, move_to_nearest_code);
}
if (log) {
@@ -743,7 +765,7 @@ SBBreakpoint SBTarget::BreakpointCreateByName(const char *symbol_name,
const lldb::addr_t offset = 0;
if (module_name && module_name[0]) {
FileSpecList module_spec_list;
- module_spec_list.Append(FileSpec(module_name, false));
+ module_spec_list.Append(FileSpec(module_name));
sb_bp = target_sp->CreateBreakpoint(
&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto,
eLanguageTypeUnknown, offset, skip_prologue, internal, hardware);
@@ -767,7 +789,7 @@ lldb::SBBreakpoint
SBTarget::BreakpointCreateByName(const char *symbol_name,
const SBFileSpecList &module_list,
const SBFileSpecList &comp_unit_list) {
- uint32_t name_type_mask = eFunctionNameTypeAuto;
+ lldb::FunctionNameType name_type_mask = eFunctionNameTypeAuto;
return BreakpointCreateByName(symbol_name, name_type_mask,
eLanguageTypeUnknown, module_list,
comp_unit_list);
@@ -794,9 +816,10 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
const bool hardware = false;
const LazyBool skip_prologue = eLazyBoolCalculate;
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
- sb_bp = target_sp->CreateBreakpoint(
- module_list.get(), comp_unit_list.get(), symbol_name, name_type_mask,
- symbol_language, 0, skip_prologue, internal, hardware);
+ FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
+ sb_bp = target_sp->CreateBreakpoint(module_list.get(), comp_unit_list.get(),
+ symbol_name, mask, symbol_language, 0,
+ skip_prologue, internal, hardware);
}
if (log)
@@ -837,11 +860,11 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateByNames(
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
const bool internal = false;
const bool hardware = false;
+ FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
const LazyBool skip_prologue = eLazyBoolCalculate;
sb_bp = target_sp->CreateBreakpoint(
- module_list.get(), comp_unit_list.get(), symbol_names, num_names,
- name_type_mask, symbol_language, offset, skip_prologue, internal,
- hardware);
+ module_list.get(), comp_unit_list.get(), symbol_names, num_names, mask,
+ symbol_language, offset, skip_prologue, internal, hardware);
}
if (log) {
@@ -870,7 +893,7 @@ SBBreakpoint SBTarget::BreakpointCreateByRegex(const char *symbol_name_regex,
SBFileSpecList module_spec_list;
SBFileSpecList comp_unit_list;
if (module_name && module_name[0]) {
- module_spec_list.Append(FileSpec(module_name, false));
+ module_spec_list.Append(FileSpec(module_name));
}
return BreakpointCreateByRegex(symbol_name_regex, eLanguageTypeUnknown,
module_spec_list, comp_unit_list);
@@ -971,7 +994,7 @@ SBTarget::BreakpointCreateBySourceRegex(const char *source_regex,
SBFileSpecList module_spec_list;
if (module_name && module_name[0]) {
- module_spec_list.Append(FileSpec(module_name, false));
+ module_spec_list.Append(FileSpec(module_name));
}
SBFileSpecList source_file_list;
@@ -1037,7 +1060,7 @@ SBTarget::BreakpointCreateForException(lldb::LanguageType language,
}
if (log)
- log->Printf("SBTarget(%p)::BreakpointCreateByRegex (Language: %s, catch: "
+ log->Printf("SBTarget(%p)::BreakpointCreateForException (Language: %s, catch: "
"%s throw: %s) => SBBreakpoint(%p)",
static_cast<void *>(target_sp.get()),
Language::GetNameForLanguageType(language),
@@ -1047,6 +1070,42 @@ SBTarget::BreakpointCreateForException(lldb::LanguageType language,
return sb_bp;
}
+lldb::SBBreakpoint
+SBTarget::BreakpointCreateFromScript(const char *class_name,
+ SBStructuredData &extra_args,
+ const SBFileSpecList &module_list,
+ const SBFileSpecList &file_list,
+ bool request_hardware)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+
+ SBBreakpoint sb_bp;
+ TargetSP target_sp(GetSP());
+ if (target_sp) {
+ std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
+ Status error;
+
+ StructuredData::ObjectSP obj_sp = extra_args.m_impl_up->GetObjectSP();
+ sb_bp =
+ target_sp->CreateScriptedBreakpoint(class_name,
+ module_list.get(),
+ file_list.get(),
+ false, /* internal */
+ request_hardware,
+ obj_sp,
+ &error);
+ }
+ if (log)
+ log->Printf("SBTarget(%p)::BreakpointCreateFromScript (class name: %s) "
+ " => SBBreakpoint(%p)",
+ static_cast<void *>(target_sp.get()),
+ class_name,
+ static_cast<void *>(sb_bp.GetSP().get()));
+
+ return sb_bp;
+}
+
+
uint32_t SBTarget::GetNumBreakpoints() const {
TargetSP target_sp(GetSP());
if (target_sp) {
@@ -1457,6 +1516,26 @@ bool SBTarget::DeleteAllWatchpoints() {
return false;
}
+void SBTarget::AppendImageSearchPath(const char *from, const char *to,
+ lldb::SBError &error) {
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return error.SetErrorString("invalid target");
+
+ const ConstString csFrom(from), csTo(to);
+ if (!csFrom)
+ return error.SetErrorString("<from> path can't be empty");
+ if (!csTo)
+ return error.SetErrorString("<to> path can't be empty");
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+ if (log)
+ log->Printf("SBTarget(%p)::%s: '%s' -> '%s'",
+ static_cast<void *>(target_sp.get()), __FUNCTION__,
+ from, to);
+ target_sp->GetImageSearchPathList().Append(csFrom, csTo, true);
+}
+
lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
const char *uuid_cstr) {
return AddModule(path, triple, uuid_cstr, NULL);
@@ -1469,7 +1548,7 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
if (target_sp) {
ModuleSpec module_spec;
if (path)
- module_spec.GetFileSpec().SetFile(path, false, FileSpec::Style::native);
+ module_spec.GetFileSpec().SetFile(path, FileSpec::Style::native);
if (uuid_cstr)
module_spec.GetUUID().SetFromStringRef(uuid_cstr);
@@ -1481,8 +1560,7 @@ lldb::SBModule SBTarget::AddModule(const char *path, const char *triple,
module_spec.GetArchitecture() = target_sp->GetArchitecture();
if (symfile)
- module_spec.GetSymbolFileSpec().SetFile(symfile, false,
- FileSpec::Style::native);
+ module_spec.GetSymbolFileSpec().SetFile(symfile, FileSpec::Style::native);
sb_module.SetSP(target_sp->GetSharedModule(module_spec));
}
@@ -1656,17 +1734,19 @@ bool SBTarget::GetDescription(SBStream &description,
lldb::SBSymbolContextList SBTarget::FindFunctions(const char *name,
uint32_t name_type_mask) {
lldb::SBSymbolContextList sb_sc_list;
- if (name && name[0]) {
- TargetSP target_sp(GetSP());
- if (target_sp) {
- const bool symbols_ok = true;
- const bool inlines_ok = true;
- const bool append = true;
- target_sp->GetImages().FindFunctions(ConstString(name), name_type_mask,
- symbols_ok, inlines_ok, append,
- *sb_sc_list);
- }
- }
+ if (!name | !name[0])
+ return sb_sc_list;
+
+ TargetSP target_sp(GetSP());
+ if (!target_sp)
+ return sb_sc_list;
+
+ const bool symbols_ok = true;
+ const bool inlines_ok = true;
+ const bool append = true;
+ FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
+ target_sp->GetImages().FindFunctions(ConstString(name), mask, symbols_ok,
+ inlines_ok, append, *sb_sc_list);
return sb_sc_list;
}
@@ -1770,11 +1850,10 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) {
ModuleList &images = target_sp->GetImages();
ConstString const_typename(typename_cstr);
bool exact_match = false;
- SymbolContext sc;
TypeList type_list;
llvm::DenseSet<SymbolFile *> searched_symbol_files;
uint32_t num_matches =
- images.FindTypes(sc, const_typename, exact_match, UINT32_MAX,
+ images.FindTypes(nullptr, const_typename, exact_match, UINT32_MAX,
searched_symbol_files, type_list);
if (num_matches > 0) {
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 0d25b85f57d2..2c859d5222d6 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -14,7 +14,6 @@
#include "lldb/API/SBSymbolContext.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -32,6 +31,7 @@
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StructuredData.h"
@@ -571,7 +571,7 @@ bool SBThread::GetInfoItemByPathAsString(const char *path, SBStream &strm) {
success = true;
}
if (node->GetType() == eStructuredDataTypeBoolean) {
- if (node->GetAsBoolean()->GetValue() == true)
+ if (node->GetAsBoolean()->GetValue())
strm.Printf("true");
else
strm.Printf("false");
@@ -657,6 +657,7 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
bool abort_other_plans = false;
StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
+ Status new_plan_status;
ThreadPlanSP new_plan_sp;
if (frame_sp) {
if (frame_sp->HasDebugInformation()) {
@@ -664,10 +665,10 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = thread->QueueThreadPlanForStepOverRange(
abort_other_plans, sc.line_entry, sc, stop_other_threads,
- avoid_no_debug);
+ new_plan_status, avoid_no_debug);
} else {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, stop_other_threads);
+ true, abort_other_plans, stop_other_threads, new_plan_status);
}
}
error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
@@ -707,6 +708,7 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line,
Thread *thread = exe_ctx.GetThreadPtr();
StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
if (frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
@@ -724,13 +726,17 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line,
eLazyBoolCalculate;
new_plan_sp = thread->QueueThreadPlanForStepInRange(
abort_other_plans, range, sc, target_name, stop_other_threads,
- step_in_avoids_code_without_debug_info,
+ new_plan_status, step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, stop_other_threads);
+ false, abort_other_plans, stop_other_threads, new_plan_status);
}
- error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+
+ if (new_plan_status.Success())
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ error.SetErrorString(new_plan_status.AsCString());
}
void SBThread::StepOut() {
@@ -759,11 +765,15 @@ void SBThread::StepOut(SBError &error) {
Thread *thread = exe_ctx.GetThreadPtr();
const LazyBool avoid_no_debug = eLazyBoolCalculate;
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
- eVoteNoOpinion, 0, avoid_no_debug));
+ eVoteNoOpinion, 0, new_plan_status, avoid_no_debug));
- error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ if (new_plan_status.Success())
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ error.SetErrorString(new_plan_status.AsCString());
}
void SBThread::StepOutOfFrame(SBFrame &sb_frame) {
@@ -812,11 +822,15 @@ void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) {
return;
}
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut(
abort_other_plans, NULL, false, stop_other_threads, eVoteYes,
- eVoteNoOpinion, frame_sp->GetFrameIndex()));
+ eVoteNoOpinion, frame_sp->GetFrameIndex(), new_plan_status));
- error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ if (new_plan_status.Success())
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ error.SetErrorString(new_plan_status.AsCString());
}
void SBThread::StepInstruction(bool step_over) {
@@ -840,10 +854,14 @@ void SBThread::StepInstruction(bool step_over, SBError &error) {
}
Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP new_plan_sp(
- thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true));
+ Status new_plan_status;
+ ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepSingleInstruction(
+ step_over, true, true, new_plan_status));
- error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ if (new_plan_status.Success())
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ error.SetErrorString(new_plan_status.AsCString());
}
void SBThread::RunToAddress(lldb::addr_t addr) {
@@ -873,10 +891,14 @@ void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) {
Thread *thread = exe_ctx.GetThreadPtr();
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
- abort_other_plans, target_addr, stop_other_threads));
+ abort_other_plans, target_addr, stop_other_threads, new_plan_status));
- error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ if (new_plan_status.Success())
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ error.SetErrorString(new_plan_status.AsCString());
}
SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
@@ -988,12 +1010,16 @@ SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame,
} else
sb_error.SetErrorString("step until target not in current function");
} else {
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil(
abort_other_plans, &step_over_until_addrs[0],
step_over_until_addrs.size(), stop_other_threads,
- frame_sp->GetFrameIndex()));
+ frame_sp->GetFrameIndex(), new_plan_status));
- sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ if (new_plan_status.Success())
+ sb_error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ sb_error.SetErrorString(new_plan_status.AsCString());
}
} else {
sb_error.SetErrorString("this SBThread object is invalid");
@@ -1008,7 +1034,7 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name) {
SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
bool resume_immediately) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
- SBError sb_error;
+ SBError error;
std::unique_lock<std::recursive_mutex> lock;
ExecutionContext exe_ctx(m_opaque_sp.get(), lock);
@@ -1019,37 +1045,29 @@ SBError SBThread::StepUsingScriptedThreadPlan(const char *script_class_name,
}
if (!exe_ctx.HasThreadScope()) {
- sb_error.SetErrorString("this SBThread object is invalid");
- return sb_error;
+ error.SetErrorString("this SBThread object is invalid");
+ return error;
}
Thread *thread = exe_ctx.GetThreadPtr();
- ThreadPlanSP thread_plan_sp =
- thread->QueueThreadPlanForStepScripted(false, script_class_name, false);
+ Status new_plan_status;
+ ThreadPlanSP new_plan_sp = thread->QueueThreadPlanForStepScripted(
+ false, script_class_name, false, new_plan_status);
- if (!thread_plan_sp) {
- sb_error.SetErrorStringWithFormat(
- "Error queueing thread plan for class: %s", script_class_name);
- return sb_error;
+ if (new_plan_status.Fail()) {
+ error.SetErrorString(new_plan_status.AsCString());
+ return error;
}
- if (!resume_immediately) {
- return sb_error;
- }
+ if (!resume_immediately)
+ return error;
- if (thread_plan_sp)
- sb_error = ResumeNewPlan(exe_ctx, thread_plan_sp.get());
- else {
- sb_error.SetErrorStringWithFormat(
- "Error resuming thread plan for class: %s.", script_class_name);
- if (log)
- log->Printf("SBThread(%p)::StepUsingScriptedThreadPlan: Error queuing "
- "thread plan for class: %s",
- static_cast<void *>(exe_ctx.GetThreadPtr()),
- script_class_name);
- }
+ if (new_plan_status.Success())
+ error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
+ else
+ error.SetErrorString(new_plan_status.AsCString());
- return sb_error;
+ return error;
}
SBError SBThread::JumpToLine(lldb::SBFileSpec &file_spec, uint32_t line) {
@@ -1452,7 +1470,7 @@ SBThread SBThread::GetExtendedBacktraceThread(const char *type) {
}
}
- if (log && sb_origin_thread.IsValid() == false)
+ if (log && !sb_origin_thread.IsValid())
log->Printf("SBThread(%p)::GetExtendedBacktraceThread() is not returning a "
"Valid thread",
static_cast<void *>(exe_ctx.GetThreadPtr()));
@@ -1466,6 +1484,20 @@ uint32_t SBThread::GetExtendedBacktraceOriginatingIndexID() {
return LLDB_INVALID_INDEX32;
}
+SBValue SBThread::GetCurrentException() {
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (!thread_sp) return SBValue();
+
+ return SBValue(thread_sp->GetCurrentException());
+}
+
+SBThread SBThread::GetCurrentExceptionBacktrace() {
+ ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
+ if (!thread_sp) return SBThread();
+
+ return SBThread(thread_sp->GetCurrentExceptionBacktrace());
+}
+
bool SBThread::SafeToCallFunctions() {
ThreadSP thread_sp(m_opaque_sp->GetThreadSP());
if (thread_sp)
diff --git a/source/API/SBThreadPlan.cpp b/source/API/SBThreadPlan.cpp
index 131f84195908..fc54f5b5f87e 100644
--- a/source/API/SBThreadPlan.cpp
+++ b/source/API/SBThreadPlan.cpp
@@ -14,7 +14,6 @@
#include "lldb/API/SBSymbolContext.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -31,6 +30,7 @@
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StructuredData.h"
@@ -143,6 +143,12 @@ bool SBThreadPlan::IsValid() {
SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address,
lldb::addr_t size) {
+ SBError error;
+ return QueueThreadPlanForStepOverRange(sb_start_address, size, error);
+}
+
+SBThreadPlan SBThreadPlan::QueueThreadPlanForStepOverRange(
+ SBAddress &sb_start_address, lldb::addr_t size, SBError &error) {
if (m_opaque_sp) {
Address *start_address = sb_start_address.get();
if (!start_address) {
@@ -152,9 +158,16 @@ SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address,
AddressRange range(*start_address, size);
SymbolContext sc;
start_address->CalculateSymbolContext(&sc);
- return SBThreadPlan(
- m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange(
- false, range, sc, eAllThreads));
+ Status plan_status;
+
+ SBThreadPlan plan =
+ SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOverRange(
+ false, range, sc, eAllThreads, plan_status));
+
+ if (plan_status.Fail())
+ error.SetErrorString(plan_status.AsCString());
+
+ return plan;
} else {
return SBThreadPlan();
}
@@ -163,6 +176,13 @@ SBThreadPlan::QueueThreadPlanForStepOverRange(SBAddress &sb_start_address,
SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,
lldb::addr_t size) {
+ SBError error;
+ return QueueThreadPlanForStepInRange(sb_start_address, size, error);
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,
+ lldb::addr_t size, SBError &error) {
if (m_opaque_sp) {
Address *start_address = sb_start_address.get();
if (!start_address) {
@@ -172,8 +192,16 @@ SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,
AddressRange range(*start_address, size);
SymbolContext sc;
start_address->CalculateSymbolContext(&sc);
- return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange(
- false, range, sc, NULL, eAllThreads));
+
+ Status plan_status;
+ SBThreadPlan plan =
+ SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepInRange(
+ false, range, sc, NULL, eAllThreads, plan_status));
+
+ if (plan_status.Fail())
+ error.SetErrorString(plan_status.AsCString());
+
+ return plan;
} else {
return SBThreadPlan();
}
@@ -182,13 +210,28 @@ SBThreadPlan::QueueThreadPlanForStepInRange(SBAddress &sb_start_address,
SBThreadPlan
SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
bool first_insn) {
+ SBError error;
+ return QueueThreadPlanForStepOut(frame_idx_to_step_to, first_insn, error);
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
+ bool first_insn, SBError &error) {
if (m_opaque_sp) {
SymbolContext sc;
sc = m_opaque_sp->GetThread().GetStackFrameAtIndex(0)->GetSymbolContext(
lldb::eSymbolContextEverything);
- return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut(
- false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
- frame_idx_to_step_to));
+
+ Status plan_status;
+ SBThreadPlan plan =
+ SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepOut(
+ false, &sc, first_insn, false, eVoteYes, eVoteNoOpinion,
+ frame_idx_to_step_to, plan_status));
+
+ if (plan_status.Fail())
+ error.SetErrorString(plan_status.AsCString());
+
+ return plan;
} else {
return SBThreadPlan();
}
@@ -196,13 +239,50 @@ SBThreadPlan::QueueThreadPlanForStepOut(uint32_t frame_idx_to_step_to,
SBThreadPlan
SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address) {
+ SBError error;
+ return QueueThreadPlanForRunToAddress(sb_address, error);
+}
+
+SBThreadPlan SBThreadPlan::QueueThreadPlanForRunToAddress(SBAddress sb_address,
+ SBError &error) {
if (m_opaque_sp) {
Address *address = sb_address.get();
if (!address)
return SBThreadPlan();
- return SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress(
- false, *address, false));
+ Status plan_status;
+ SBThreadPlan plan =
+ SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForRunToAddress(
+ false, *address, false, plan_status));
+
+ if (plan_status.Fail())
+ error.SetErrorString(plan_status.AsCString());
+
+ return plan;
+ } else {
+ return SBThreadPlan();
+ }
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name) {
+ SBError error;
+ return QueueThreadPlanForStepScripted(script_class_name, error);
+}
+
+SBThreadPlan
+SBThreadPlan::QueueThreadPlanForStepScripted(const char *script_class_name,
+ SBError &error) {
+ if (m_opaque_sp) {
+ Status plan_status;
+ SBThreadPlan plan =
+ SBThreadPlan(m_opaque_sp->GetThread().QueueThreadPlanForStepScripted(
+ false, script_class_name, false, plan_status));
+
+ if (plan_status.Fail())
+ error.SetErrorString(plan_status.AsCString());
+
+ return plan;
} else {
return SBThreadPlan();
}
diff --git a/source/API/SBType.cpp b/source/API/SBType.cpp
index e199b7a33e48..77d7dc654100 100644
--- a/source/API/SBType.cpp
+++ b/source/API/SBType.cpp
@@ -47,20 +47,20 @@ SBType::SBType(const SBType &rhs) : m_opaque_sp() {
//{}
//
bool SBType::operator==(SBType &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
- if (rhs.IsValid() == false)
+ if (!rhs.IsValid())
return false;
return *m_opaque_sp.get() == *rhs.m_opaque_sp.get();
}
bool SBType::operator!=(SBType &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return rhs.IsValid();
- if (rhs.IsValid() == false)
+ if (!rhs.IsValid())
return true;
return *m_opaque_sp.get() != *rhs.m_opaque_sp.get();
@@ -103,10 +103,11 @@ bool SBType::IsValid() const {
}
uint64_t SBType::GetByteSize() {
- if (!IsValid())
- return 0;
-
- return m_opaque_sp->GetCompilerType(false).GetByteSize(nullptr);
+ if (IsValid())
+ if (llvm::Optional<uint64_t> size =
+ m_opaque_sp->GetCompilerType(false).GetByteSize(nullptr))
+ return *size;
+ return 0;
}
bool SBType::IsPointerType() {
@@ -451,7 +452,7 @@ SBTypeList::SBTypeList(const SBTypeList &rhs)
Append(const_cast<SBTypeList &>(rhs).GetTypeAtIndex(i));
}
-bool SBTypeList::IsValid() { return (m_opaque_ap.get() != NULL); }
+bool SBTypeList::IsValid() { return (m_opaque_ap != NULL); }
SBTypeList &SBTypeList::operator=(const SBTypeList &rhs) {
if (this != &rhs) {
@@ -469,7 +470,7 @@ void SBTypeList::Append(SBType type) {
}
SBType SBTypeList::GetTypeAtIndex(uint32_t index) {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return SBType(m_opaque_ap->GetTypeAtIndex(index));
return SBType();
}
@@ -500,39 +501,39 @@ lldb::SBTypeMember &SBTypeMember::operator=(const lldb::SBTypeMember &rhs) {
bool SBTypeMember::IsValid() const { return m_opaque_ap.get(); }
const char *SBTypeMember::GetName() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetName().GetCString();
return NULL;
}
SBType SBTypeMember::GetType() {
SBType sb_type;
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
sb_type.SetSP(m_opaque_ap->GetTypeImpl());
}
return sb_type;
}
uint64_t SBTypeMember::GetOffsetInBytes() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetBitOffset() / 8u;
return 0;
}
uint64_t SBTypeMember::GetOffsetInBits() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetBitOffset();
return 0;
}
bool SBTypeMember::IsBitfield() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetIsBitfield();
return false;
}
uint32_t SBTypeMember::GetBitfieldSizeInBits() {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return m_opaque_ap->GetBitfieldBitSize();
return 0;
}
@@ -541,7 +542,7 @@ bool SBTypeMember::GetDescription(lldb::SBStream &description,
lldb::DescriptionLevel description_level) {
Stream &strm = description.ref();
- if (m_opaque_ap.get()) {
+ if (m_opaque_ap) {
const uint32_t bit_offset = m_opaque_ap->GetBitOffset();
const uint32_t byte_offset = bit_offset / 8u;
const uint32_t byte_bit_offset = bit_offset % 8u;
@@ -571,12 +572,12 @@ void SBTypeMember::reset(TypeMemberImpl *type_member_impl) {
}
TypeMemberImpl &SBTypeMember::ref() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new TypeMemberImpl());
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
-const TypeMemberImpl &SBTypeMember::ref() const { return *m_opaque_ap.get(); }
+const TypeMemberImpl &SBTypeMember::ref() const { return *m_opaque_ap; }
SBTypeMemberFunction::SBTypeMemberFunction() : m_opaque_sp() {}
diff --git a/source/API/SBTypeCategory.cpp b/source/API/SBTypeCategory.cpp
index 30414bd728cb..7c2a37e7cf21 100644
--- a/source/API/SBTypeCategory.cpp
+++ b/source/API/SBTypeCategory.cpp
@@ -529,14 +529,14 @@ operator=(const lldb::SBTypeCategory &rhs) {
}
bool SBTypeCategory::operator==(lldb::SBTypeCategory &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp.get() == rhs.m_opaque_sp.get();
}
bool SBTypeCategory::operator!=(lldb::SBTypeCategory &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return rhs.IsValid();
return m_opaque_sp.get() != rhs.m_opaque_sp.get();
diff --git a/source/API/SBTypeEnumMember.cpp b/source/API/SBTypeEnumMember.cpp
index 5ca9db7ce242..87be40e8b141 100644
--- a/source/API/SBTypeEnumMember.cpp
+++ b/source/API/SBTypeEnumMember.cpp
@@ -94,7 +94,7 @@ SBTypeEnumMemberList::SBTypeEnumMemberList(const SBTypeEnumMemberList &rhs)
Append(const_cast<SBTypeEnumMemberList &>(rhs).GetTypeEnumMemberAtIndex(i));
}
-bool SBTypeEnumMemberList::IsValid() { return (m_opaque_ap.get() != NULL); }
+bool SBTypeEnumMemberList::IsValid() { return (m_opaque_ap != NULL); }
SBTypeEnumMemberList &SBTypeEnumMemberList::
operator=(const SBTypeEnumMemberList &rhs) {
@@ -116,7 +116,7 @@ void SBTypeEnumMemberList::Append(SBTypeEnumMember enum_member) {
SBTypeEnumMember
SBTypeEnumMemberList::GetTypeEnumMemberAtIndex(uint32_t index) {
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
return SBTypeEnumMember(m_opaque_ap->GetTypeEnumMemberAtIndex(index));
return SBTypeEnumMember();
}
diff --git a/source/API/SBTypeFilter.cpp b/source/API/SBTypeFilter.cpp
index 8fa322211384..9709d2e5da10 100644
--- a/source/API/SBTypeFilter.cpp
+++ b/source/API/SBTypeFilter.cpp
@@ -91,14 +91,14 @@ lldb::SBTypeFilter &SBTypeFilter::operator=(const lldb::SBTypeFilter &rhs) {
}
bool SBTypeFilter::operator==(lldb::SBTypeFilter &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp == rhs.m_opaque_sp;
}
bool SBTypeFilter::IsEqualTo(lldb::SBTypeFilter &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
if (GetNumberOfExpressionPaths() != rhs.GetNumberOfExpressionPaths())
@@ -113,7 +113,7 @@ bool SBTypeFilter::IsEqualTo(lldb::SBTypeFilter &rhs) {
}
bool SBTypeFilter::operator!=(lldb::SBTypeFilter &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp != rhs.m_opaque_sp;
diff --git a/source/API/SBTypeFormat.cpp b/source/API/SBTypeFormat.cpp
index 6fe7625831d2..66bfd3671736 100644
--- a/source/API/SBTypeFormat.cpp
+++ b/source/API/SBTypeFormat.cpp
@@ -88,13 +88,13 @@ lldb::SBTypeFormat &SBTypeFormat::operator=(const lldb::SBTypeFormat &rhs) {
}
bool SBTypeFormat::operator==(lldb::SBTypeFormat &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp == rhs.m_opaque_sp;
}
bool SBTypeFormat::IsEqualTo(lldb::SBTypeFormat &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
if (GetFormat() == rhs.GetFormat())
@@ -104,7 +104,7 @@ bool SBTypeFormat::IsEqualTo(lldb::SBTypeFormat &rhs) {
}
bool SBTypeFormat::operator!=(lldb::SBTypeFormat &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp != rhs.m_opaque_sp;
}
diff --git a/source/API/SBTypeNameSpecifier.cpp b/source/API/SBTypeNameSpecifier.cpp
index 2f9deafb68c8..5ffb3d98a0f2 100644
--- a/source/API/SBTypeNameSpecifier.cpp
+++ b/source/API/SBTypeNameSpecifier.cpp
@@ -80,13 +80,13 @@ operator=(const lldb::SBTypeNameSpecifier &rhs) {
}
bool SBTypeNameSpecifier::operator==(lldb::SBTypeNameSpecifier &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp == rhs.m_opaque_sp;
}
bool SBTypeNameSpecifier::IsEqualTo(lldb::SBTypeNameSpecifier &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
if (IsRegex() != rhs.IsRegex())
@@ -98,7 +98,7 @@ bool SBTypeNameSpecifier::IsEqualTo(lldb::SBTypeNameSpecifier &rhs) {
}
bool SBTypeNameSpecifier::operator!=(lldb::SBTypeNameSpecifier &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp != rhs.m_opaque_sp;
}
diff --git a/source/API/SBTypeSummary.cpp b/source/API/SBTypeSummary.cpp
index cd4edd17f672..76c94ae83444 100644
--- a/source/API/SBTypeSummary.cpp
+++ b/source/API/SBTypeSummary.cpp
@@ -25,7 +25,7 @@ SBTypeSummaryOptions::SBTypeSummaryOptions() {
SBTypeSummaryOptions::SBTypeSummaryOptions(
const lldb::SBTypeSummaryOptions &rhs) {
if (rhs.m_opaque_ap)
- m_opaque_ap.reset(new TypeSummaryOptions(*rhs.m_opaque_ap.get()));
+ m_opaque_ap.reset(new TypeSummaryOptions(*rhs.m_opaque_ap));
else
m_opaque_ap.reset(new TypeSummaryOptions());
}
@@ -70,11 +70,11 @@ lldb_private::TypeSummaryOptions *SBTypeSummaryOptions::get() {
}
lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() {
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
const lldb_private::TypeSummaryOptions &SBTypeSummaryOptions::ref() const {
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
SBTypeSummaryOptions::SBTypeSummaryOptions(
@@ -261,7 +261,7 @@ lldb::SBTypeSummary &SBTypeSummary::operator=(const lldb::SBTypeSummary &rhs) {
}
bool SBTypeSummary::operator==(lldb::SBTypeSummary &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp == rhs.m_opaque_sp;
}
@@ -305,7 +305,7 @@ bool SBTypeSummary::IsEqualTo(lldb::SBTypeSummary &rhs) {
}
bool SBTypeSummary::operator!=(lldb::SBTypeSummary &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp != rhs.m_opaque_sp;
}
diff --git a/source/API/SBTypeSynthetic.cpp b/source/API/SBTypeSynthetic.cpp
index 37b6086f855a..750d917e67f1 100644
--- a/source/API/SBTypeSynthetic.cpp
+++ b/source/API/SBTypeSynthetic.cpp
@@ -106,13 +106,13 @@ operator=(const lldb::SBTypeSynthetic &rhs) {
}
bool SBTypeSynthetic::operator==(lldb::SBTypeSynthetic &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp == rhs.m_opaque_sp;
}
bool SBTypeSynthetic::IsEqualTo(lldb::SBTypeSynthetic &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
if (m_opaque_sp->IsScripted() != rhs.m_opaque_sp->IsScripted())
@@ -128,7 +128,7 @@ bool SBTypeSynthetic::IsEqualTo(lldb::SBTypeSynthetic &rhs) {
}
bool SBTypeSynthetic::operator!=(lldb::SBTypeSynthetic &rhs) {
- if (IsValid() == false)
+ if (!IsValid())
return !rhs.IsValid();
return m_opaque_sp != rhs.m_opaque_sp;
}
diff --git a/source/API/SBValue.cpp b/source/API/SBValue.cpp
index a270c0471e9f..a61a2a19a621 100644
--- a/source/API/SBValue.cpp
+++ b/source/API/SBValue.cpp
@@ -18,7 +18,6 @@
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
@@ -38,6 +37,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Stream.h"
#include "lldb/API/SBDebugger.h"
@@ -98,10 +98,7 @@ public:
// they depend on. So I have no good way to make that check without
// tracking that in all the ValueObject subclasses.
TargetSP target_sp = m_valobj_sp->GetTargetSP();
- if (target_sp && target_sp->IsValid())
- return true;
- else
- return false;
+ return target_sp && target_sp->IsValid();
}
}
diff --git a/source/API/SBValueList.cpp b/source/API/SBValueList.cpp
index 0adf3bb914aa..82b464bab9b9 100644
--- a/source/API/SBValueList.cpp
+++ b/source/API/SBValueList.cpp
@@ -99,7 +99,7 @@ SBValueList::SBValueList(const ValueListImpl *lldb_object_ptr) : m_opaque_ap() {
SBValueList::~SBValueList() {}
-bool SBValueList::IsValid() const { return (m_opaque_ap.get() != NULL); }
+bool SBValueList::IsValid() const { return (m_opaque_ap != NULL); }
void SBValueList::Clear() { m_opaque_ap.reset(); }
@@ -150,7 +150,7 @@ SBValue SBValueList::GetValueAtIndex(uint32_t idx) const {
// idx);
SBValue sb_value;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
sb_value = m_opaque_ap->GetValueAtIndex(idx);
if (log) {
@@ -172,7 +172,7 @@ uint32_t SBValueList::GetSize() const {
// log->Printf ("SBValueList::GetSize ()");
uint32_t size = 0;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
size = m_opaque_ap->GetSize();
if (log)
@@ -183,20 +183,20 @@ uint32_t SBValueList::GetSize() const {
}
void SBValueList::CreateIfNeeded() {
- if (m_opaque_ap.get() == NULL)
+ if (m_opaque_ap == NULL)
m_opaque_ap.reset(new ValueListImpl());
}
SBValue SBValueList::FindValueObjectByUID(lldb::user_id_t uid) {
SBValue sb_value;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
sb_value = m_opaque_ap->FindValueByUID(uid);
return sb_value;
}
SBValue SBValueList::GetFirstValueByName(const char *name) const {
SBValue sb_value;
- if (m_opaque_ap.get())
+ if (m_opaque_ap)
sb_value = m_opaque_ap->GetFirstValueByName(name);
return sb_value;
}
@@ -205,5 +205,5 @@ void *SBValueList::opaque_ptr() { return m_opaque_ap.get(); }
ValueListImpl &SBValueList::ref() {
CreateIfNeeded();
- return *m_opaque_ap.get();
+ return *m_opaque_ap;
}
diff --git a/source/API/SBVariablesOptions.cpp b/source/API/SBVariablesOptions.cpp
index e12b9696521c..2651ce11d02a 100644
--- a/source/API/SBVariablesOptions.cpp
+++ b/source/API/SBVariablesOptions.cpp
@@ -9,6 +9,10 @@
//===----------------------------------------------------------------------===//
#include "lldb/API/SBVariablesOptions.h"
+#include "lldb/API/SBTarget.h"
+#include "lldb/Target/Target.h"
+
+#include "lldb/lldb-private.h"
using namespace lldb;
using namespace lldb_private;
@@ -19,6 +23,7 @@ public:
: m_include_arguments(false), m_include_locals(false),
m_include_statics(false), m_in_scope_only(false),
m_include_runtime_support_values(false),
+ m_include_recognized_arguments(eLazyBoolCalculate),
m_use_dynamic(lldb::eNoDynamicValues) {}
VariablesOptionsImpl(const VariablesOptionsImpl &) = default;
@@ -31,6 +36,16 @@ public:
void SetIncludeArguments(bool b) { m_include_arguments = b; }
+ bool GetIncludeRecognizedArguments(const lldb::TargetSP &target_sp) const {
+ if (m_include_recognized_arguments != eLazyBoolCalculate)
+ return m_include_recognized_arguments;
+ return target_sp ? target_sp->GetDisplayRecognizedArguments() : false;
+ }
+
+ void SetIncludeRecognizedArguments(bool b) {
+ m_include_recognized_arguments = b ? eLazyBoolYes : eLazyBoolNo;
+ }
+
bool GetIncludeLocals() const { return m_include_locals; }
void SetIncludeLocals(bool b) { m_include_locals = b; }
@@ -61,6 +76,7 @@ private:
bool m_include_statics : 1;
bool m_in_scope_only : 1;
bool m_include_runtime_support_values : 1;
+ LazyBool m_include_recognized_arguments; // can be overridden with a setting
lldb::DynamicValueType m_use_dynamic;
};
@@ -78,9 +94,7 @@ operator=(const SBVariablesOptions &options) {
SBVariablesOptions::~SBVariablesOptions() = default;
-bool SBVariablesOptions::IsValid() const {
- return m_opaque_ap.get() != nullptr;
-}
+bool SBVariablesOptions::IsValid() const { return m_opaque_ap != nullptr; }
bool SBVariablesOptions::GetIncludeArguments() const {
return m_opaque_ap->GetIncludeArguments();
@@ -90,6 +104,15 @@ void SBVariablesOptions::SetIncludeArguments(bool arguments) {
m_opaque_ap->SetIncludeArguments(arguments);
}
+bool SBVariablesOptions::GetIncludeRecognizedArguments(
+ const lldb::SBTarget &target) const {
+ return m_opaque_ap->GetIncludeRecognizedArguments(target.GetSP());
+}
+
+void SBVariablesOptions::SetIncludeRecognizedArguments(bool arguments) {
+ m_opaque_ap->SetIncludeRecognizedArguments(arguments);
+}
+
bool SBVariablesOptions::GetIncludeLocals() const {
return m_opaque_ap->GetIncludeLocals();
}
diff --git a/source/API/SystemInitializerFull.cpp b/source/API/SystemInitializerFull.cpp
index 18de376183c7..42dea6a01aba 100644
--- a/source/API/SystemInitializerFull.cpp
+++ b/source/API/SystemInitializerFull.cpp
@@ -24,9 +24,6 @@
#include "lldb/Initialization/SystemInitializerCommon.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Symbol/JavaASTContext.h"
-#include "lldb/Symbol/OCamlASTContext.h"
#include "lldb/Utility/Timer.h"
#include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h"
@@ -43,6 +40,7 @@
#include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h"
#include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
#include "Plugins/Architecture/Arm/ArchitectureArm.h"
+#include "Plugins/Architecture/Mips/ArchitectureMips.h"
#include "Plugins/Architecture/PPC64/ArchitecturePPC64.h"
#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h"
@@ -58,22 +56,17 @@
#include "Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.h"
#include "Plugins/JITLoader/GDB/JITLoaderGDB.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/Language/Go/GoLanguage.h"
-#include "Plugins/Language/Java/JavaLanguage.h"
-#include "Plugins/Language/OCaml/OCamlLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h"
#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"
-#include "Plugins/LanguageRuntime/Go/GoLanguageRuntime.h"
-#include "Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h"
#include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h"
#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
-#include "Plugins/OperatingSystem/Go/OperatingSystemGo.h"
#include "Plugins/OperatingSystem/Python/OperatingSystemPython.h"
#include "Plugins/Platform/Android/PlatformAndroid.h"
#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h"
@@ -90,6 +83,7 @@
#include "Plugins/Process/mach-core/ProcessMachCore.h"
#include "Plugins/Process/minidump/ProcessMinidump.h"
#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
+#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
@@ -106,6 +100,7 @@
#include "Plugins/Platform/MacOSX/PlatformDarwinKernel.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h"
+#include "Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h"
#include "Plugins/Platform/MacOSX/PlatformiOSSimulator.h"
#include "Plugins/Process/MacOSX-Kernel/ProcessKDP.h"
#include "Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.h"
@@ -177,6 +172,18 @@ extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor,
const char *method_name,
Event *event_sp, bool &got_error);
+extern "C" void *LLDBSwigPythonCreateScriptedBreakpointResolver(
+ const char *python_class_name,
+ const char *session_dictionary_name,
+ lldb_private::StructuredDataImpl *args,
+ lldb::BreakpointSP &bkpt_sp);
+
+extern "C" unsigned int LLDBSwigPythonCallBreakpointResolver(
+ void *implementor,
+ const char *method_name,
+ lldb_private::SymbolContext *sym_ctx
+);
+
extern "C" size_t LLDBSwigPython_CalculateNumChildren(void *implementor,
uint32_t max);
@@ -222,6 +229,13 @@ LLDBSWIGPythonCreateOSPlugin(const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP &process_sp);
+extern "C" void *LLDBSWIGPython_CreateFrameRecognizer(
+ const char *python_class_name,
+ const char *session_dictionary_name);
+
+extern "C" void *LLDBSwigPython_GetRecognizedArguments(void *implementor,
+ const lldb::StackFrameSP& frame_sp);
+
extern "C" bool LLDBSWIGPythonRunScriptKeywordProcess(
const char *python_function_name, const char *session_dictionary_name,
lldb::ProcessSP &process, std::string &output);
@@ -252,9 +266,12 @@ SystemInitializerFull::SystemInitializerFull() {}
SystemInitializerFull::~SystemInitializerFull() {}
-void SystemInitializerFull::Initialize() {
- SystemInitializerCommon::Initialize();
+llvm::Error
+SystemInitializerFull::Initialize(const InitializerOptions &options) {
+ if (auto e = SystemInitializerCommon::Initialize(options))
+ return e;
+ breakpad::ObjectFileBreakpad::Initialize();
ObjectFileELF::Initialize();
ObjectFileMachO::Initialize();
ObjectFilePECOFF::Initialize();
@@ -264,7 +281,6 @@ void SystemInitializerFull::Initialize() {
#ifndef LLDB_DISABLE_PYTHON
OperatingSystemPython::Initialize();
#endif
- OperatingSystemGo::Initialize();
#if !defined(LLDB_DISABLE_PYTHON)
InitializeSWIG();
@@ -296,9 +312,6 @@ void SystemInitializerFull::Initialize() {
llvm::InitializeAllDisassemblers();
ClangASTContext::Initialize();
- GoASTContext::Initialize();
- JavaASTContext::Initialize();
- OCamlASTContext::Initialize();
ABIMacOSX_i386::Initialize();
ABIMacOSX_arm::Initialize();
@@ -315,6 +328,7 @@ void SystemInitializerFull::Initialize() {
ABISysV_s390x::Initialize();
ArchitectureArm::Initialize();
+ ArchitectureMips::Initialize();
ArchitecturePPC64::Initialize();
DisassemblerLLVMC::Initialize();
@@ -330,6 +344,7 @@ void SystemInitializerFull::Initialize() {
MainThreadCheckerRuntime::Initialize();
SymbolVendorELF::Initialize();
+ breakpad::SymbolFileBreakpad::Initialize();
SymbolFileDWARF::Initialize();
SymbolFilePDB::Initialize();
SymbolFileSymtab::Initialize();
@@ -343,15 +358,10 @@ void SystemInitializerFull::Initialize() {
AppleObjCRuntimeV1::Initialize();
SystemRuntimeMacOSX::Initialize();
RenderScriptRuntime::Initialize();
- GoLanguageRuntime::Initialize();
- JavaLanguageRuntime::Initialize();
CPlusPlusLanguage::Initialize();
- GoLanguage::Initialize();
- JavaLanguage::Initialize();
ObjCLanguage::Initialize();
ObjCPlusPlusLanguage::Initialize();
- OCamlLanguage::Initialize();
#if defined(_WIN32)
ProcessWindows::Initialize();
@@ -366,6 +376,7 @@ void SystemInitializerFull::Initialize() {
PlatformAppleWatchSimulator::Initialize();
PlatformRemoteAppleTV::Initialize();
PlatformRemoteAppleWatch::Initialize();
+ PlatformRemoteAppleBridge::Initialize();
DynamicLoaderDarwinKernel::Initialize();
#endif
@@ -393,6 +404,8 @@ void SystemInitializerFull::Initialize() {
// AFTER PluginManager::Initialize is called.
Debugger::SettingsInitialize();
+
+ return llvm::Error::success();
}
void SystemInitializerFull::InitializeSWIG() {
@@ -409,11 +422,14 @@ void SystemInitializerFull::InitializeSWIG() {
LLDBSwigPython_MightHaveChildrenSynthProviderInstance,
LLDBSwigPython_GetValueSynthProviderInstance, LLDBSwigPythonCallCommand,
LLDBSwigPythonCallCommandObject, LLDBSwigPythonCallModuleInit,
- LLDBSWIGPythonCreateOSPlugin, LLDBSWIGPythonRunScriptKeywordProcess,
+ LLDBSWIGPythonCreateOSPlugin, LLDBSWIGPython_CreateFrameRecognizer,
+ LLDBSwigPython_GetRecognizedArguments,
+ LLDBSWIGPythonRunScriptKeywordProcess,
LLDBSWIGPythonRunScriptKeywordThread,
LLDBSWIGPythonRunScriptKeywordTarget, LLDBSWIGPythonRunScriptKeywordFrame,
LLDBSWIGPythonRunScriptKeywordValue, LLDBSWIGPython_GetDynamicSetting,
- LLDBSwigPythonCreateScriptedThreadPlan, LLDBSWIGPythonCallThreadPlan);
+ LLDBSwigPythonCreateScriptedThreadPlan, LLDBSWIGPythonCallThreadPlan,
+ LLDBSwigPythonCreateScriptedBreakpointResolver, LLDBSwigPythonCallBreakpointResolver);
#endif
}
@@ -427,9 +443,10 @@ void SystemInitializerFull::Terminate() {
PluginManager::Terminate();
ClangASTContext::Terminate();
- GoASTContext::Terminate();
- JavaASTContext::Terminate();
- OCamlASTContext::Terminate();
+
+ ArchitectureArm::Terminate();
+ ArchitectureMips::Terminate();
+ ArchitecturePPC64::Terminate();
ABIMacOSX_i386::Terminate();
ABIMacOSX_arm::Terminate();
@@ -456,6 +473,7 @@ void SystemInitializerFull::Terminate() {
UndefinedBehaviorSanitizerRuntime::Terminate();
MainThreadCheckerRuntime::Terminate();
SymbolVendorELF::Terminate();
+ breakpad::SymbolFileBreakpad::Terminate();
SymbolFileDWARF::Terminate();
SymbolFilePDB::Terminate();
SymbolFileSymtab::Terminate();
@@ -469,14 +487,10 @@ void SystemInitializerFull::Terminate() {
AppleObjCRuntimeV1::Terminate();
SystemRuntimeMacOSX::Terminate();
RenderScriptRuntime::Terminate();
- JavaLanguageRuntime::Terminate();
CPlusPlusLanguage::Terminate();
- GoLanguage::Terminate();
- JavaLanguage::Terminate();
ObjCLanguage::Terminate();
ObjCPlusPlusLanguage::Terminate();
- OCamlLanguage::Terminate();
#if defined(__APPLE__)
DynamicLoaderDarwinKernel::Terminate();
@@ -486,6 +500,7 @@ void SystemInitializerFull::Terminate() {
PlatformAppleWatchSimulator::Terminate();
PlatformRemoteAppleTV::Terminate();
PlatformRemoteAppleWatch::Terminate();
+ PlatformRemoteAppleBridge::Terminate();
#endif
#if defined(__FreeBSD__)
@@ -506,7 +521,6 @@ void SystemInitializerFull::Terminate() {
#ifndef LLDB_DISABLE_PYTHON
OperatingSystemPython::Terminate();
#endif
- OperatingSystemGo::Terminate();
platform_freebsd::PlatformFreeBSD::Terminate();
platform_linux::PlatformLinux::Terminate();
@@ -522,6 +536,7 @@ void SystemInitializerFull::Terminate() {
PlatformDarwinKernel::Terminate();
#endif
+ breakpad::ObjectFileBreakpad::Terminate();
ObjectFileELF::Terminate();
ObjectFileMachO::Terminate();
ObjectFilePECOFF::Terminate();
diff --git a/source/API/SystemInitializerFull.h b/source/API/SystemInitializerFull.h
index 9cfc6896da61..b0cf476e9193 100644
--- a/source/API/SystemInitializerFull.h
+++ b/source/API/SystemInitializerFull.h
@@ -26,7 +26,7 @@ public:
SystemInitializerFull();
~SystemInitializerFull() override;
- void Initialize() override;
+ llvm::Error Initialize(const InitializerOptions &options) override;
void Terminate() override;
private:
diff --git a/source/Breakpoint/Breakpoint.cpp b/source/Breakpoint/Breakpoint.cpp
index 1dc029654bfc..131d2a707d44 100644
--- a/source/Breakpoint/Breakpoint.cpp
+++ b/source/Breakpoint/Breakpoint.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/Support/Casting.h"
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
@@ -785,8 +781,8 @@ void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,
// we go.
if (old_id_vec.size() == new_id_vec.size()) {
- llvm::sort(old_id_vec.begin(), old_id_vec.end());
- llvm::sort(new_id_vec.begin(), new_id_vec.end());
+ llvm::sort(old_id_vec);
+ llvm::sort(new_id_vec);
size_t num_elements = old_id_vec.size();
for (size_t idx = 0; idx < num_elements; idx++) {
BreakpointLocationSP old_loc_sp =
@@ -857,6 +853,10 @@ size_t Breakpoint::GetNumResolvedLocations() const {
return m_locations.GetNumResolvedLocations();
}
+bool Breakpoint::HasResolvedLocations() const {
+ return GetNumResolvedLocations() > 0;
+}
+
size_t Breakpoint::GetNumLocations() const { return m_locations.GetSize(); }
bool Breakpoint::AddName(llvm::StringRef new_name) {
diff --git a/source/Breakpoint/BreakpointID.cpp b/source/Breakpoint/BreakpointID.cpp
index 3f72f2052b52..eb12e09abcf1 100644
--- a/source/Breakpoint/BreakpointID.cpp
+++ b/source/Breakpoint/BreakpointID.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdio.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Utility/Status.h"
diff --git a/source/Breakpoint/BreakpointIDList.cpp b/source/Breakpoint/BreakpointIDList.cpp
index bc4c2a111fd4..b86f276a5c47 100644
--- a/source/Breakpoint/BreakpointIDList.cpp
+++ b/source/Breakpoint/BreakpointIDList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/Breakpoint/BreakpointIDList.h"
diff --git a/source/Breakpoint/BreakpointList.cpp b/source/Breakpoint/BreakpointList.cpp
index 4a49b1e105ab..370da10d82b4 100644
--- a/source/Breakpoint/BreakpointList.cpp
+++ b/source/Breakpoint/BreakpointList.cpp
@@ -9,15 +9,18 @@
#include "lldb/Breakpoint/BreakpointList.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
+static void NotifyChange(const BreakpointSP &bp, BreakpointEventType event) {
+ Target &target = bp->GetTarget();
+ if (target.EventTypeHasListeners(Target::eBroadcastBitBreakpointChanged))
+ target.BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
+ new Breakpoint::BreakpointEventData(event, bp));
+}
+
BreakpointList::BreakpointList(bool is_internal)
: m_mutex(), m_breakpoints(), m_next_break_id(0),
m_is_internal(is_internal) {}
@@ -26,37 +29,34 @@ BreakpointList::~BreakpointList() {}
break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
+
// Internal breakpoint IDs are negative, normal ones are positive
bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
m_breakpoints.push_back(bp_sp);
- if (notify) {
- if (bp_sp->GetTarget().EventTypeHasListeners(
- Target::eBroadcastBitBreakpointChanged))
- bp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
- new Breakpoint::BreakpointEventData(
- eBreakpointEventTypeAdded, bp_sp));
- }
+
+ if (notify)
+ NotifyChange(bp_sp, eBreakpointEventTypeAdded);
+
return bp_sp->GetID();
}
bool BreakpointList::Remove(break_id_t break_id, bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- bp_collection::iterator pos = GetBreakpointIDIterator(break_id); // Predicate
- if (pos != m_breakpoints.end()) {
- BreakpointSP bp_sp(*pos);
- m_breakpoints.erase(pos);
- if (notify) {
- if (bp_sp->GetTarget().EventTypeHasListeners(
- Target::eBroadcastBitBreakpointChanged))
- bp_sp->GetTarget().BroadcastEvent(
- Target::eBroadcastBitBreakpointChanged,
- new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
- bp_sp));
- }
- return true;
- }
- return false;
+
+ auto it = std::find_if(
+ m_breakpoints.begin(), m_breakpoints.end(),
+ [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
+
+ if (it == m_breakpoints.end())
+ return false;
+
+ if (notify)
+ NotifyChange(*it, eBreakpointEventTypeRemoved);
+
+ m_breakpoints.erase(it);
+
+ return true;
}
void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
@@ -83,93 +83,50 @@ void BreakpointList::RemoveAll(bool notify) {
ClearAllBreakpointSites();
if (notify) {
- bp_collection::iterator pos, end = m_breakpoints.end();
- for (pos = m_breakpoints.begin(); pos != end; ++pos) {
- if ((*pos)->GetTarget().EventTypeHasListeners(
- Target::eBroadcastBitBreakpointChanged)) {
- (*pos)->GetTarget().BroadcastEvent(
- Target::eBroadcastBitBreakpointChanged,
- new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
- *pos));
- }
- }
+ for (const auto &bp_sp : m_breakpoints)
+ NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
}
- m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end());
+
+ m_breakpoints.clear();
}
void BreakpointList::RemoveAllowed(bool notify) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- bp_collection::iterator pos, end = m_breakpoints.end();
- if (notify) {
- for (pos = m_breakpoints.begin(); pos != end; ++pos) {
- if(!(*pos)->AllowDelete())
- continue;
- if ((*pos)->GetTarget().EventTypeHasListeners(
- Target::eBroadcastBitBreakpointChanged)) {
- (*pos)->GetTarget().BroadcastEvent(
- Target::eBroadcastBitBreakpointChanged,
- new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
- *pos));
- }
- }
- }
- pos = m_breakpoints.begin();
- while ( pos != end) {
- auto bp = *pos;
- if (bp->AllowDelete()) {
- bp->ClearAllBreakpointSites();
- pos = m_breakpoints.erase(pos);
- } else
- pos++;
+ for (const auto &bp_sp : m_breakpoints) {
+ if (bp_sp->AllowDelete())
+ bp_sp->ClearAllBreakpointSites();
+ if (notify)
+ NotifyChange(bp_sp, eBreakpointEventTypeRemoved);
}
-}
-
-class BreakpointIDMatches {
-public:
- BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {}
- bool operator()(const BreakpointSP &bp) const {
- return m_break_id == bp->GetID();
- }
-
-private:
- const break_id_t m_break_id;
-};
+ m_breakpoints.erase(
+ std::remove_if(m_breakpoints.begin(), m_breakpoints.end(),
+ [&](const BreakpointSP &bp) { return bp->AllowDelete(); }),
+ m_breakpoints.end());
+}
BreakpointList::bp_collection::iterator
BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
- return std::find_if(m_breakpoints.begin(),
- m_breakpoints.end(), // Search full range
- BreakpointIDMatches(break_id)); // Predicate
+ return std::find_if(
+ m_breakpoints.begin(), m_breakpoints.end(),
+ [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
}
BreakpointList::bp_collection::const_iterator
BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
- return std::find_if(m_breakpoints.begin(),
- m_breakpoints.end(), // Search full range
- BreakpointIDMatches(break_id)); // Predicate
-}
-
-BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- BreakpointSP stop_sp;
- bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
- if (pos != m_breakpoints.end())
- stop_sp = *pos;
-
- return stop_sp;
+ return std::find_if(
+ m_breakpoints.begin(), m_breakpoints.end(),
+ [&](const BreakpointSP &bp) { return bp->GetID() == break_id; });
}
-const BreakpointSP
-BreakpointList::FindBreakpointByID(break_id_t break_id) const {
+BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- BreakpointSP stop_sp;
- bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
- if (pos != m_breakpoints.end())
- stop_sp = *pos;
- return stop_sp;
+ auto it = GetBreakpointIDConstIterator(break_id);
+ if (it != m_breakpoints.end())
+ return *it;
+ return {};
}
bool BreakpointList::FindBreakpointsByName(const char *name,
@@ -186,6 +143,7 @@ bool BreakpointList::FindBreakpointsByName(const char *name,
matching_bps.Add(bkpt_sp, false);
}
}
+
return true;
}
@@ -201,30 +159,11 @@ void BreakpointList::Dump(Stream *s) const {
s->IndentLess();
}
-BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) {
+BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- BreakpointSP stop_sp;
- bp_collection::iterator end = m_breakpoints.end();
- bp_collection::iterator pos;
- size_t curr_i = 0;
- for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) {
- if (curr_i == i)
- stop_sp = *pos;
- }
- return stop_sp;
-}
-
-const BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- BreakpointSP stop_sp;
- bp_collection::const_iterator end = m_breakpoints.end();
- bp_collection::const_iterator pos;
- size_t curr_i = 0;
- for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) {
- if (curr_i == i)
- stop_sp = *pos;
- }
- return stop_sp;
+ if (i < m_breakpoints.size())
+ return m_breakpoints[i];
+ return {};
}
void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
diff --git a/source/Breakpoint/BreakpointLocation.cpp b/source/Breakpoint/BreakpointLocation.cpp
index 932147703304..5d3763a367c3 100644
--- a/source/Breakpoint/BreakpointLocation.cpp
+++ b/source/Breakpoint/BreakpointLocation.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointID.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
diff --git a/source/Breakpoint/BreakpointLocationCollection.cpp b/source/Breakpoint/BreakpointLocationCollection.cpp
index 6536002bda67..27957a50d2b0 100644
--- a/source/Breakpoint/BreakpointLocationCollection.cpp
+++ b/source/Breakpoint/BreakpointLocationCollection.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
diff --git a/source/Breakpoint/BreakpointLocationList.cpp b/source/Breakpoint/BreakpointLocationList.cpp
index 23ca89da6ce1..6a3280e961cc 100644
--- a/source/Breakpoint/BreakpointLocationList.cpp
+++ b/source/Breakpoint/BreakpointLocationList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocationList.h"
#include "lldb/Breakpoint/Breakpoint.h"
diff --git a/source/Breakpoint/BreakpointName.cpp b/source/Breakpoint/BreakpointName.cpp
index be4710d7849c..baf871ebbae1 100644
--- a/source/Breakpoint/BreakpointName.cpp
+++ b/source/Breakpoint/BreakpointName.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/Support/Casting.h"
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
diff --git a/source/Breakpoint/BreakpointOptions.cpp b/source/Breakpoint/BreakpointOptions.cpp
index b5869fc34dfc..ff497c5633b0 100644
--- a/source/Breakpoint/BreakpointOptions.cpp
+++ b/source/Breakpoint/BreakpointOptions.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
diff --git a/source/Breakpoint/BreakpointResolver.cpp b/source/Breakpoint/BreakpointResolver.cpp
index 6ab578dd8576..0a1eeed28954 100644
--- a/source/Breakpoint/BreakpointResolver.cpp
+++ b/source/Breakpoint/BreakpointResolver.cpp
@@ -9,10 +9,6 @@
#include "lldb/Breakpoint/BreakpointResolver.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
// Have to include the other breakpoint resolver types here so the static
@@ -21,6 +17,7 @@
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/SearchFilter.h"
@@ -44,9 +41,10 @@ const char *BreakpointResolver::g_ty_to_name[] = {"FileAndLine", "Address",
const char *BreakpointResolver::g_option_names[static_cast<uint32_t>(
BreakpointResolver::OptionNames::LastOptionName)] = {
- "AddressOffset", "Exact", "FileName", "Inlines", "Language",
- "LineNumber", "ModuleName", "NameMask", "Offset", "Regex",
- "SectionName", "SkipPrologue", "SymbolNames"};
+ "AddressOffset", "Exact", "FileName", "Inlines", "Language",
+ "LineNumber", "Column", "ModuleName", "NameMask", "Offset",
+ "PythonClass", "Regex", "ScriptArgs", "SectionName", "SearchDepth",
+ "SkipPrologue", "SymbolNames"};
const char *BreakpointResolver::ResolverTyToName(enum ResolverTy type) {
if (type > LastKnownResolverType)
@@ -132,6 +130,10 @@ BreakpointResolverSP BreakpointResolver::CreateFromStructuredData(
resolver = BreakpointResolverFileRegex::CreateFromStructuredData(
nullptr, *subclass_options, error);
break;
+ case PythonResolver:
+ resolver = BreakpointResolverScripted::CreateFromStructuredData(
+ nullptr, *subclass_options, error);
+ break;
case ExceptionResolver:
error.SetErrorString("Exception resolvers are hard.");
break;
@@ -165,6 +167,7 @@ StructuredData::DictionarySP BreakpointResolver::WrapOptionsDict(
void BreakpointResolver::SetBreakpoint(Breakpoint *bkpt) {
m_breakpoint = bkpt;
+ NotifyBreakpointSet();
}
void BreakpointResolver::ResolveBreakpointInModules(SearchFilter &filter,
@@ -176,133 +179,162 @@ void BreakpointResolver::ResolveBreakpoint(SearchFilter &filter) {
filter.Search(*this);
}
+namespace {
+struct SourceLoc {
+ uint32_t line = UINT32_MAX;
+ uint32_t column;
+ SourceLoc(uint32_t l, uint32_t c) : line(l), column(c ? c : UINT32_MAX) {}
+ SourceLoc(const SymbolContext &sc)
+ : line(sc.line_entry.line),
+ column(sc.line_entry.column ? sc.line_entry.column : UINT32_MAX) {}
+};
+
+bool operator<(const SourceLoc a, const SourceLoc b) {
+ if (a.line < b.line)
+ return true;
+ if (a.line > b.line)
+ return false;
+ uint32_t a_col = a.column ? a.column : UINT32_MAX;
+ uint32_t b_col = b.column ? b.column : UINT32_MAX;
+ return a_col < b_col;
+}
+} // namespace
+
void BreakpointResolver::SetSCMatchesByLine(SearchFilter &filter,
SymbolContextList &sc_list,
bool skip_prologue,
- llvm::StringRef log_ident) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ llvm::StringRef log_ident,
+ uint32_t line, uint32_t column) {
+ llvm::SmallVector<SymbolContext, 16> all_scs;
+ for (uint32_t i = 0; i < sc_list.GetSize(); ++i)
+ all_scs.push_back(sc_list[i]);
+
+ while (all_scs.size()) {
+ uint32_t closest_line = UINT32_MAX;
+
+ // Move all the elements with a matching file spec to the end.
+ auto &match = all_scs[0];
+ auto worklist_begin = std::partition(
+ all_scs.begin(), all_scs.end(), [&](const SymbolContext &sc) {
+ if (sc.line_entry.file == match.line_entry.file ||
+ sc.line_entry.original_file == match.line_entry.original_file) {
+ // When a match is found, keep track of the smallest line number.
+ closest_line = std::min(closest_line, sc.line_entry.line);
+ return false;
+ }
+ return true;
+ });
+
+ // (worklist_begin, worklist_end) now contains all entries for one filespec.
+ auto worklist_end = all_scs.end();
+
+ if (column) {
+ // If a column was requested, do a more precise match and only
+ // return the first location that comes after or at the
+ // requested location.
+ SourceLoc requested(line, column);
+ // First, filter out all entries left of the requested column.
+ worklist_end = std::remove_if(
+ worklist_begin, worklist_end,
+ [&](const SymbolContext &sc) { return SourceLoc(sc) < requested; });
+ // Sort the remaining entries by (line, column).
+ llvm::sort(worklist_begin, worklist_end,
+ [](const SymbolContext &a, const SymbolContext &b) {
+ return SourceLoc(a) < SourceLoc(b);
+ });
+
+ // Filter out all locations with a source location after the closest match.
+ if (worklist_begin != worklist_end)
+ worklist_end = std::remove_if(
+ worklist_begin, worklist_end, [&](const SymbolContext &sc) {
+ return SourceLoc(*worklist_begin) < SourceLoc(sc);
+ });
+ } else {
+ // Remove all entries with a larger line number.
+ // ResolveSymbolContext will always return a number that is >=
+ // the line number you pass in. So the smaller line number is
+ // always better.
+ worklist_end = std::remove_if(worklist_begin, worklist_end,
+ [&](const SymbolContext &sc) {
+ return closest_line != sc.line_entry.line;
+ });
+ }
- while (sc_list.GetSize() > 0) {
- SymbolContextList tmp_sc_list;
- unsigned current_idx = 0;
- SymbolContext sc;
- bool first_entry = true;
-
- FileSpec match_file_spec;
- FileSpec match_original_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;
- match_original_file_spec = sc.line_entry.original_file;
- matches = true;
- first_entry = false;
- } else
- matches = ((sc.line_entry.file == match_file_spec) ||
- (sc.line_entry.original_file == match_original_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++;
+ // Sort by file address.
+ llvm::sort(worklist_begin, worklist_end,
+ [](const SymbolContext &a, const SymbolContext &b) {
+ return a.line_entry.range.GetBaseAddress().GetFileAddress() <
+ b.line_entry.range.GetBaseAddress().GetFileAddress();
+ });
+
+ // Go through and see if there are line table entries that are
+ // contiguous, and if so keep only the first of the contiguous range.
+ // We do this by picking the first location in each lexical block.
+ llvm::SmallDenseSet<Block *, 8> blocks_with_breakpoints;
+ for (auto first = worklist_begin; first != worklist_end; ++first) {
+ assert(!blocks_with_breakpoints.count(first->block));
+ blocks_with_breakpoints.insert(first->block);
+ worklist_end =
+ std::remove_if(std::next(first), worklist_end,
+ [&](const SymbolContext &sc) {
+ return blocks_with_breakpoints.count(sc.block);
+ });
}
- // Okay, we've found the closest line number match, now throw away all the
- // others:
+ // Make breakpoints out of the closest line number match.
+ for (auto &sc : llvm::make_range(worklist_begin, worklist_end))
+ AddLocation(filter, sc, skip_prologue, log_ident);
- 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++;
- }
- }
+ // Remove all contexts processed by this iteration.
+ all_scs.erase(worklist_begin, all_scs.end());
+ }
+}
- // 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++;
- }
- }
- }
+void BreakpointResolver::AddLocation(SearchFilter &filter,
+ const SymbolContext &sc,
+ bool skip_prologue,
+ llvm::StringRef log_ident) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ Address line_start = sc.line_entry.range.GetBaseAddress();
+ if (!line_start.IsValid()) {
+ if (log)
+ log->Printf("error: Unable to set breakpoint %s at file address "
+ "0x%" PRIx64 "\n",
+ log_ident.str().c_str(), line_start.GetFileAddress());
+ return;
+ }
- // 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(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.str().c_str(), line_start.GetFileAddress());
- }
- } else {
- if (log)
- log->Printf(
- "error: Unable to set breakpoint %s at file address 0x%" PRIx64
- "\n",
- log_ident.str().c_str(), line_start.GetFileAddress());
+ if (!filter.AddressPasses(line_start)) {
+ if (log)
+ log->Printf("Breakpoint %s at file address 0x%" PRIx64
+ " didn't pass the filter.\n",
+ log_ident.str().c_str(), line_start.GetFileAddress());
+ }
+
+ // If the line number is before the prologue end, move it there...
+ bool skipped_prologue = false;
+ if (skip_prologue && 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(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());
+ }
}
BreakpointLocationSP BreakpointResolver::AddLocation(Address loc_addr,
@@ -315,7 +347,8 @@ void BreakpointResolver::SetOffset(lldb::addr_t offset) {
// There may already be an offset, so we are actually adjusting location
// addresses by the difference.
// lldb::addr_t slide = offset - m_offset;
- // FIXME: We should go fix up all the already set locations for the new slide.
+ // FIXME: We should go fix up all the already set locations for the new
+ // slide.
m_offset = offset;
}
diff --git a/source/Breakpoint/BreakpointResolverAddress.cpp b/source/Breakpoint/BreakpointResolverAddress.cpp
index d4647e2c589d..3084ce41e8e3 100644
--- a/source/Breakpoint/BreakpointResolverAddress.cpp
+++ b/source/Breakpoint/BreakpointResolverAddress.cpp
@@ -9,10 +9,6 @@
#include "lldb/Breakpoint/BreakpointResolverAddress.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
@@ -66,7 +62,7 @@ BreakpointResolver *BreakpointResolverAddress::CreateFromStructuredData(
error.SetErrorString("BRA::CFSD: Couldn't read module name entry.");
return nullptr;
}
- module_filespec.SetFile(module_name, false, FileSpec::Style::native);
+ module_filespec.SetFile(module_name, FileSpec::Style::native);
}
return new BreakpointResolverAddress(bkpt, address, module_filespec);
}
@@ -173,8 +169,8 @@ BreakpointResolverAddress::SearchCallback(SearchFilter &filter,
return Searcher::eCallbackReturnStop;
}
-Searcher::Depth BreakpointResolverAddress::GetDepth() {
- return Searcher::eDepthTarget;
+lldb::SearchDepth BreakpointResolverAddress::GetDepth() {
+ return lldb::eSearchDepthTarget;
}
void BreakpointResolverAddress::GetDescription(Stream *s) {
diff --git a/source/Breakpoint/BreakpointResolverFileLine.cpp b/source/Breakpoint/BreakpointResolverFileLine.cpp
index ecef88eb9989..438f430bd2a5 100644
--- a/source/Breakpoint/BreakpointResolverFileLine.cpp
+++ b/source/Breakpoint/BreakpointResolverFileLine.cpp
@@ -9,10 +9,6 @@
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -28,11 +24,12 @@ using namespace lldb_private;
//----------------------------------------------------------------------
BreakpointResolverFileLine::BreakpointResolverFileLine(
Breakpoint *bkpt, const FileSpec &file_spec, uint32_t line_no,
- lldb::addr_t offset, bool check_inlines, bool skip_prologue,
- bool exact_match)
+ uint32_t column, lldb::addr_t offset, bool check_inlines,
+ bool skip_prologue, bool exact_match)
: BreakpointResolver(bkpt, BreakpointResolver::FileLineResolver, offset),
- m_file_spec(file_spec), m_line_number(line_no), m_inlines(check_inlines),
- m_skip_prologue(skip_prologue), m_exact_match(exact_match) {}
+ m_file_spec(file_spec), m_line_number(line_no), m_column(column),
+ m_inlines(check_inlines), m_skip_prologue(skip_prologue),
+ m_exact_match(exact_match) {}
BreakpointResolverFileLine::~BreakpointResolverFileLine() {}
@@ -41,6 +38,7 @@ BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
Status &error) {
llvm::StringRef filename;
uint32_t line_no;
+ uint32_t column;
bool check_inlines;
bool skip_prologue;
bool exact_match;
@@ -62,6 +60,13 @@ BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
return nullptr;
}
+ success =
+ options_dict.GetValueForKeyAsInteger(GetKey(OptionNames::Column), column);
+ if (!success) {
+ // Backwards compatibility.
+ column = 0;
+ }
+
success = options_dict.GetValueForKeyAsBoolean(GetKey(OptionNames::Inlines),
check_inlines);
if (!success) {
@@ -83,10 +88,10 @@ BreakpointResolver *BreakpointResolverFileLine::CreateFromStructuredData(
return nullptr;
}
- FileSpec file_spec(filename, false);
+ FileSpec file_spec(filename);
- return new BreakpointResolverFileLine(bkpt, file_spec, line_no, offset,
- check_inlines, skip_prologue,
+ return new BreakpointResolverFileLine(bkpt, file_spec, line_no, column,
+ offset, check_inlines, skip_prologue,
exact_match);
}
@@ -99,6 +104,8 @@ BreakpointResolverFileLine::SerializeToStructuredData() {
m_file_spec.GetPath());
options_dict_sp->AddIntegerItem(GetKey(OptionNames::LineNumber),
m_line_number);
+ options_dict_sp->AddIntegerItem(GetKey(OptionNames::Column),
+ m_column);
options_dict_sp->AddBooleanItem(GetKey(OptionNames::Inlines), m_inlines);
options_dict_sp->AddBooleanItem(GetKey(OptionNames::SkipPrologue),
m_skip_prologue);
@@ -181,8 +188,12 @@ void BreakpointResolverFileLine::FilterContexts(SymbolContextList &sc_list,
// inline int foo2() { ... }
//
// but that's the best we can do for now.
+ // One complication, if the line number returned from GetStartLineSourceInfo
+ // is 0, then we can't do this calculation. That can happen if
+ // GetStartLineSourceInfo gets an error, or if the first line number in
+ // the function really is 0 - which happens for some languages.
const int decl_line_is_too_late_fudge = 1;
- if (m_line_number < line - decl_line_is_too_late_fudge) {
+ if (line && m_line_number < line - decl_line_is_too_late_fudge) {
LLDB_LOG(log, "removing symbol context at {0}:{1}", file, line);
sc_list.RemoveContextAtIndex(i);
--i;
@@ -236,18 +247,22 @@ BreakpointResolverFileLine::SearchCallback(SearchFilter &filter,
s.Printf("for %s:%d ", m_file_spec.GetFilename().AsCString("<Unknown>"),
m_line_number);
- SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString());
+ SetSCMatchesByLine(filter, sc_list, m_skip_prologue, s.GetString(),
+ m_line_number, m_column);
return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth BreakpointResolverFileLine::GetDepth() {
- return Searcher::eDepthModule;
+lldb::SearchDepth BreakpointResolverFileLine::GetDepth() {
+ return lldb::eSearchDepthModule;
}
void BreakpointResolverFileLine::GetDescription(Stream *s) {
- s->Printf("file = '%s', line = %u, exact_match = %d",
- m_file_spec.GetPath().c_str(), m_line_number, m_exact_match);
+ s->Printf("file = '%s', line = %u, ", m_file_spec.GetPath().c_str(),
+ m_line_number);
+ if (m_column)
+ s->Printf("column = %u, ", m_column);
+ s->Printf("exact_match = %d", m_exact_match);
}
void BreakpointResolverFileLine::Dump(Stream *s) const {}
@@ -255,7 +270,7 @@ void BreakpointResolverFileLine::Dump(Stream *s) const {}
lldb::BreakpointResolverSP
BreakpointResolverFileLine::CopyForBreakpoint(Breakpoint &breakpoint) {
lldb::BreakpointResolverSP ret_sp(new BreakpointResolverFileLine(
- &breakpoint, m_file_spec, m_line_number, m_offset, m_inlines,
+ &breakpoint, m_file_spec, m_line_number, m_column, m_offset, m_inlines,
m_skip_prologue, m_exact_match));
return ret_sp;
diff --git a/source/Breakpoint/BreakpointResolverFileRegex.cpp b/source/Breakpoint/BreakpointResolverFileRegex.cpp
index 54c05a042468..62cf9553c82c 100644
--- a/source/Breakpoint/BreakpointResolverFileRegex.cpp
+++ b/source/Breakpoint/BreakpointResolverFileRegex.cpp
@@ -9,10 +9,6 @@
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -157,8 +153,8 @@ BreakpointResolverFileRegex::SearchCallback(SearchFilter &filter,
return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth BreakpointResolverFileRegex::GetDepth() {
- return Searcher::eDepthCompUnit;
+lldb::SearchDepth BreakpointResolverFileRegex::GetDepth() {
+ return lldb::eSearchDepthCompUnit;
}
void BreakpointResolverFileRegex::GetDescription(Stream *s) {
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
index ba277ae2655e..43f7cb85a574 100644
--- a/source/Breakpoint/BreakpointResolverName.cpp
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolverName.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
@@ -30,7 +26,7 @@ using namespace lldb;
using namespace lldb_private;
BreakpointResolverName::BreakpointResolverName(
- Breakpoint *bkpt, const char *name_cstr, uint32_t name_type_mask,
+ Breakpoint *bkpt, const char *name_cstr, FunctionNameType name_type_mask,
LanguageType language, Breakpoint::MatchType type, lldb::addr_t offset,
bool skip_prologue)
: BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
@@ -51,7 +47,7 @@ BreakpointResolverName::BreakpointResolverName(
BreakpointResolverName::BreakpointResolverName(
Breakpoint *bkpt, const char *names[], size_t num_names,
- uint32_t name_type_mask, LanguageType language, lldb::addr_t offset,
+ FunctionNameType name_type_mask, LanguageType language, lldb::addr_t offset,
bool skip_prologue)
: BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
m_match_type(Breakpoint::Exact), m_language(language),
@@ -61,9 +57,12 @@ BreakpointResolverName::BreakpointResolverName(
}
}
-BreakpointResolverName::BreakpointResolverName(
- Breakpoint *bkpt, std::vector<std::string> names, uint32_t name_type_mask,
- LanguageType language, lldb::addr_t offset, bool skip_prologue)
+BreakpointResolverName::BreakpointResolverName(Breakpoint *bkpt,
+ std::vector<std::string> names,
+ FunctionNameType name_type_mask,
+ LanguageType language,
+ lldb::addr_t offset,
+ bool skip_prologue)
: BreakpointResolver(bkpt, BreakpointResolver::NameResolver, offset),
m_match_type(Breakpoint::Exact), m_language(language),
m_skip_prologue(skip_prologue) {
@@ -161,9 +160,8 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData(
return nullptr;
}
std::vector<std::string> names;
- std::vector<uint32_t> name_masks;
+ std::vector<FunctionNameType> name_masks;
for (size_t i = 0; i < num_elem; i++) {
- uint32_t name_mask;
llvm::StringRef name;
success = names_array->GetItemAtIndexAsString(i, name);
@@ -171,13 +169,14 @@ BreakpointResolver *BreakpointResolverName::CreateFromStructuredData(
error.SetErrorString("BRN::CFSD: name entry is not a string.");
return nullptr;
}
- success = names_mask_array->GetItemAtIndexAsInteger(i, name_mask);
+ std::underlying_type<FunctionNameType>::type fnt;
+ success = names_mask_array->GetItemAtIndexAsInteger(i, fnt);
if (!success) {
error.SetErrorString("BRN::CFSD: name mask entry is not an integer.");
return nullptr;
}
names.push_back(name);
- name_masks.push_back(name_mask);
+ name_masks.push_back(static_cast<FunctionNameType>(fnt));
}
BreakpointResolverName *resolver = new BreakpointResolverName(
@@ -220,7 +219,7 @@ StructuredData::ObjectSP BreakpointResolverName::SerializeToStructuredData() {
}
void BreakpointResolverName::AddNameLookup(const ConstString &name,
- uint32_t name_type_mask) {
+ FunctionNameType name_type_mask) {
ObjCLanguage::MethodName objc_method(name.GetCString(), false);
if (objc_method.IsValid(false)) {
std::vector<ConstString> objc_names;
@@ -396,8 +395,8 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter,
return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth BreakpointResolverName::GetDepth() {
- return Searcher::eDepthModule;
+lldb::SearchDepth BreakpointResolverName::GetDepth() {
+ return lldb::eSearchDepthModule;
}
void BreakpointResolverName::GetDescription(Stream *s) {
diff --git a/source/Breakpoint/BreakpointResolverScripted.cpp b/source/Breakpoint/BreakpointResolverScripted.cpp
new file mode 100644
index 000000000000..47940ef60703
--- /dev/null
+++ b/source/Breakpoint/BreakpointResolverScripted.cpp
@@ -0,0 +1,189 @@
+//===-- BreakpointResolverScripted.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/Breakpoint/BreakpointResolverScripted.h"
+
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// BreakpointResolverScripted:
+//----------------------------------------------------------------------
+BreakpointResolverScripted::BreakpointResolverScripted(
+ Breakpoint *bkpt,
+ const llvm::StringRef class_name,
+ lldb::SearchDepth depth,
+ StructuredDataImpl *args_data,
+ ScriptInterpreter &script_interp)
+ : BreakpointResolver(bkpt, BreakpointResolver::PythonResolver),
+ m_class_name(class_name), m_depth(depth), m_args_ptr(args_data) {
+ CreateImplementationIfNeeded();
+}
+
+void BreakpointResolverScripted::CreateImplementationIfNeeded() {
+ if (m_implementation_sp)
+ return;
+
+ if (m_class_name.empty())
+ return;
+
+ if (m_breakpoint) {
+ TargetSP target_sp = m_breakpoint->GetTargetSP();
+ ScriptInterpreter *script_interp = target_sp->GetDebugger()
+ .GetCommandInterpreter()
+ .GetScriptInterpreter();
+ if (!script_interp)
+ return;
+ lldb::BreakpointSP bkpt_sp(m_breakpoint->shared_from_this());
+ m_implementation_sp = script_interp->CreateScriptedBreakpointResolver(
+ m_class_name.c_str(), m_args_ptr, bkpt_sp);
+ }
+}
+
+void BreakpointResolverScripted::NotifyBreakpointSet() {
+ CreateImplementationIfNeeded();
+}
+
+BreakpointResolverScripted::~BreakpointResolverScripted() {}
+
+BreakpointResolver *
+BreakpointResolverScripted::CreateFromStructuredData(
+ Breakpoint *bkpt, const StructuredData::Dictionary &options_dict,
+ Status &error) {
+ llvm::StringRef class_name;
+ bool success;
+
+ if (!bkpt)
+ return nullptr;
+
+ success = options_dict.GetValueForKeyAsString(
+ GetKey(OptionNames::PythonClassName), class_name);
+ if (!success) {
+ error.SetErrorString("BRFL::CFSD: Couldn't find class name entry.");
+ return nullptr;
+ }
+ lldb::SearchDepth depth;
+ int depth_as_int;
+ success = options_dict.GetValueForKeyAsInteger(
+ GetKey(OptionNames::SearchDepth), depth_as_int);
+ if (!success) {
+ error.SetErrorString("BRFL::CFSD: Couldn't find class name entry.");
+ return nullptr;
+ }
+ if (depth_as_int >= (int) OptionNames::LastOptionName) {
+ error.SetErrorString("BRFL::CFSD: Invalid value for search depth.");
+ return nullptr;
+ }
+ depth = (lldb::SearchDepth) depth_as_int;
+
+ StructuredDataImpl *args_data_impl = new StructuredDataImpl();
+ StructuredData::Dictionary *args_dict = new StructuredData::Dictionary();
+ success = options_dict.GetValueForKeyAsDictionary(
+ GetKey(OptionNames::ScriptArgs), args_dict);
+ if (success) {
+ // FIXME: The resolver needs a copy of the ARGS dict that it can own,
+ // so I need to make a copy constructor for the Dictionary so I can pass
+ // that to it here. For now the args are empty.
+ //StructuredData::Dictionary *dict_copy = new StructuredData::Dictionary(args_dict);
+
+ }
+ ScriptInterpreter *script_interp = bkpt->GetTarget()
+ .GetDebugger()
+ .GetCommandInterpreter()
+ .GetScriptInterpreter();
+ return new BreakpointResolverScripted(bkpt, class_name, depth, args_data_impl,
+ *script_interp);
+}
+
+StructuredData::ObjectSP
+BreakpointResolverScripted::SerializeToStructuredData() {
+ StructuredData::DictionarySP options_dict_sp(
+ new StructuredData::Dictionary());
+
+ options_dict_sp->AddStringItem(GetKey(OptionNames::PythonClassName),
+ m_class_name);
+ return WrapOptionsDict(options_dict_sp);
+}
+
+ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() {
+ return m_breakpoint->GetTarget().GetDebugger().GetCommandInterpreter()
+ .GetScriptInterpreter();
+}
+
+Searcher::CallbackReturn
+BreakpointResolverScripted::SearchCallback(SearchFilter &filter,
+ SymbolContext &context, Address *addr,
+ bool containing) {
+ assert(m_breakpoint != NULL);
+ bool should_continue = true;
+ if (!m_implementation_sp)
+ return Searcher::eCallbackReturnStop;
+
+ ScriptInterpreter *interp = GetScriptInterpreter();
+ should_continue = interp->ScriptedBreakpointResolverSearchCallback(
+ m_implementation_sp,
+ &context);
+ if (should_continue)
+ return Searcher::eCallbackReturnContinue;
+ else
+ return Searcher::eCallbackReturnStop;
+}
+
+lldb::SearchDepth
+BreakpointResolverScripted::GetDepth() {
+ assert(m_breakpoint != NULL);
+ lldb::SearchDepth depth = lldb::eSearchDepthModule;
+ if (m_implementation_sp) {
+ ScriptInterpreter *interp = GetScriptInterpreter();
+ depth = interp->ScriptedBreakpointResolverSearchDepth(
+ m_implementation_sp);
+ }
+ return depth;
+}
+
+void BreakpointResolverScripted::GetDescription(Stream *s) {
+ StructuredData::GenericSP generic_sp;
+ std::string short_help;
+
+ if (m_implementation_sp) {
+ ScriptInterpreter *interp = GetScriptInterpreter();
+ interp->GetShortHelpForCommandObject(m_implementation_sp,
+ short_help);
+ }
+ if (!short_help.empty())
+ s->PutCString(short_help.c_str());
+ else
+ s->Printf("python class = %s", m_class_name.c_str());
+}
+
+void BreakpointResolverScripted::Dump(Stream *s) const {}
+
+lldb::BreakpointResolverSP
+BreakpointResolverScripted::CopyForBreakpoint(Breakpoint &breakpoint) {
+ ScriptInterpreter *script_interp = GetScriptInterpreter();
+ // FIXME: Have to make a copy of the arguments from the m_args_ptr and then
+ // pass that to the new resolver.
+ lldb::BreakpointResolverSP ret_sp(
+ new BreakpointResolverScripted(&breakpoint, m_class_name,
+ m_depth, nullptr, *script_interp));
+ return ret_sp;
+}
diff --git a/source/Breakpoint/BreakpointSite.cpp b/source/Breakpoint/BreakpointSite.cpp
index a5c5136eb7a6..73c1357ce963 100644
--- a/source/Breakpoint/BreakpointSite.cpp
+++ b/source/Breakpoint/BreakpointSite.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <inttypes.h>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Breakpoint/Breakpoint.h"
diff --git a/source/Breakpoint/BreakpointSiteList.cpp b/source/Breakpoint/BreakpointSiteList.cpp
index 9bb9aa366106..2fe107ee3e30 100644
--- a/source/Breakpoint/BreakpointSiteList.cpp
+++ b/source/Breakpoint/BreakpointSiteList.cpp
@@ -9,10 +9,6 @@
#include "lldb/Breakpoint/BreakpointSiteList.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Stream.h"
#include <algorithm>
diff --git a/source/Breakpoint/CMakeLists.txt b/source/Breakpoint/CMakeLists.txt
index f93d48579ad7..9ce3a3b93e09 100644
--- a/source/Breakpoint/CMakeLists.txt
+++ b/source/Breakpoint/CMakeLists.txt
@@ -13,6 +13,7 @@ add_lldb_library(lldbBreakpoint
BreakpointResolverFileLine.cpp
BreakpointResolverFileRegex.cpp
BreakpointResolverName.cpp
+ BreakpointResolverScripted.cpp
BreakpointSite.cpp
BreakpointSiteList.cpp
Stoppoint.cpp
diff --git a/source/Breakpoint/Stoppoint.cpp b/source/Breakpoint/Stoppoint.cpp
index dbc832b4307a..13a8b837469f 100644
--- a/source/Breakpoint/Stoppoint.cpp
+++ b/source/Breakpoint/Stoppoint.cpp
@@ -10,10 +10,6 @@
#include "lldb/Breakpoint/Stoppoint.h"
#include "lldb/lldb-private.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Breakpoint/StoppointCallbackContext.cpp b/source/Breakpoint/StoppointCallbackContext.cpp
index 3d24eb78c455..828ff18c433f 100644
--- a/source/Breakpoint/StoppointCallbackContext.cpp
+++ b/source/Breakpoint/StoppointCallbackContext.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
using namespace lldb_private;
diff --git a/source/Breakpoint/StoppointLocation.cpp b/source/Breakpoint/StoppointLocation.cpp
index d624ddbfa519..73394668508b 100644
--- a/source/Breakpoint/StoppointLocation.cpp
+++ b/source/Breakpoint/StoppointLocation.cpp
@@ -9,10 +9,6 @@
#include "lldb/Breakpoint/StoppointLocation.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Breakpoint/Watchpoint.cpp b/source/Breakpoint/Watchpoint.cpp
index 7a936d1fb130..34daaee64ccd 100644
--- a/source/Breakpoint/Watchpoint.cpp
+++ b/source/Breakpoint/Watchpoint.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -135,10 +131,7 @@ void Watchpoint::IncrementFalseAlarmsAndReviseHitCount() {
bool Watchpoint::ShouldStop(StoppointCallbackContext *context) {
IncrementHitCount();
- if (!IsEnabled())
- return false;
-
- return true;
+ return IsEnabled();
}
void Watchpoint::GetDescription(Stream *s, lldb::DescriptionLevel level) {
diff --git a/source/Breakpoint/WatchpointList.cpp b/source/Breakpoint/WatchpointList.cpp
index 6497780084d9..e1e2864ba0eb 100644
--- a/source/Breakpoint/WatchpointList.cpp
+++ b/source/Breakpoint/WatchpointList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Breakpoint/Watchpoint.h"
diff --git a/source/Breakpoint/WatchpointOptions.cpp b/source/Breakpoint/WatchpointOptions.cpp
index 402fee943a02..033eb66014b9 100644
--- a/source/Breakpoint/WatchpointOptions.cpp
+++ b/source/Breakpoint/WatchpointOptions.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
diff --git a/source/Commands/CMakeLists.txt b/source/Commands/CMakeLists.txt
index 1dbaab5174e0..41c54ea03086 100644
--- a/source/Commands/CMakeLists.txt
+++ b/source/Commands/CMakeLists.txt
@@ -18,6 +18,7 @@ add_lldb_library(lldbCommands
CommandObjectProcess.cpp
CommandObjectQuit.cpp
CommandObjectRegister.cpp
+ CommandObjectReproducer.cpp
CommandObjectSettings.cpp
CommandObjectSource.cpp
CommandObjectStats.cpp
diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp
index 7b351c50dc69..705e87651a8c 100644
--- a/source/Commands/CommandCompletions.cpp
+++ b/source/Commands/CommandCompletions.cpp
@@ -7,18 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <sys/stat.h>
#if defined(__APPLE__) || defined(__linux__)
#include <pwd.h>
#endif
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSet.h"
-// Project includes
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
@@ -105,7 +101,6 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
if (CompletionBuffer.size() >= PATH_MAX)
return matches.GetSize();
- namespace fs = llvm::sys::fs;
namespace path = llvm::sys::path;
llvm::StringRef SearchDir;
@@ -121,7 +116,7 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
if (FirstSep != llvm::StringRef::npos)
Remainder = Buffer.drop_front(FirstSep + 1);
- llvm::SmallString<PATH_MAX> Resolved;
+ llvm::SmallString<256> Resolved;
if (!Resolver.ResolveExact(Username, Resolved)) {
// We couldn't resolve it as a full username. If there were no slashes
// then this might be a partial username. We try to resolve it as such
@@ -166,7 +161,11 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
size_t FullPrefixLen = CompletionBuffer.size();
PartialItem = path::filename(CompletionBuffer);
- if (PartialItem == ".")
+
+ // path::filename() will return "." when the passed path ends with a
+ // directory separator. We have to filter those out, but only when the
+ // "." doesn't come from the completion request itself.
+ if (PartialItem == "." && path::is_separator(CompletionBuffer.back()))
PartialItem = llvm::StringRef();
if (SearchDir.empty()) {
@@ -178,11 +177,16 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
// SearchDir now contains the directory to search in, and Prefix contains the
// text we want to match against items in that directory.
+ FileSystem &fs = FileSystem::Instance();
std::error_code EC;
- fs::directory_iterator Iter(SearchDir, EC, false);
- fs::directory_iterator End;
+ llvm::vfs::directory_iterator Iter = fs.DirBegin(SearchDir, EC);
+ llvm::vfs::directory_iterator End;
for (; Iter != End && !EC; Iter.increment(EC)) {
auto &Entry = *Iter;
+ llvm::ErrorOr<llvm::vfs::Status> Status = fs.GetStatus(Entry.path());
+
+ if (!Status)
+ continue;
auto Name = path::filename(Entry.path());
@@ -190,20 +194,18 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
if (Name == "." || Name == ".." || !Name.startswith(PartialItem))
continue;
- // We have a match.
-
- llvm::ErrorOr<fs::basic_file_status> st = Entry.status();
- if (!st)
- continue;
+ bool is_dir = Status->isDirectory();
// If it's a symlink, then we treat it as a directory as long as the target
// is a directory.
- bool is_dir = fs::is_directory(*st);
- if (fs::is_symlink_file(*st)) {
- fs::file_status target_st;
- if (!fs::status(Entry.path(), target_st))
- is_dir = fs::is_directory(target_st);
+ if (Status->isSymlink()) {
+ FileSpec symlink_filespec(Entry.path());
+ FileSpec resolved_filespec;
+ auto error = fs.ResolveSymbolicLink(symlink_filespec, resolved_filespec);
+ if (error.Success())
+ is_dir = fs.IsDirectory(symlink_filespec);
}
+
if (only_directories && !is_dir)
continue;
@@ -357,13 +359,13 @@ CommandCompletions::SourceFileCompleter::SourceFileCompleter(
CompletionRequest &request)
: CommandCompletions::Completer(interpreter, request),
m_include_support_files(include_support_files), m_matching_files() {
- FileSpec partial_spec(m_request.GetCursorArgumentPrefix(), false);
+ FileSpec partial_spec(m_request.GetCursorArgumentPrefix());
m_file_name = partial_spec.GetFilename().GetCString();
m_dir_name = partial_spec.GetDirectory().GetCString();
}
-Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
- return eDepthCompUnit;
+lldb::SearchDepth CommandCompletions::SourceFileCompleter::GetDepth() {
+ return lldb::eSearchDepthCompUnit;
}
Searcher::CallbackReturn
@@ -454,8 +456,8 @@ CommandCompletions::SymbolCompleter::SymbolCompleter(
m_regex.Compile(regex_str);
}
-Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
- return eDepthModule;
+lldb::SearchDepth CommandCompletions::SymbolCompleter::GetDepth() {
+ return lldb::eSearchDepthModule;
}
Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
@@ -497,13 +499,13 @@ size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
CommandCompletions::ModuleCompleter::ModuleCompleter(
CommandInterpreter &interpreter, CompletionRequest &request)
: CommandCompletions::Completer(interpreter, request) {
- FileSpec partial_spec(m_request.GetCursorArgumentPrefix(), false);
+ FileSpec partial_spec(m_request.GetCursorArgumentPrefix());
m_file_name = partial_spec.GetFilename().GetCString();
m_dir_name = partial_spec.GetDirectory().GetCString();
}
-Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
- return eDepthModule;
+lldb::SearchDepth CommandCompletions::ModuleCompleter::GetDepth() {
+ return lldb::eSearchDepthModule;
}
Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
diff --git a/source/Commands/CommandObjectApropos.cpp b/source/Commands/CommandObjectApropos.cpp
index 047575278faa..69c2760ded4e 100644
--- a/source/Commands/CommandObjectApropos.cpp
+++ b/source/Commands/CommandObjectApropos.cpp
@@ -8,10 +8,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectApropos.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
diff --git a/source/Commands/CommandObjectApropos.h b/source/Commands/CommandObjectApropos.h
index 5cad40d5c62d..acd4cedfe9fd 100644
--- a/source/Commands/CommandObjectApropos.h
+++ b/source/Commands/CommandObjectApropos.h
@@ -11,10 +11,6 @@
#ifndef liblldb_CommandObjectApropos_h_
#define liblldb_CommandObjectApropos_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp
index fb0553e482db..8eb6a5fa5a02 100644
--- a/source/Commands/CommandObjectBreakpoint.cpp
+++ b/source/Commands/CommandObjectBreakpoint.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectBreakpoint.h"
#include "CommandObjectBreakpointCommand.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -50,19 +46,19 @@ static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
// Modifiable Breakpoint Options
//-------------------------------------------------------------------------
#pragma mark Modify::CommandOptions
-static OptionDefinition g_breakpoint_modify_options[] = {
+static constexpr OptionDefinition g_breakpoint_modify_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
- { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
- { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
- { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
- { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
- { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
- { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
- { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
- { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
- { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
- { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
+ { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
+ { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
+ { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
+ { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
+ { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
+ { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
+ { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
+ { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
+ { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
+ { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
+ { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." },
// clang-format on
};
class lldb_private::BreakpointOptionGroup : public OptionGroup
@@ -198,9 +194,9 @@ public:
BreakpointOptions m_bp_opts;
};
-static OptionDefinition g_breakpoint_dummy_options[] = {
+static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
"which prime new targets." },
// clang-format on
};
@@ -245,23 +241,23 @@ public:
// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
-#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
-#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
+#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
-#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
+#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
+#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
-static OptionDefinition g_breakpoint_set_options[] = {
+static constexpr OptionDefinition g_breakpoint_set_options[] = {
// clang-format off
- { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
+ { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, 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, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
- { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
+ { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
+ { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
"lldb only looks for files that are #included if they use the standard include "
"file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
"#included, set target.inline-breakpoint-strategy to \"always\"." },
- { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 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
@@ -269,7 +265,7 @@ static OptionDefinition g_breakpoint_set_options[] = {
// { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
// "Set the breakpoint by source location at this particular column."},
- { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
+ { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
"a particular binary, then the address will be converted to a \"file\" "
"address, so that the breakpoint will track that binary+offset no matter where "
"the binary eventually loads. Alternately, if you also specify the module - "
@@ -278,47 +274,50 @@ static OptionDefinition g_breakpoint_set_options[] = {
"that offset on subsequent reloads. The module need not have been loaded at "
"the time you specify this breakpoint, and will get resolved when the module "
"is loaded." },
- { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
+ { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
"one breakpoint for multiple names" },
- { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
+ { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
"functions. Can be repeated multiple times." },
- { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
+ { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
"namespaces and all arguments, and for Objective-C this means a full function "
"prototype with class and selector. Can be repeated multiple times to make "
"one breakpoint for multiple names." },
- { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
+ { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
"make one breakpoint for multiple Selectors." },
- { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
+ { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
"make one breakpoint for multiple methods." },
- { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
+ { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
"the function name(s)." },
- { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
+ { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
"ignored). Can be repeated multiple times to make one breakpoint for multiple "
"symbols." },
- { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched "
+ { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 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\". If you want to "
"match against all source files, pass the \"--all-files\" option." },
- { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." },
- { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
+ { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
+ { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
+ { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
+ { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
+ { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
"options, on throw but not catch.)" },
- { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
- { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
+ { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
+ { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
// Don't add this option till it actually does something useful...
// { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
// "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" },
- { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
+ { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
"(note: currently only implemented for setting breakpoints on identifiers). "
"If not set the target.language setting is used." },
- { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
+ { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
"If not set the target.skip-prologue setting is used." },
- { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
- { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
+ { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
+ { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
"At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
- { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
+ { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
"setting is used." },
// clang-format on
};
@@ -336,7 +335,8 @@ public:
eSetTypeFunctionName,
eSetTypeFunctionRegexp,
eSetTypeSourceRegexp,
- eSetTypeException
+ eSetTypeException,
+ eSetTypeScripted,
} BreakpointSetType;
CommandObjectBreakpointSet(CommandInterpreter &interpreter)
@@ -434,7 +434,7 @@ public:
} break;
case 'f':
- m_filenames.AppendIfUnique(FileSpec(option_arg, false));
+ m_filenames.AppendIfUnique(FileSpec(option_arg));
break;
case 'F':
@@ -454,7 +454,15 @@ public:
case 'H':
m_hardware = true;
break;
-
+
+ case 'k': {
+ if (m_current_key.empty())
+ m_current_key.assign(option_arg);
+ else
+ error.SetErrorStringWithFormat("Key: %s missing value.",
+ m_current_key.c_str());
+
+ } break;
case 'K': {
bool success;
bool value;
@@ -535,13 +543,17 @@ public:
case 'p':
m_source_text_regexp.assign(option_arg);
break;
+
+ case 'P':
+ m_python_class.assign(option_arg);
+ break;
case 'r':
m_func_regexp.assign(option_arg);
break;
case 's':
- m_modules.AppendIfUnique(FileSpec(option_arg, false));
+ m_modules.AppendIfUnique(FileSpec(option_arg));
break;
case 'S':
@@ -549,6 +561,16 @@ public:
m_func_name_type_mask |= eFunctionNameTypeSelector;
break;
+ case 'v': {
+ if (!m_current_key.empty()) {
+ m_extra_args_sp->AddStringItem(m_current_key, option_arg);
+ m_current_key.clear();
+ }
+ else
+ error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
+ option_arg.str().c_str());
+ } break;
+
case 'w': {
bool success;
m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
@@ -593,6 +615,9 @@ public:
m_exception_extra_args.Clear();
m_move_to_nearest_code = eLazyBoolCalculate;
m_source_regex_func_names.clear();
+ m_python_class.clear();
+ m_extra_args_sp.reset(new StructuredData::Dictionary());
+ m_current_key.clear();
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -607,7 +632,7 @@ public:
uint32_t m_column;
std::vector<std::string> m_func_names;
std::vector<std::string> m_breakpoint_names;
- uint32_t m_func_name_type_mask;
+ lldb::FunctionNameType m_func_name_type_mask;
std::string m_func_regexp;
std::string m_source_text_regexp;
FileSpecList m_modules;
@@ -623,6 +648,9 @@ public:
Args m_exception_extra_args;
LazyBool m_move_to_nearest_code;
std::unordered_set<std::string> m_source_regex_func_names;
+ std::string m_python_class;
+ StructuredData::DictionarySP m_extra_args_sp;
+ std::string m_current_key;
};
protected:
@@ -649,7 +677,9 @@ protected:
BreakpointSetType break_type = eSetTypeInvalid;
- if (m_options.m_line_num != 0)
+ if (!m_options.m_python_class.empty())
+ break_type = eSetTypeScripted;
+ else if (m_options.m_line_num != 0)
break_type = eSetTypeFileAndLine;
else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
break_type = eSetTypeAddress;
@@ -696,7 +726,8 @@ protected:
bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
file,
- m_options.m_line_num,
+ m_options.m_line_num,
+ m_options.m_column,
m_options.m_offset_addr,
check_inlines,
m_options.m_skip_prologue,
@@ -730,7 +761,7 @@ protected:
}
case eSetTypeFunctionName: // Breakpoint by function name
{
- uint32_t name_type_mask = m_options.m_func_name_type_mask;
+ FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
if (name_type_mask == 0)
name_type_mask = eFunctionNameTypeAuto;
@@ -823,6 +854,25 @@ protected:
return false;
}
} break;
+ case eSetTypeScripted: {
+
+ Status error;
+ bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
+ &(m_options.m_modules),
+ &(m_options.m_filenames),
+ false,
+ m_options.m_hardware,
+ m_options.m_extra_args_sp,
+ &error);
+ if (error.Fail()) {
+ result.AppendErrorWithFormat(
+ "Error setting extra exception arguments: %s",
+ error.AsCString());
+ target->RemoveBreakpointByID(bp_sp->GetID());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ } break;
default:
break;
}
@@ -1207,15 +1257,15 @@ protected:
//-------------------------------------------------------------------------
#pragma mark List::CommandOptions
-static OptionDefinition g_breakpoint_list_options[] = {
+static constexpr OptionDefinition g_breakpoint_list_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
- { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
+ { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
+ { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
// FIXME: We need to add an "internal" command, and then add this sort of thing to it.
// But I need to see it for now, and don't want to wait.
- { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
- { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
- { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
+ { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
+ { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
// clang-format on
};
@@ -1373,10 +1423,10 @@ private:
//-------------------------------------------------------------------------
#pragma mark Clear::CommandOptions
-static OptionDefinition g_breakpoint_clear_options[] = {
+static constexpr OptionDefinition g_breakpoint_clear_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
- { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
// clang-format on
};
@@ -1531,10 +1581,10 @@ private:
//-------------------------------------------------------------------------
// CommandObjectBreakpointDelete
//-------------------------------------------------------------------------
-static OptionDefinition g_breakpoint_delete_options[] = {
+static constexpr OptionDefinition g_breakpoint_delete_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
- { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
+ { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
// clang-format on
};
@@ -1688,12 +1738,12 @@ private:
// CommandObjectBreakpointName
//-------------------------------------------------------------------------
-static OptionDefinition g_breakpoint_name_options[] = {
+static constexpr OptionDefinition g_breakpoint_name_options[] = {
// clang-format off
- {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
- {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
- {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
- {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A help string describing the purpose of this name."},
+ {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
+ {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
+ {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+ {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."},
// clang-format on
};
class BreakpointNameOptionGroup : public OptionGroup {
@@ -1757,23 +1807,20 @@ public:
OptionValueString m_help_string;
};
-static OptionDefinition g_breakpoint_access_options[] = {
+static constexpr OptionDefinition g_breakpoint_access_options[] = {
// clang-format off
- {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
- {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
- {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
+ {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
+ {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
+ {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
// clang-format on
};
-class BreakpointAccessOptionGroup : public OptionGroup
-{
+class BreakpointAccessOptionGroup : public OptionGroup {
public:
- BreakpointAccessOptionGroup() :
- OptionGroup()
- {}
-
+ BreakpointAccessOptionGroup() : OptionGroup() {}
+
~BreakpointAccessOptionGroup() override = default;
-
+
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
return llvm::makeArrayRef(g_breakpoint_access_options);
}
@@ -2229,10 +2276,10 @@ public:
// CommandObjectBreakpointRead
//-------------------------------------------------------------------------
#pragma mark Read::CommandOptions
-static OptionDefinition g_breakpoint_read_options[] = {
+static constexpr OptionDefinition g_breakpoint_read_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
- {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
+ {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
+ {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
// clang-format on
};
@@ -2319,7 +2366,8 @@ protected:
std::unique_lock<std::recursive_mutex> lock;
target->GetBreakpointList().GetListMutex(lock);
- FileSpec input_spec(m_options.m_filename, true);
+ FileSpec input_spec(m_options.m_filename);
+ FileSystem::Instance().Resolve(input_spec);
BreakpointIDList new_bps;
Status error = target->CreateBreakpointsFromFile(
input_spec, m_options.m_names, new_bps);
@@ -2359,10 +2407,10 @@ private:
// CommandObjectBreakpointWrite
//-------------------------------------------------------------------------
#pragma mark Write::CommandOptions
-static OptionDefinition g_breakpoint_write_options[] = {
+static constexpr OptionDefinition g_breakpoint_write_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
- { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
+ { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
+ { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
// clang-format on
};
@@ -2453,8 +2501,10 @@ protected:
return false;
}
}
- Status error = target->SerializeBreakpointsToFile(
- FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append);
+ FileSpec file_spec(m_options.m_filename);
+ FileSystem::Instance().Resolve(file_spec);
+ Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
+ m_options.m_append);
if (!error.Success()) {
result.AppendErrorWithFormat("error serializing breakpoints: %s.",
error.AsCString());
diff --git a/source/Commands/CommandObjectBreakpoint.h b/source/Commands/CommandObjectBreakpoint.h
index 5e1026a6b7ea..d0026f90e30c 100644
--- a/source/Commands/CommandObjectBreakpoint.h
+++ b/source/Commands/CommandObjectBreakpoint.h
@@ -10,14 +10,10 @@
#ifndef liblldb_CommandObjectBreakpoint_h_
#define liblldb_CommandObjectBreakpoint_h_
-// C Includes
-// C++ Includes
#include <utility>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-private.h"
#include "lldb/Breakpoint/BreakpointName.h"
#include "lldb/Core/Address.h"
diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp
index f2546cbed848..991b174980e1 100644
--- a/source/Commands/CommandObjectBreakpointCommand.cpp
+++ b/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectBreakpointCommand.h"
#include "CommandObjectBreakpoint.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -18,13 +14,13 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/IOHandler.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
#include "llvm/ADT/STLExtras.h"
@@ -40,21 +36,24 @@ using namespace lldb_private;
// language to lldb and have it pickable here without having to change this
// enumeration by hand and rebuild lldb proper.
-static OptionEnumValueElement g_script_option_enumeration[4] = {
+static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
{eScriptLanguageNone, "command",
"Commands are in the lldb command interpreter language"},
{eScriptLanguagePython, "python", "Commands are in the Python language."},
{eSortOrderByName, "default-script",
- "Commands are in the default scripting language."},
- {0, nullptr, nullptr}};
+ "Commands are in the default scripting language."} };
-static OptionDefinition g_breakpoint_add_options[] = {
+static constexpr OptionEnumValues ScriptOptionEnum() {
+ return OptionEnumValues(g_script_option_enumeration);
+}
+
+static constexpr OptionDefinition g_breakpoint_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." },
- { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." },
- { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." },
- { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." },
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." },
+ { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." },
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
// clang-format on
};
@@ -475,9 +474,9 @@ const char *CommandObjectBreakpointCommandAdd::g_reader_instructions =
// CommandObjectBreakpointCommandDelete
//-------------------------------------------------------------------------
-static OptionDefinition g_breakpoint_delete_options[] = {
+static constexpr OptionDefinition g_breakpoint_delete_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
// clang-format on
};
diff --git a/source/Commands/CommandObjectBreakpointCommand.h b/source/Commands/CommandObjectBreakpointCommand.h
index 048cc5e07c1b..96d212138282 100644
--- a/source/Commands/CommandObjectBreakpointCommand.h
+++ b/source/Commands/CommandObjectBreakpointCommand.h
@@ -10,11 +10,7 @@
#ifndef liblldb_CommandObjectBreakpointCommand_h_
#define liblldb_CommandObjectBreakpointCommand_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
diff --git a/source/Commands/CommandObjectBugreport.cpp b/source/Commands/CommandObjectBugreport.cpp
index 7ba8ab945eae..dc4b9ef302c0 100644
--- a/source/Commands/CommandObjectBugreport.cpp
+++ b/source/Commands/CommandObjectBugreport.cpp
@@ -9,13 +9,9 @@
#include "CommandObjectBugreport.h"
-// C Includes
#include <cstdio>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupOutputFile.h"
@@ -72,8 +68,6 @@ protected:
const FileSpec &outfile_spec =
m_outfile_options.GetFile().GetCurrentValue();
if (outfile_spec) {
- char path[PATH_MAX];
- outfile_spec.GetPath(path, sizeof(path));
uint32_t open_options =
File::eOpenOptionWrite | File::eOpenOptionCanCreate |
@@ -84,10 +78,13 @@ protected:
open_options |= File::eOpenOptionTruncate;
StreamFileSP outfile_stream = std::make_shared<StreamFile>();
- Status error = outfile_stream->GetFile().Open(path, open_options);
+ File &file = outfile_stream->GetFile();
+ Status error =
+ FileSystem::Instance().Open(file, outfile_spec, open_options);
if (error.Fail()) {
+ auto path = outfile_spec.GetPath();
result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
- path, append ? "append" : "write",
+ path.c_str(), append ? "append" : "write",
error.AsCString());
result.SetStatus(eReturnStatusFailed);
return false;
diff --git a/source/Commands/CommandObjectBugreport.h b/source/Commands/CommandObjectBugreport.h
index 281ea2dd203e..1d9aea59925a 100644
--- a/source/Commands/CommandObjectBugreport.h
+++ b/source/Commands/CommandObjectBugreport.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectBugreport_h_
#define liblldb_CommandObjectBugreport_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp
index 333f72056cbc..01e1c4269bba 100644
--- a/source/Commands/CommandObjectCommands.cpp
+++ b/source/Commands/CommandObjectCommands.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "CommandObjectCommands.h"
#include "CommandObjectHelp.h"
#include "lldb/Core/Debugger.h"
@@ -38,12 +34,12 @@ using namespace lldb_private;
// CommandObjectCommandsSource
//-------------------------------------------------------------------------
-static OptionDefinition g_history_options[] = {
+static constexpr OptionDefinition g_history_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
- { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
- { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Clears the current command history." },
+ { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." },
+ { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." },
+ { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeBoolean, "Clears the current command history." },
// clang-format on
};
@@ -197,11 +193,11 @@ protected:
// CommandObjectCommandsSource
//-------------------------------------------------------------------------
-static OptionDefinition g_source_options[] = {
+static constexpr OptionDefinition g_source_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
- { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
- { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." },
+ { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." },
+ { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." },
// clang-format on
};
@@ -308,7 +304,8 @@ protected:
return false;
}
- FileSpec cmd_file(command[0].ref, true);
+ FileSpec cmd_file(command[0].ref);
+ FileSystem::Instance().Resolve(cmd_file);
ExecutionContext *exe_ctx = nullptr; // Just use the default context.
// If any options were set, then use them
@@ -319,8 +316,15 @@ protected:
CommandInterpreterRunOptions options;
options.SetStopOnContinue(m_options.m_stop_on_continue.GetCurrentValue());
options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue());
- options.SetEchoCommands(!m_options.m_silent_run.GetCurrentValue());
- options.SetPrintResults(!m_options.m_silent_run.GetCurrentValue());
+
+ // Individual silent setting is override for global command echo settings.
+ if (m_options.m_silent_run.GetCurrentValue()) {
+ options.SetSilent(true);
+ } else {
+ options.SetPrintResults(true);
+ options.SetEchoCommands(m_interpreter.GetEchoCommands());
+ options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands());
+ }
m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result);
} else {
@@ -340,10 +344,10 @@ protected:
// CommandObjectCommandsAlias
//-------------------------------------------------------------------------
-static OptionDefinition g_alias_options[] = {
+static constexpr OptionDefinition g_alias_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Help text for this command" },
- { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "Long help text for this command" },
+ { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" },
+ { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" },
// clang-format on
};
@@ -914,10 +918,10 @@ protected:
// CommandObjectCommandsAddRegex
//-------------------------------------------------------------------------
-static OptionDefinition g_regex_options[] = {
+static constexpr OptionDefinition g_regex_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "The help text to display for this command." },
- { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
+ { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." },
+ { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." },
// clang-format on
};
@@ -1394,9 +1398,9 @@ private:
// CommandObjectCommandsScriptImport
//-------------------------------------------------------------------------
-OptionDefinition g_script_import_options[] = {
+static constexpr OptionDefinition g_script_import_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, nullptr, 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, nullptr, {}, 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." },
// clang-format on
};
@@ -1519,22 +1523,24 @@ protected:
//-------------------------------------------------------------------------
// CommandObjectCommandsScriptAdd
//-------------------------------------------------------------------------
+static constexpr OptionEnumValueElement g_script_synchro_type[] = {
+ {eScriptedCommandSynchronicitySynchronous, "synchronous",
+ "Run synchronous"},
+ {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
+ "Run asynchronous"},
+ {eScriptedCommandSynchronicityCurrentValue, "current",
+ "Do not alter current setting"} };
+
+static constexpr OptionEnumValues ScriptSynchroType() {
+ return OptionEnumValues(g_script_synchro_type);
+}
-static OptionEnumValueElement g_script_synchro_type[] = {
- {eScriptedCommandSynchronicitySynchronous, "synchronous",
- "Run synchronous"},
- {eScriptedCommandSynchronicityAsynchronous, "asynchronous",
- "Run asynchronous"},
- {eScriptedCommandSynchronicityCurrentValue, "current",
- "Do not alter current setting"},
- {0, nullptr, nullptr}};
-
-static OptionDefinition g_script_add_options[] = {
+static constexpr OptionDefinition g_script_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
- { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
- { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeHelpText, "The help text to display for this command." },
- { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, 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, nullptr, {}, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." },
+ { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." },
+ { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "The help text to display for this command." },
+ { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, ScriptSynchroType(), 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." },
// clang-format on
};
diff --git a/source/Commands/CommandObjectCommands.h b/source/Commands/CommandObjectCommands.h
index a5ef777aa982..57ae8f27efec 100644
--- a/source/Commands/CommandObjectCommands.h
+++ b/source/Commands/CommandObjectCommands.h
@@ -11,10 +11,6 @@
#ifndef liblldb_CommandObjectCommands_h_
#define liblldb_CommandObjectCommands_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/STLUtils.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp
index 519e5e2dcdb0..f8ee46121851 100644
--- a/source/Commands/CommandObjectDisassemble.cpp
+++ b/source/Commands/CommandObjectDisassemble.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectDisassemble.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Disassembler.h"
@@ -35,30 +31,30 @@
using namespace lldb;
using namespace lldb_private;
-static OptionDefinition g_disassemble_options[] = {
+static constexpr OptionDefinition g_disassemble_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show opcode bytes when disassembling." },
- { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of context lines of source to show." },
- { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable mixed source and assembly display." },
- { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print raw disassembly with no symbol information." },
- { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." },
- { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
+ { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show opcode bytes when disassembling." },
+ { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of context lines of source to show." },
+ { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable mixed source and assembly display." },
+ { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print raw disassembly with no symbol information." },
+ { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." },
+ { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. "
"Currently the only valid options are default, and for Intel "
"architectures, att and intel." },
- { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." },
+ { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." },
{ LLDB_OPT_SET_1 |
- LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." },
- { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." },
+ LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." },
+ { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." },
{ LLDB_OPT_SET_2 |
LLDB_OPT_SET_3 |
LLDB_OPT_SET_4 |
- LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumLines, "Number of instructions to display." },
- { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." },
- { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." },
- { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble around the current pc." },
- { LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line "
+ LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of instructions to display." },
+ { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." },
+ { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." },
+ { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble around the current pc." },
+ { LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, {}, 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, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." },
+ { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." },
// clang-format on
};
diff --git a/source/Commands/CommandObjectDisassemble.h b/source/Commands/CommandObjectDisassemble.h
index af15d45eb76b..04c4cc247ee9 100644
--- a/source/Commands/CommandObjectDisassemble.h
+++ b/source/Commands/CommandObjectDisassemble.h
@@ -65,7 +65,6 @@ public:
// "at_pc". This should be set
// in SetOptionValue if anything the selects a location is set.
lldb::addr_t symbol_containing_addr;
- static OptionDefinition g_option_table[];
};
CommandObjectDisassemble(CommandInterpreter &interpreter);
diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp
index 08959ff8473d..e87d68a53da4 100644
--- a/source/Commands/CommandObjectExpression.cpp
+++ b/source/Commands/CommandObjectExpression.cpp
@@ -7,13 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "CommandObjectExpression.h"
#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "lldb/Core/Debugger.h"
@@ -43,29 +39,32 @@ CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {}
CommandObjectExpression::CommandOptions::~CommandOptions() = default;
-static OptionEnumValueElement g_description_verbosity_type[] = {
+static constexpr 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, nullptr, nullptr}};
+ "Show the full output, including persistent variable's name and type"} };
-static OptionDefinition g_expression_options[] = {
+static constexpr OptionEnumValues DescriptionVerbosityTypes() {
+ return OptionEnumValues(g_description_verbosity_type);
+}
+
+static constexpr OptionDefinition g_expression_options[] = {
// clang-format off
- {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
- {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. "
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 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, nullptr, nullptr, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction "
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, {}, 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 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language "
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language "
"setting is used." },
- {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." },
- {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
- {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local "
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." },
+ {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local "
"context. Allows declaration of persistent, top-level entities without a $ prefix."},
- {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by "
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by "
"the interpreter (defaults to true)."}
// clang-format on
};
@@ -307,6 +306,72 @@ CommandObjectExpression::~CommandObjectExpression() = default;
Options *CommandObjectExpression::GetOptions() { return &m_option_group; }
+int CommandObjectExpression::HandleCompletion(CompletionRequest &request) {
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(m_varobj_options.use_objc);
+ options.SetLanguage(m_command_options.language);
+ options.SetExecutionPolicy(lldb_private::eExecutionPolicyNever);
+ options.SetAutoApplyFixIts(false);
+ options.SetGenerateDebugInfo(false);
+
+ // We need a valid execution context with a frame pointer for this
+ // completion, so if we don't have one we should try to make a valid
+ // execution context.
+ if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
+ m_interpreter.UpdateExecutionContext(nullptr);
+
+ // This didn't work, so let's get out before we start doing things that
+ // expect a valid frame pointer.
+ if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr)
+ return 0;
+
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
+
+ Target *target = exe_ctx.GetTargetPtr();
+
+ if (!target)
+ target = GetDummyTarget();
+
+ if (!target)
+ return 0;
+
+ unsigned cursor_pos = request.GetRawCursorPos();
+ llvm::StringRef code = request.GetRawLine();
+
+ const std::size_t original_code_size = code.size();
+
+ // Remove the first token which is 'expr' or some alias/abbreviation of that.
+ code = llvm::getToken(code).second.ltrim();
+ OptionsWithRaw args(code);
+ code = args.GetRawPart();
+
+ // The position where the expression starts in the command line.
+ assert(original_code_size >= code.size());
+ std::size_t raw_start = original_code_size - code.size();
+
+ // Check if the cursor is actually in the expression string, and if not, we
+ // exit.
+ // FIXME: We should complete the options here.
+ if (cursor_pos < raw_start)
+ return 0;
+
+ // Make the cursor_pos again relative to the start of the code string.
+ assert(cursor_pos >= raw_start);
+ cursor_pos -= raw_start;
+
+ auto language = exe_ctx.GetFrameRef().GetLanguage();
+
+ Status error;
+ lldb::UserExpressionSP expr(target->GetUserExpressionForLanguage(
+ code, llvm::StringRef(), language, UserExpression::eResultTypeAny,
+ options, error));
+ if (error.Fail())
+ return 0;
+
+ expr->Complete(exe_ctx, request, cursor_pos);
+ return request.GetNumberOfMatches();
+}
+
static lldb_private::Status
CanBeUsedForElementCountPrinting(ValueObject &valobj) {
CompilerType type(valobj.GetCompilerType());
@@ -355,8 +420,7 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr,
if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)
auto_apply_fixits = target->GetEnableAutoApplyFixIts();
else
- auto_apply_fixits =
- m_command_options.auto_apply_fixits == eLazyBoolYes ? true : false;
+ auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes;
options.SetAutoApplyFixIts(auto_apply_fixits);
diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h
index 710f87140977..2eeca0da0578 100644
--- a/source/Commands/CommandObjectExpression.h
+++ b/source/Commands/CommandObjectExpression.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectExpression_h_
#define liblldb_CommandObjectExpression_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/IOHandler.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
@@ -39,9 +35,6 @@ public:
void OptionParsingStarting(ExecutionContext *execution_context) override;
- // Options table: Required for subclasses of Options.
-
- static OptionDefinition g_option_table[];
bool top_level;
bool unwind_on_error;
bool ignore_breakpoints;
@@ -62,6 +55,8 @@ public:
Options *GetOptions() override;
+ int HandleCompletion(CompletionRequest &request) override;
+
protected:
//------------------------------------------------------------------
// IOHandler::Delegate functions
diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp
index 64de14f2edbf..f8318a38e28d 100644
--- a/source/Commands/CommandObjectFrame.cpp
+++ b/source/Commands/CommandObjectFrame.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectFrame.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -24,6 +20,7 @@
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
+#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionGroupFormat.h"
@@ -40,6 +37,7 @@
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -61,11 +59,11 @@ using namespace lldb_private;
// CommandObjectFrameDiagnose
//-------------------------------------------------------------------------
-static OptionDefinition g_frame_diag_options[] = {
+static constexpr OptionDefinition g_frame_diag_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegisterName, "A register to diagnose." },
- { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "An address to diagnose." },
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "An optional offset. Requires --register." }
+ { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegisterName, "A register to diagnose." },
+ { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "An address to diagnose." },
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "An optional offset. Requires --register." }
// clang-format on
};
@@ -251,7 +249,7 @@ protected:
static OptionDefinition g_frame_select_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." },
+ { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." },
// clang-format on
};
@@ -427,7 +425,17 @@ public:
"arguments and local variables in scope. Names of argument, "
"local, file static and file global variables can be specified. "
"Children of aggregate variables can be specified such as "
- "'var->child.x'.",
+ "'var->child.x'. The -> and [] operators in 'frame variable' do "
+ "not invoke operator overloads if they exist, but directly access "
+ "the specified element. If you want to trigger operator overloads "
+ "use the expression command to print the variable instead."
+ "\nIt is worth noting that except for overloaded "
+ "operators, when printing local variables 'expr local_var' and "
+ "'frame var local_var' produce the same "
+ "results. However, 'frame variable' is more efficient, since it "
+ "uses debug information and memory reads directly, rather than "
+ "parsing and evaluating an expression, which may even involve "
+ "JITing and running code in the target program.",
nullptr, eCommandRequiresFrame | eCommandTryTargetAPILock |
eCommandProcessMustBeLaunched |
eCommandProcessMustBePaused | eCommandRequiresProcess),
@@ -705,6 +713,23 @@ protected:
result.SetStatus(eReturnStatusSuccessFinishResult);
}
+ if (m_option_variable.show_recognized_args) {
+ auto recognized_frame = frame->GetRecognizedFrame();
+ if (recognized_frame) {
+ ValueObjectListSP recognized_arg_list =
+ recognized_frame->GetRecognizedArguments();
+ if (recognized_arg_list) {
+ for (auto &rec_value_sp : recognized_arg_list->GetObjects()) {
+ options.SetFormat(m_option_format.GetFormat());
+ options.SetVariableFormatDisplayLanguage(
+ rec_value_sp->GetPreferredDisplayLanguage());
+ options.SetRootValueObjectName(rec_value_sp->GetName().AsCString());
+ rec_value_sp->Dump(result.GetOutputStream(), options);
+ }
+ }
+ }
+ }
+
if (m_interpreter.TruncationWarningNecessary()) {
result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
m_cmd_name.c_str());
@@ -728,6 +753,370 @@ protected:
OptionGroupValueObjectDisplay m_varobj_options;
};
+#pragma mark CommandObjectFrameRecognizer
+
+static OptionDefinition g_frame_recognizer_add_options[] = {
+ // clang-format off
+ { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Name of the module or shared library that this recognizer applies to." },
+ { LLDB_OPT_SET_ALL, false, "function", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeName, "Name of the function that this recognizer applies to." },
+ { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Give the name of a Python class to use for this frame recognizer." },
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Function name and module name are actually regular expressions." }
+ // clang-format on
+};
+
+class CommandObjectFrameRecognizerAdd : public CommandObjectParsed {
+private:
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'l':
+ m_class_name = std::string(option_arg);
+ break;
+ case 's':
+ m_module = std::string(option_arg);
+ break;
+ case 'n':
+ m_function = std::string(option_arg);
+ break;
+ case 'x':
+ m_regex = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_module = "";
+ m_function = "";
+ m_class_name = "";
+ m_regex = false;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_frame_recognizer_add_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ std::string m_class_name;
+ std::string m_module;
+ std::string m_function;
+ bool m_regex;
+ };
+
+ CommandOptions m_options;
+
+ Options *GetOptions() override { return &m_options; }
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override;
+
+public:
+ CommandObjectFrameRecognizerAdd(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "frame recognizer add",
+ "Add a new frame recognizer.", nullptr),
+ m_options() {
+ SetHelpLong(R"(
+Frame recognizers allow for retrieving information about special frames based on
+ABI, arguments or other special properties of that frame, even without source
+code or debug info. Currently, one use case is to extract function arguments
+that would otherwise be unaccesible, or augment existing arguments.
+
+Adding a custom frame recognizer is possible by implementing a Python class
+and using the 'frame recognizer add' command. The Python class should have a
+'get_recognized_arguments' method and it will receive an argument of type
+lldb.SBFrame representing the current frame that we are trying to recognize.
+The method should return a (possibly empty) list of lldb.SBValue objects that
+represent the recognized arguments.
+
+An example of a recognizer that retrieves the file descriptor values from libc
+functions 'read', 'write' and 'close' follows:
+
+ class LibcFdRecognizer(object):
+ def get_recognized_arguments(self, frame):
+ if frame.name in ["read", "write", "close"]:
+ fd = frame.EvaluateExpression("$arg1").unsigned
+ value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd)
+ return [value]
+ return []
+
+The file containing this implementation can be imported via 'command script
+import' and then we can register this recognizer with 'frame recognizer add'.
+It's important to restrict the recognizer to the libc library (which is
+libsystem_kernel.dylib on macOS) to avoid matching functions with the same name
+in other modules:
+
+(lldb) command script import .../fd_recognizer.py
+(lldb) frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib
+
+When the program is stopped at the beginning of the 'read' function in libc, we
+can view the recognizer arguments in 'frame variable':
+
+(lldb) b read
+(lldb) r
+Process 1234 stopped
+* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
+ frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
+(lldb) frame variable
+(int) fd = 3
+
+ )");
+ }
+ ~CommandObjectFrameRecognizerAdd() override = default;
+};
+
+bool CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
+ CommandReturnObject &result) {
+#ifndef LLDB_DISABLE_PYTHON
+ if (m_options.m_class_name.empty()) {
+ result.AppendErrorWithFormat(
+ "%s needs a Python class name (-l argument).\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_options.m_module.empty()) {
+ result.AppendErrorWithFormat("%s needs a module name (-s argument).\n",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_options.m_function.empty()) {
+ result.AppendErrorWithFormat("%s needs a function name (-n argument).\n",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ScriptInterpreter *interpreter = m_interpreter.GetScriptInterpreter();
+
+ if (interpreter &&
+ !interpreter->CheckObjectExists(m_options.m_class_name.c_str())) {
+ result.AppendWarning(
+ "The provided class does not exist - please define it "
+ "before attempting to use this frame recognizer");
+ }
+
+ StackFrameRecognizerSP recognizer_sp =
+ StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
+ interpreter, m_options.m_class_name.c_str()));
+ if (m_options.m_regex) {
+ auto module =
+ RegularExpressionSP(new RegularExpression(m_options.m_module));
+ auto func =
+ RegularExpressionSP(new RegularExpression(m_options.m_function));
+ StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
+ } else {
+ auto module = ConstString(m_options.m_module);
+ auto func = ConstString(m_options.m_function);
+ StackFrameRecognizerManager::AddRecognizer(recognizer_sp, module, func);
+ }
+#endif
+
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+}
+
+class CommandObjectFrameRecognizerClear : public CommandObjectParsed {
+public:
+ CommandObjectFrameRecognizerClear(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "frame recognizer clear",
+ "Delete all frame recognizers.", nullptr) {}
+
+ ~CommandObjectFrameRecognizerClear() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ StackFrameRecognizerManager::RemoveAllRecognizers();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectFrameRecognizerDelete : public CommandObjectParsed {
+ public:
+ CommandObjectFrameRecognizerDelete(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "frame recognizer delete",
+ "Delete an existing frame recognizer.", nullptr) {}
+
+ ~CommandObjectFrameRecognizerDelete() override = default;
+
+ protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (command.GetArgumentCount() == 0) {
+ if (!m_interpreter.Confirm(
+ "About to delete all frame recognizers, do you want to do that?",
+ true)) {
+ result.AppendMessage("Operation cancelled...");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ StackFrameRecognizerManager::RemoveAllRecognizers();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+
+ if (command.GetArgumentCount() != 1) {
+ result.AppendErrorWithFormat("'%s' takes zero or one arguments.\n",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ uint32_t recognizer_id =
+ StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
+
+ StackFrameRecognizerManager::RemoveRecognizerWithID(recognizer_id);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectFrameRecognizerList : public CommandObjectParsed {
+ public:
+ CommandObjectFrameRecognizerList(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "frame recognizer list",
+ "Show a list of active frame recognizers.",
+ nullptr) {}
+
+ ~CommandObjectFrameRecognizerList() override = default;
+
+ protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ bool any_printed = false;
+ StackFrameRecognizerManager::ForEach(
+ [&result, &any_printed](uint32_t recognizer_id, std::string name,
+ std::string function, std::string symbol,
+ bool regexp) {
+ if (name == "") name = "(internal)";
+ result.GetOutputStream().Printf(
+ "%d: %s, module %s, function %s%s\n", recognizer_id, name.c_str(),
+ function.c_str(), symbol.c_str(), regexp ? " (regexp)" : "");
+ any_printed = true;
+ });
+
+ if (any_printed)
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ else {
+ result.GetOutputStream().PutCString("no matching results found.\n");
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectFrameRecognizerInfo : public CommandObjectParsed {
+ public:
+ CommandObjectFrameRecognizerInfo(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "frame recognizer info",
+ "Show which frame recognizer is applied a stack frame (if any).",
+ nullptr) {
+ CommandArgumentEntry arg;
+ CommandArgumentData index_arg;
+
+ // Define the first (and only) variant of this arg.
+ index_arg.arg_type = eArgTypeFrameIndex;
+ index_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg.push_back(index_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg);
+ }
+
+ ~CommandObjectFrameRecognizerInfo() override = default;
+
+ protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Process *process = m_exe_ctx.GetProcessPtr();
+ if (process == nullptr) {
+ result.AppendError("no process");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ Thread *thread = m_exe_ctx.GetThreadPtr();
+ if (thread == nullptr) {
+ result.AppendError("no thread");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ if (command.GetArgumentCount() != 1) {
+ result.AppendErrorWithFormat(
+ "'%s' takes exactly one frame index argument.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ uint32_t frame_index =
+ StringConvert::ToUInt32(command.GetArgumentAtIndex(0), 0, 0);
+ StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_index);
+ if (!frame_sp) {
+ result.AppendErrorWithFormat("no frame with index %u", frame_index);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ auto recognizer =
+ StackFrameRecognizerManager::GetRecognizerForFrame(frame_sp);
+
+ Stream &output_stream = result.GetOutputStream();
+ output_stream.Printf("frame %d ", frame_index);
+ if (recognizer) {
+ output_stream << "is recognized by ";
+ output_stream << recognizer->GetName();
+ } else {
+ output_stream << "not recognized by any recognizer";
+ }
+ output_stream.EOL();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectFrameRecognizer : public CommandObjectMultiword {
+ public:
+ CommandObjectFrameRecognizer(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "frame recognizer",
+ "Commands for editing and viewing frame recognizers.",
+ "frame recognizer [<sub-command-options>] ") {
+ LoadSubCommand(
+ "add",
+ CommandObjectSP(new CommandObjectFrameRecognizerAdd(interpreter)));
+ LoadSubCommand(
+ "clear",
+ CommandObjectSP(new CommandObjectFrameRecognizerClear(interpreter)));
+ LoadSubCommand(
+ "delete",
+ CommandObjectSP(new CommandObjectFrameRecognizerDelete(interpreter)));
+ LoadSubCommand(
+ "list",
+ CommandObjectSP(new CommandObjectFrameRecognizerList(interpreter)));
+ LoadSubCommand(
+ "info",
+ CommandObjectSP(new CommandObjectFrameRecognizerInfo(interpreter)));
+ }
+
+ ~CommandObjectFrameRecognizer() override = default;
+};
+
#pragma mark CommandObjectMultiwordFrame
//-------------------------------------------------------------------------
@@ -748,6 +1137,11 @@ CommandObjectMultiwordFrame::CommandObjectMultiwordFrame(
CommandObjectSP(new CommandObjectFrameSelect(interpreter)));
LoadSubCommand("variable",
CommandObjectSP(new CommandObjectFrameVariable(interpreter)));
+#ifndef LLDB_DISABLE_PYTHON
+ LoadSubCommand(
+ "recognizer",
+ CommandObjectSP(new CommandObjectFrameRecognizer(interpreter)));
+#endif
}
CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame() = default;
diff --git a/source/Commands/CommandObjectGUI.cpp b/source/Commands/CommandObjectGUI.cpp
index d65e12e30982..ed834dcbe4fb 100644
--- a/source/Commands/CommandObjectGUI.cpp
+++ b/source/Commands/CommandObjectGUI.cpp
@@ -9,10 +9,6 @@
#include "CommandObjectGUI.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/lldb-private.h"
diff --git a/source/Commands/CommandObjectGUI.h b/source/Commands/CommandObjectGUI.h
index c71558fa1758..b20c3a7191ab 100644
--- a/source/Commands/CommandObjectGUI.h
+++ b/source/Commands/CommandObjectGUI.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectGUI_h_
#define liblldb_CommandObjectGUI_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp
index 903c6011b03f..1f1d63d72903 100644
--- a/source/Commands/CommandObjectHelp.cpp
+++ b/source/Commands/CommandObjectHelp.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectHelp.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
@@ -71,11 +67,11 @@ CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter)
CommandObjectHelp::~CommandObjectHelp() = default;
-static OptionDefinition g_help_options[] = {
+static constexpr OptionDefinition g_help_options[] = {
// clang-format off
- {LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide aliases in the command list."},
- {LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Hide user-defined commands from the list."},
- {LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
+ {LLDB_OPT_SET_ALL, false, "hide-aliases", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Hide aliases in the command list."},
+ {LLDB_OPT_SET_ALL, false, "hide-user-commands", 'u', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Hide user-defined commands from the list."},
+ {LLDB_OPT_SET_ALL, false, "show-hidden-commands", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include commands prefixed with an underscore."},
// clang-format on
};
@@ -171,10 +167,13 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) {
}
sub_cmd_obj->GenerateHelpText(result);
-
- if (m_interpreter.AliasExists(command_name)) {
+ std::string alias_full_name;
+ // Don't use AliasExists here, that only checks exact name matches. If
+ // the user typed a shorter unique alias name, we should still tell them
+ // it was an alias.
+ if (m_interpreter.GetAliasFullName(command_name, alias_full_name)) {
StreamString sstr;
- m_interpreter.GetAlias(command_name)->GetAliasExpansion(sstr);
+ m_interpreter.GetAlias(alias_full_name)->GetAliasExpansion(sstr);
result.GetOutputStream().Printf("\n'%s' is an abbreviation for %s\n",
command[0].c_str(), sstr.GetData());
}
diff --git a/source/Commands/CommandObjectHelp.h b/source/Commands/CommandObjectHelp.h
index c78682dead1f..5d5b672a5fbd 100644
--- a/source/Commands/CommandObjectHelp.h
+++ b/source/Commands/CommandObjectHelp.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectHelp_h_
#define liblldb_CommandObjectHelp_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/Options.h"
diff --git a/source/Commands/CommandObjectLanguage.h b/source/Commands/CommandObjectLanguage.h
index b796c511b513..ef8e11863e7e 100644
--- a/source/Commands/CommandObjectLanguage.h
+++ b/source/Commands/CommandObjectLanguage.h
@@ -10,11 +10,7 @@
#ifndef liblldb_CommandObjectLanguage_h_
#define liblldb_CommandObjectLanguage_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/lldb-types.h"
diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp
index 1389ff2bde02..b019336bdc92 100644
--- a/source/Commands/CommandObjectLog.cpp
+++ b/source/Commands/CommandObjectLog.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectLog.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -36,18 +32,18 @@
using namespace lldb;
using namespace lldb_private;
-static OptionDefinition g_log_options[] = {
+static constexpr OptionDefinition g_log_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Set the destination file to log to." },
- { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." },
- { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose logging." },
- { LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." },
- { LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend all log lines with a timestamp." },
- { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, nullptr, nullptr, 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, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
- { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to the log file instead of overwriting." },
- { LLDB_OPT_SET_1, false, "file-function",'F',OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Prepend the names of files and function that generate the logs." },
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Set the destination file to log to." },
+ { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." },
+ { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose logging." },
+ { LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." },
+ { LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with a timestamp." },
+ { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, nullptr, {}, 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, nullptr, {}, 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, nullptr, {}, 0, eArgTypeNone, "Append a stack backtrace to each log line." },
+ { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to the log file instead of overwriting." },
+ { LLDB_OPT_SET_1, false, "file-function",'F',OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend the names of files and function that generate the logs." },
// clang-format on
};
@@ -101,7 +97,8 @@ public:
switch (short_option) {
case 'f':
- log_file.SetFile(option_arg, true, FileSpec::Style::native);
+ log_file.SetFile(option_arg, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(log_file);
break;
case 't':
log_options |= LLDB_LOG_OPTION_THREADSAFE;
diff --git a/source/Commands/CommandObjectLog.h b/source/Commands/CommandObjectLog.h
index 1e24a4b2ac67..f02a7be514ac 100644
--- a/source/Commands/CommandObjectLog.h
+++ b/source/Commands/CommandObjectLog.h
@@ -10,13 +10,9 @@
#ifndef liblldb_CommandObjectLog_h_
#define liblldb_CommandObjectLog_h_
-// C Includes
-// C++ Includes
#include <map>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp
index e4a49e55857d..b1edb1afa5d2 100644
--- a/source/Commands/CommandObjectMemory.cpp
+++ b/source/Commands/CommandObjectMemory.cpp
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <inttypes.h>
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/Decl.h"
-// Project includes
#include "CommandObjectMemory.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/Debugger.h"
@@ -50,16 +46,16 @@
using namespace lldb;
using namespace lldb_private;
-static OptionDefinition g_read_memory_options[] = {
+static constexpr OptionDefinition g_read_memory_options[] = {
// clang-format off
- {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNumberPerLine, "The number of items per line to display." },
- {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that "
+ {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumberPerLine, "The number of items per line to display." },
+ {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, {}, 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, nullptr, nullptr, 0, eArgTypeNone, "The name of a type to view memory as." },
- {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." },
+ {LLDB_OPT_SET_3, true , "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The name of a type to view memory as." },
+ {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." },
{LLDB_OPT_SET_1 |
LLDB_OPT_SET_2 |
- LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." },
+ LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." },
// clang-format on
};
@@ -386,7 +382,6 @@ protected:
if (view_as_type_cstr && view_as_type_cstr[0]) {
// We are viewing memory as a type
- SymbolContext sc;
const bool exact_match = false;
TypeList type_list;
uint32_t reference_count = 0;
@@ -471,17 +466,13 @@ protected:
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
ConstString lookup_type_name(type_str.c_str());
StackFrame *frame = m_exe_ctx.GetFramePtr();
+ ModuleSP search_first;
if (frame) {
- sc = frame->GetSymbolContext(eSymbolContextModule);
- if (sc.module_sp) {
- sc.module_sp->FindTypes(sc, lookup_type_name, exact_match, 1,
- searched_symbol_files, type_list);
- }
- }
- if (type_list.GetSize() == 0) {
- target->GetImages().FindTypes(sc, lookup_type_name, exact_match, 1,
- searched_symbol_files, type_list);
+ search_first = frame->GetSymbolContext(eSymbolContextModule).module_sp;
}
+ target->GetImages().FindTypes(search_first.get(), lookup_type_name,
+ exact_match, 1, searched_symbol_files,
+ type_list);
if (type_list.GetSize() == 0 && lookup_type_name.GetCString() &&
*lookup_type_name.GetCString() == '$') {
@@ -528,15 +519,15 @@ protected:
--pointer_count;
}
- m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
-
- if (m_format_options.GetByteSizeValue() == 0) {
+ llvm::Optional<uint64_t> size = clang_ast_type.GetByteSize(nullptr);
+ if (!size) {
result.AppendErrorWithFormat(
"unable to get the byte size of the type '%s'\n",
view_as_type_cstr);
result.SetStatus(eReturnStatusFailed);
return false;
}
+ m_format_options.GetByteSizeValue() = *size;
if (!m_format_options.GetCountValue().OptionWasSet())
m_format_options.GetCountValue() = 1;
@@ -651,12 +642,15 @@ protected:
if (!m_format_options.GetFormatValue().OptionWasSet())
m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
- bytes_read = clang_ast_type.GetByteSize(nullptr) *
- m_format_options.GetCountValue().GetCurrentValue();
+ llvm::Optional<uint64_t> size = clang_ast_type.GetByteSize(nullptr);
+ if (!size) {
+ result.AppendError("can't get size of type");
+ return false;
+ }
+ bytes_read = *size * m_format_options.GetCountValue().GetCurrentValue();
if (argc > 0)
- addr = addr + (clang_ast_type.GetByteSize(nullptr) *
- m_memory_options.m_offset.GetCurrentValue());
+ addr = addr + (*size * m_memory_options.m_offset.GetCurrentValue());
} else if (m_format_options.GetFormatValue().GetCurrentValue() !=
eFormatCString) {
data_sp.reset(new DataBufferHeap(total_byte_size, '\0'));
@@ -762,9 +756,9 @@ protected:
Stream *output_stream = nullptr;
const FileSpec &outfile_spec =
m_outfile_options.GetFile().GetCurrentValue();
+
+ std::string path = outfile_spec.GetPath();
if (outfile_spec) {
- char path[PATH_MAX];
- outfile_spec.GetPath(path, sizeof(path));
uint32_t open_options =
File::eOpenOptionWrite | File::eOpenOptionCanCreate;
@@ -772,19 +766,21 @@ protected:
if (append)
open_options |= File::eOpenOptionAppend;
- if (outfile_stream.GetFile().Open(path, open_options).Success()) {
+ Status error = FileSystem::Instance().Open(outfile_stream.GetFile(),
+ outfile_spec, open_options);
+ if (error.Success()) {
if (m_memory_options.m_output_as_binary) {
const size_t bytes_written =
outfile_stream.Write(data_sp->GetBytes(), bytes_read);
if (bytes_written > 0) {
result.GetOutputStream().Printf(
"%zi bytes %s to '%s'\n", bytes_written,
- append ? "appended" : "written", path);
+ append ? "appended" : "written", path.c_str());
return true;
} else {
result.AppendErrorWithFormat("Failed to write %" PRIu64
" bytes to '%s'.\n",
- (uint64_t)bytes_read, path);
+ (uint64_t)bytes_read, path.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -794,8 +790,8 @@ protected:
output_stream = &outfile_stream;
}
} else {
- result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path,
- append ? "append" : "write");
+ result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n",
+ path.c_str(), append ? "append" : "write");
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -884,12 +880,12 @@ protected:
CompilerType m_prev_clang_ast_type;
};
-OptionDefinition g_memory_find_option_table[] = {
+static constexpr OptionDefinition g_memory_find_option_table[] = {
// clang-format off
- {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
- {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Use text to find a byte pattern."},
- {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many times to perform the search."},
- {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
+ {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
+ {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Use text to find a byte pattern."},
+ {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many times to perform the search."},
+ {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
// clang-format on
};
@@ -1068,7 +1064,11 @@ protected:
m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
result_sp) {
uint64_t value = result_sp->GetValueAsUnsigned(0);
- switch (result_sp->GetCompilerType().GetByteSize(nullptr)) {
+ llvm::Optional<uint64_t> size =
+ result_sp->GetCompilerType().GetByteSize(nullptr);
+ if (!size)
+ return false;
+ switch (*size) {
case 1: {
uint8_t byte = (uint8_t)value;
buffer.CopyData(&byte, 1);
@@ -1179,10 +1179,10 @@ protected:
OptionGroupFindMemory m_memory_options;
};
-OptionDefinition g_memory_write_option_table[] = {
+static constexpr OptionDefinition g_memory_write_option_table[] = {
// clang-format off
- {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFilename, "Write memory using the contents of a file."},
- {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."},
+ {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Write memory using the contents of a file."},
+ {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."},
// clang-format on
};
@@ -1209,8 +1209,9 @@ public:
switch (short_option) {
case 'i':
- m_infile.SetFile(option_value, true, FileSpec::Style::native);
- if (!m_infile.Exists()) {
+ m_infile.SetFile(option_value, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(m_infile);
+ if (!FileSystem::Instance().Exists(m_infile)) {
m_infile.Clear();
error.SetErrorStringWithFormat("input file does not exist: '%s'",
option_value.str().c_str());
@@ -1358,7 +1359,7 @@ protected:
size_t length = SIZE_MAX;
if (item_byte_size > 1)
length = item_byte_size;
- auto data_sp = DataBufferLLVM::CreateSliceFromPath(
+ auto data_sp = FileSystem::Instance().CreateDataBuffer(
m_memory_options.m_infile.GetPath(), length,
m_memory_options.m_infile_offset);
if (data_sp) {
@@ -1724,6 +1725,7 @@ protected:
error = process_sp->GetMemoryRegionInfo(load_addr, range_info);
if (error.Success()) {
lldb_private::Address addr;
+ ConstString name = range_info.GetName();
ConstString section_name;
if (process_sp->GetTarget().ResolveLoadAddress(load_addr, addr)) {
SectionSP section_sp(addr.GetSection());
@@ -1735,13 +1737,14 @@ protected:
}
}
result.AppendMessageWithFormat(
- "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s\n",
+ "[0x%16.16" PRIx64 "-0x%16.16" PRIx64 ") %c%c%c%s%s%s%s\n",
range_info.GetRange().GetRangeBase(),
range_info.GetRange().GetRangeEnd(),
range_info.GetReadable() ? 'r' : '-',
range_info.GetWritable() ? 'w' : '-',
- range_info.GetExecutable() ? 'x' : '-', section_name ? " " : "",
- section_name ? section_name.AsCString() : "");
+ range_info.GetExecutable() ? 'x' : '-',
+ name ? " " : "", name.AsCString(""),
+ section_name ? " " : "", section_name.AsCString(""));
m_prev_end_addr = range_info.GetRange().GetRangeEnd();
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
diff --git a/source/Commands/CommandObjectMemory.h b/source/Commands/CommandObjectMemory.h
index 9f3978baf76a..0fa5251e82ff 100644
--- a/source/Commands/CommandObjectMemory.h
+++ b/source/Commands/CommandObjectMemory.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectMemory_h_
#define liblldb_CommandObjectMemory_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectMultiword.cpp b/source/Commands/CommandObjectMultiword.cpp
index 19fcf60e557c..64c4f6686e6b 100644
--- a/source/Commands/CommandObjectMultiword.cpp
+++ b/source/Commands/CommandObjectMultiword.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -193,9 +189,10 @@ int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
auto arg0 = request.GetParsedLine()[0].ref;
if (request.GetCursorIndex() == 0) {
- StringList new_matches;
- AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches);
- request.AddCompletions(new_matches);
+ StringList new_matches, descriptions;
+ AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches,
+ &descriptions);
+ request.AddCompletions(new_matches, descriptions);
if (new_matches.GetSize() == 1 &&
new_matches.GetStringAtIndex(0) != nullptr &&
diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp
index 22a9a169c7c8..fc442f5f4d5d 100644
--- a/source/Commands/CommandObjectPlatform.cpp
+++ b/source/Commands/CommandObjectPlatform.cpp
@@ -7,11 +7,7 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectPlatform.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -63,19 +59,19 @@ static mode_t ParsePermissionString(llvm::StringRef permissions) {
return user | group | world;
}
-static OptionDefinition g_permissions_options[] = {
+static constexpr OptionDefinition g_permissions_options[] = {
// clang-format off
- {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"},
- {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."},
- {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to read."},
- {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to write."},
- {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to execute."},
- {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to read."},
- {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to write."},
- {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to execute."},
- {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to read."},
- {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to write."},
- {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to execute."},
+ {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"},
+ {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."},
+ {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to read."},
+ {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to write."},
+ {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to execute."},
+ {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to read."},
+ {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to write."},
+ {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to execute."},
+ {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to read."},
+ {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to write."},
+ {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to execute."},
// clang-format on
};
@@ -491,8 +487,7 @@ public:
else
mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
lldb::eFilePermissionsWorldRX;
- Status error =
- platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode);
+ Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
if (error.Success()) {
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
@@ -545,7 +540,7 @@ public:
perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
lldb::eFilePermissionsWorldRead;
lldb::user_id_t fd = platform_sp->OpenFile(
- FileSpec(cmd_line, false),
+ FileSpec(cmd_line),
File::eOpenOptionRead | File::eOpenOptionWrite |
File::eOpenOptionAppend | File::eOpenOptionCanCreate,
perms, error);
@@ -614,10 +609,10 @@ public:
// "platform fread"
//----------------------------------------------------------------------
-static OptionDefinition g_platform_fread_options[] = {
+static constexpr OptionDefinition g_platform_fread_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
- { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Number of bytes to read from the file." },
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
+ { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Number of bytes to read from the file." },
// clang-format on
};
@@ -709,10 +704,10 @@ protected:
// "platform fwrite"
//----------------------------------------------------------------------
-static OptionDefinition g_platform_fwrite_options[] = {
+static constexpr OptionDefinition g_platform_fwrite_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
- { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Text to write to the file." },
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
+ { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Text to write to the file." },
// clang-format on
};
@@ -883,8 +878,8 @@ public:
if (platform_sp) {
const char *remote_file_path = args.GetArgumentAtIndex(0);
const char *local_file_path = args.GetArgumentAtIndex(1);
- Status error = platform_sp->GetFile(FileSpec(remote_file_path, false),
- FileSpec(local_file_path, false));
+ Status error = platform_sp->GetFile(FileSpec(remote_file_path),
+ FileSpec(local_file_path));
if (error.Success()) {
result.AppendMessageWithFormat(
"successfully get-file from %s (remote) to %s (host)\n",
@@ -949,8 +944,7 @@ public:
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, false));
+ user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
if (size != UINT64_MAX) {
result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
"\n",
@@ -987,8 +981,9 @@ public:
const char *src = args.GetArgumentAtIndex(0);
const char *dst = args.GetArgumentAtIndex(1);
- FileSpec src_fs(src, true);
- FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false);
+ FileSpec src_fs(src);
+ FileSystem::Instance().Resolve(src_fs);
+ FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
PlatformSP platform_sp(
m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
@@ -1043,7 +1038,7 @@ protected:
Module *exe_module = target->GetExecutableModulePointer();
if (exe_module) {
m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
- llvm::SmallString<PATH_MAX> exe_path;
+ llvm::SmallString<128> exe_path;
m_options.launch_info.GetExecutableFile().GetPath(exe_path);
if (!exe_path.empty())
m_options.launch_info.GetArguments().AppendArgument(exe_path);
@@ -1102,22 +1097,22 @@ protected:
// "platform process list"
//----------------------------------------------------------------------
-OptionDefinition g_platform_process_list_options[] = {
+static OptionDefinition g_platform_process_list_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "List the process info for a specific process ID." },
- { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." },
- { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." },
- { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." },
- { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." },
- { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
- { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "Find processes that have a matching parent process ID." },
- { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." },
- { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." },
- { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." },
- { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." },
- { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." },
- { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." },
- { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose output." },
+ { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "List the process info for a specific process ID." },
+ { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." },
+ { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." },
+ { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." },
+ { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." },
+ { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
+ { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "Find processes that have a matching parent process ID." },
+ { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." },
+ { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." },
+ { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." },
+ { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." },
+ { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." },
+ { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." },
+ { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose output." },
// clang-format on
};
@@ -1336,31 +1331,31 @@ protected:
case 'n':
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- option_arg, false, FileSpec::Style::native);
+ option_arg, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::Equals);
break;
case 'e':
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- option_arg, false, FileSpec::Style::native);
+ option_arg, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::EndsWith);
break;
case 's':
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- option_arg, false, FileSpec::Style::native);
+ option_arg, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::StartsWith);
break;
case 'c':
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- option_arg, false, FileSpec::Style::native);
+ option_arg, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::Contains);
break;
case 'r':
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- option_arg, false, FileSpec::Style::native);
+ option_arg, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::RegularExpression);
break;
@@ -1488,12 +1483,12 @@ protected:
}
};
-static OptionDefinition g_platform_process_attach_options[] = {
+static constexpr OptionDefinition g_platform_process_attach_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
- { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." },
- { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." },
- { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
+ { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
+ { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." },
+ { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." },
+ { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
// clang-format on
};
@@ -1529,7 +1524,7 @@ public:
break;
case 'n':
- attach_info.GetExecutableFile().SetFile(option_arg, false,
+ attach_info.GetExecutableFile().SetFile(option_arg,
FileSpec::Style::native);
break;
@@ -1576,7 +1571,7 @@ public:
ProcessInstanceInfoMatch match_info;
if (partial_name) {
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- partial_name, false, FileSpec::Style::native);
+ partial_name, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::StartsWith);
}
platform_sp->FindProcesses(match_info, process_infos);
@@ -1673,9 +1668,9 @@ private:
//----------------------------------------------------------------------
// "platform shell"
//----------------------------------------------------------------------
-static OptionDefinition g_platform_shell_options[] = {
+static constexpr OptionDefinition g_platform_shell_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." },
+ { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." },
// clang-format on
};
@@ -1816,9 +1811,10 @@ public:
return false;
}
// TODO: move the bulk of this code over to the platform itself
- FileSpec src(args.GetArgumentAtIndex(0), true);
- FileSpec dst(args.GetArgumentAtIndex(1), false);
- if (!src.Exists()) {
+ FileSpec src(args.GetArgumentAtIndex(0));
+ FileSystem::Instance().Resolve(src);
+ FileSpec dst(args.GetArgumentAtIndex(1));
+ if (!FileSystem::Instance().Exists(src)) {
result.AppendError("source location does not exist or is not accessible");
result.SetStatus(eReturnStatusFailed);
return false;
diff --git a/source/Commands/CommandObjectPlatform.h b/source/Commands/CommandObjectPlatform.h
index 03b8ca00c81d..e15df5a0441f 100644
--- a/source/Commands/CommandObjectPlatform.h
+++ b/source/Commands/CommandObjectPlatform.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectPlatform_h_
#define liblldb_CommandObjectPlatform_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/Options.h"
diff --git a/source/Commands/CommandObjectPlugin.cpp b/source/Commands/CommandObjectPlugin.cpp
index 13ef6b227c5b..2e805bab9d6f 100644
--- a/source/Commands/CommandObjectPlugin.cpp
+++ b/source/Commands/CommandObjectPlugin.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectPlugin.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -63,7 +59,8 @@ protected:
Status error;
- FileSpec dylib_fspec(command[0].ref, true);
+ FileSpec dylib_fspec(command[0].ref);
+ FileSystem::Instance().Resolve(dylib_fspec);
if (m_interpreter.GetDebugger().LoadPlugin(dylib_fspec, error))
result.SetStatus(eReturnStatusSuccessFinishResult);
diff --git a/source/Commands/CommandObjectPlugin.h b/source/Commands/CommandObjectPlugin.h
index d67aa43365d5..cd39eb19b49d 100644
--- a/source/Commands/CommandObjectPlugin.h
+++ b/source/Commands/CommandObjectPlugin.h
@@ -10,11 +10,7 @@
#ifndef liblldb_CommandObjectPlugin_h_
#define liblldb_CommandObjectPlugin_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/lldb-types.h"
diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp
index eb5a19aa4d39..5b0e6d784a02 100644
--- a/source/Commands/CommandObjectProcess.cpp
+++ b/source/Commands/CommandObjectProcess.cpp
@@ -7,17 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectProcess.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/StringConvert.h"
@@ -32,6 +27,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -304,14 +300,14 @@ protected:
// CommandObjectProcessAttach
//-------------------------------------------------------------------------
-static OptionDefinition g_process_attach_options[] = {
+static constexpr OptionDefinition g_process_attach_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Immediately continue the process once attached." },
- { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
- { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." },
- { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." },
- { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Include existing processes when doing attach -w." },
- { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
+ { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Immediately continue the process once attached." },
+ { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
+ { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." },
+ { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." },
+ { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include existing processes when doing attach -w." },
+ { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
// clang-format on
};
@@ -352,7 +348,7 @@ public:
break;
case 'n':
- attach_info.GetExecutableFile().SetFile(option_arg, false,
+ attach_info.GetExecutableFile().SetFile(option_arg,
FileSpec::Style::native);
break;
@@ -403,7 +399,7 @@ public:
ProcessInstanceInfoMatch match_info;
if (partial_name) {
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- partial_name, false, FileSpec::Style::native);
+ partial_name, FileSpec::Style::native);
match_info.SetNameMatchType(NameMatch::StartsWith);
}
platform_sp->FindProcesses(match_info, process_infos);
@@ -459,7 +455,7 @@ protected:
Status error;
error = m_interpreter.GetDebugger().GetTargetList().CreateTarget(
- m_interpreter.GetDebugger(), "", "", false,
+ m_interpreter.GetDebugger(), "", "", eLoadDependentsNo,
nullptr, // No platform options
new_target_sp);
target = new_target_sp.get();
@@ -556,9 +552,9 @@ protected:
// CommandObjectProcessContinue
//-------------------------------------------------------------------------
-static OptionDefinition g_process_continue_options[] = {
+static constexpr OptionDefinition g_process_continue_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." }
+ { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." }
// clang-format on
};
@@ -719,9 +715,9 @@ protected:
//-------------------------------------------------------------------------
// CommandObjectProcessDetach
//-------------------------------------------------------------------------
-static OptionDefinition g_process_detach_options[] = {
+static constexpr OptionDefinition g_process_detach_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
// clang-format on
};
@@ -818,9 +814,9 @@ protected:
// CommandObjectProcessConnect
//-------------------------------------------------------------------------
-static OptionDefinition g_process_connect_options[] = {
+static constexpr OptionDefinition g_process_connect_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
+ { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
// clang-format on
};
@@ -947,9 +943,9 @@ public:
// CommandObjectProcessLoad
//-------------------------------------------------------------------------
-static OptionDefinition g_process_load_options[] = {
+static constexpr OptionDefinition g_process_load_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." },
+ { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." },
// clang-format on
};
@@ -975,7 +971,7 @@ public:
case 'i':
do_install = true;
if (!option_arg.empty())
- install_path.SetFile(option_arg, false, FileSpec::Style::native);
+ install_path.SetFile(option_arg, FileSpec::Style::native);
break;
default:
error.SetErrorStringWithFormat("invalid short option character '%c'",
@@ -1023,18 +1019,20 @@ protected:
uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
if (!m_options.do_install) {
- FileSpec image_spec(image_path, false);
+ FileSpec image_spec(image_path);
platform->ResolveRemotePath(image_spec, image_spec);
image_token =
platform->LoadImage(process, FileSpec(), image_spec, error);
} else if (m_options.install_path) {
- FileSpec image_spec(image_path, true);
+ FileSpec image_spec(image_path);
+ FileSystem::Instance().Resolve(image_spec);
platform->ResolveRemotePath(m_options.install_path,
m_options.install_path);
image_token = platform->LoadImage(process, image_spec,
m_options.install_path, error);
} else {
- FileSpec image_spec(image_path, true);
+ FileSpec image_spec(image_path);
+ FileSystem::Instance().Resolve(image_spec);
image_token =
platform->LoadImage(process, image_spec, FileSpec(), error);
}
@@ -1281,7 +1279,7 @@ protected:
ProcessSP process_sp = m_exe_ctx.GetProcessSP();
if (process_sp) {
if (command.GetArgumentCount() == 1) {
- FileSpec output_file(command.GetArgumentAtIndex(0), false);
+ FileSpec output_file(command.GetArgumentAtIndex(0));
Status error = PluginManager::SaveCore(process_sp, output_file);
if (error.Success()) {
result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -1343,11 +1341,11 @@ public:
// CommandObjectProcessHandle
//-------------------------------------------------------------------------
-static OptionDefinition g_process_handle_options[] = {
+static constexpr OptionDefinition g_process_handle_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
- { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }
+ { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
+ { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }
// clang-format on
};
diff --git a/source/Commands/CommandObjectProcess.h b/source/Commands/CommandObjectProcess.h
index 0f520f63e1dd..7325dce49683 100644
--- a/source/Commands/CommandObjectProcess.h
+++ b/source/Commands/CommandObjectProcess.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectProcess_h_
#define liblldb_CommandObjectProcess_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectQuit.cpp b/source/Commands/CommandObjectQuit.cpp
index 37ed12be358f..2c5b20bf5846 100644
--- a/source/Commands/CommandObjectQuit.cpp
+++ b/source/Commands/CommandObjectQuit.cpp
@@ -9,10 +9,6 @@
#include "CommandObjectQuit.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Process.h"
@@ -35,7 +31,7 @@ CommandObjectQuit::~CommandObjectQuit() {}
// if all alive processes will be detached when you quit and false if at least
// one process will be killed instead
bool CommandObjectQuit::ShouldAskForConfirmation(bool &is_a_detach) {
- if (m_interpreter.GetPromptOnQuit() == false)
+ if (!m_interpreter.GetPromptOnQuit())
return false;
bool should_prompt = false;
is_a_detach = true;
@@ -55,7 +51,7 @@ bool CommandObjectQuit::ShouldAskForConfirmation(bool &is_a_detach) {
if (process_sp && process_sp->IsValid() && process_sp->IsAlive() &&
process_sp->WarnBeforeDetach()) {
should_prompt = true;
- if (process_sp->GetShouldDetach() == false) {
+ if (!process_sp->GetShouldDetach()) {
// if we need to kill at least one process, just say so and return
is_a_detach = false;
return should_prompt;
@@ -86,13 +82,6 @@ bool CommandObjectQuit::DoExecute(Args &command, CommandReturnObject &result) {
return false;
}
- if (command.GetArgumentCount() > 1) {
- result.AppendError("Too many arguments for 'quit'. Only an optional exit "
- "code is allowed");
- result.SetStatus(eReturnStatusFailed);
- return false;
- }
-
// We parse the exit code argument if there is one.
if (command.GetArgumentCount() == 1) {
llvm::StringRef arg = command.GetArgumentAtIndex(0);
diff --git a/source/Commands/CommandObjectQuit.h b/source/Commands/CommandObjectQuit.h
index f2998f8690fb..0f9da62278d9 100644
--- a/source/Commands/CommandObjectQuit.h
+++ b/source/Commands/CommandObjectQuit.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectQuit_h_
#define liblldb_CommandObjectQuit_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp
index 4dadc5d68d20..ae8b5d0027c7 100644
--- a/source/Commands/CommandObjectRegister.cpp
+++ b/source/Commands/CommandObjectRegister.cpp
@@ -10,8 +10,6 @@
#include "CommandObjectRegister.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpRegisterValue.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -27,6 +25,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Errno.h"
using namespace lldb;
@@ -36,11 +36,11 @@ using namespace lldb_private;
// "register read"
//----------------------------------------------------------------------
-static OptionDefinition g_register_read_options[] = {
+static constexpr OptionDefinition g_register_read_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display register names using the alternate register name if there is one." },
- { LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Specify which register sets to dump by index." },
- { LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show all register sets." },
+ { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display register names using the alternate register name if there is one." },
+ { LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Specify which register sets to dump by index." },
+ { LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show all register sets." },
// clang-format on
};
diff --git a/source/Commands/CommandObjectRegister.h b/source/Commands/CommandObjectRegister.h
index 81f2f6bae223..96fc47af0a21 100644
--- a/source/Commands/CommandObjectRegister.h
+++ b/source/Commands/CommandObjectRegister.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectRegister_h_
#define liblldb_CommandObjectRegister_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectReproducer.cpp b/source/Commands/CommandObjectReproducer.cpp
new file mode 100644
index 000000000000..f393f17d9aec
--- /dev/null
+++ b/source/Commands/CommandObjectReproducer.cpp
@@ -0,0 +1,97 @@
+//===-- CommandObjectReproducer.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectReproducer.h"
+
+#include "lldb/Utility/Reproducer.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class CommandObjectReproducerGenerate : public CommandObjectParsed {
+public:
+ CommandObjectReproducerGenerate(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "reproducer generate",
+ "Generate reproducer on disk.", nullptr) {}
+
+ ~CommandObjectReproducerGenerate() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (!command.empty()) {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
+ return false;
+ }
+
+ auto &r = repro::Reproducer::Instance();
+ if (auto generator = r.GetGenerator()) {
+ generator->Keep();
+ } else {
+ result.AppendErrorWithFormat("Unable to get the reproducer generator");
+ return false;
+ }
+
+ result.GetOutputStream()
+ << "Reproducer written to '" << r.GetReproducerPath() << "'\n";
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectReproducerStatus : public CommandObjectParsed {
+public:
+ CommandObjectReproducerStatus(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "reproducer status",
+ "Show the current reproducer status.", nullptr) {}
+
+ ~CommandObjectReproducerStatus() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ if (!command.empty()) {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
+ return false;
+ }
+
+ auto &r = repro::Reproducer::Instance();
+ if (auto generator = r.GetGenerator()) {
+ result.GetOutputStream() << "Reproducer is in capture mode.\n";
+ } else if (auto generator = r.GetLoader()) {
+ result.GetOutputStream() << "Reproducer is in replay mode.\n";
+ } else {
+
+ result.GetOutputStream() << "Reproducer is off.\n";
+ }
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+};
+
+CommandObjectReproducer::CommandObjectReproducer(
+ CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "reproducer",
+ "Commands controlling LLDB reproducers.",
+ "log <subcommand> [<command-options>]") {
+ LoadSubCommand(
+ "generate",
+ CommandObjectSP(new CommandObjectReproducerGenerate(interpreter)));
+ LoadSubCommand("status", CommandObjectSP(
+ new CommandObjectReproducerStatus(interpreter)));
+}
+
+CommandObjectReproducer::~CommandObjectReproducer() = default;
diff --git a/source/Commands/CommandObjectReproducer.h b/source/Commands/CommandObjectReproducer.h
new file mode 100644
index 000000000000..6691e8a8e626
--- /dev/null
+++ b/source/Commands/CommandObjectReproducer.h
@@ -0,0 +1,31 @@
+//===-- CommandObjectReproducer.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_CommandObjectReproducer_h_
+#define liblldb_CommandObjectReproducer_h_
+
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/Options.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectReproducer
+//-------------------------------------------------------------------------
+
+class CommandObjectReproducer : public CommandObjectMultiword {
+public:
+ CommandObjectReproducer(CommandInterpreter &interpreter);
+
+ ~CommandObjectReproducer() override;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectReproducer_h_
diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp
index 3db1e35cd702..967a009189e4 100644
--- a/source/Commands/CommandObjectSettings.cpp
+++ b/source/Commands/CommandObjectSettings.cpp
@@ -9,12 +9,8 @@
#include "CommandObjectSettings.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -28,9 +24,10 @@ using namespace lldb_private;
// CommandObjectSettingsSet
//-------------------------------------------------------------------------
-static OptionDefinition g_settings_set_options[] = {
+static constexpr OptionDefinition g_settings_set_options[] = {
// clang-format off
- { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Apply the new value to the global default value." }
+ { LLDB_OPT_SET_2, false, "global", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Apply the new value to the global default value." },
+ { LLDB_OPT_SET_2, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Force an empty value to be accepted as the default." }
// clang-format on
};
@@ -108,6 +105,9 @@ insert-before or insert-after.");
const int short_option = m_getopt_table[option_idx].val;
switch (short_option) {
+ case 'f':
+ m_force = true;
+ break;
case 'g':
m_global = true;
break;
@@ -122,6 +122,7 @@ insert-before or insert-after.");
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_global = false;
+ m_force = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -129,8 +130,8 @@ insert-before or insert-after.");
}
// Instance variables to hold the values for command options.
-
bool m_global;
+ bool m_force;
};
int HandleArgumentCompletion(
@@ -184,8 +185,10 @@ protected:
if (!ParseOptions(cmd_args, result))
return false;
+ const size_t min_argc = m_options.m_force ? 1 : 2;
const size_t argc = cmd_args.GetArgumentCount();
- if ((argc < 2) && (!m_options.m_global)) {
+
+ if ((argc < min_argc) && (!m_options.m_global)) {
result.AppendError("'settings set' takes more arguments");
result.SetStatus(eReturnStatusFailed);
return false;
@@ -199,6 +202,19 @@ protected:
return false;
}
+ // A missing value corresponds to clearing the setting when "force" is
+ // specified.
+ if (argc == 1 && m_options.m_force) {
+ Status error(m_interpreter.GetDebugger().SetPropertyValue(
+ &m_exe_ctx, eVarSetOperationClear, var_name, llvm::StringRef()));
+ if (error.Fail()) {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ return result.Succeeded();
+ }
+
// Split the raw command into var_name and value pair.
llvm::StringRef raw_str(command);
std::string var_value_string = raw_str.split(var_name).second.str();
@@ -301,6 +317,210 @@ protected:
};
//-------------------------------------------------------------------------
+// CommandObjectSettingsWrite -- Write settings to file
+//-------------------------------------------------------------------------
+
+static constexpr OptionDefinition g_settings_write_options[] = {
+ // clang-format off
+ { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the settings." },
+ { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved settings file if it exists."},
+ // clang-format on
+};
+
+class CommandObjectSettingsWrite : public CommandObjectParsed {
+public:
+ CommandObjectSettingsWrite(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "settings export",
+ "Write matching debugger settings and their "
+ "current values to a file that can be read in with "
+ "\"settings read\". Defaults to writing all settings.",
+ nullptr),
+ m_options() {
+ CommandArgumentEntry arg1;
+ CommandArgumentData var_name_arg;
+
+ // Define the first (and only) variant of this arg.
+ var_name_arg.arg_type = eArgTypeSettingVariableName;
+ var_name_arg.arg_repetition = eArgRepeatOptional;
+
+ // There is only one variant this argument could be; put it into the
+ // argument entry.
+ arg1.push_back(var_name_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back(arg1);
+ }
+
+ ~CommandObjectSettingsWrite() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'f':
+ m_filename.assign(option_arg);
+ break;
+ case 'a':
+ m_append = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_filename.clear();
+ m_append = false;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_settings_write_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ std::string m_filename;
+ bool m_append = false;
+ };
+
+protected:
+ bool DoExecute(Args &args, CommandReturnObject &result) override {
+ FileSpec file_spec(m_options.m_filename);
+ FileSystem::Instance().Resolve(file_spec);
+ std::string path(file_spec.GetPath());
+ uint32_t options = File::OpenOptions::eOpenOptionWrite |
+ File::OpenOptions::eOpenOptionCanCreate;
+ if (m_options.m_append)
+ options |= File::OpenOptions::eOpenOptionAppend;
+ else
+ options |= File::OpenOptions::eOpenOptionTruncate;
+
+ StreamFile out_file(path.c_str(), options,
+ lldb::eFilePermissionsFileDefault);
+
+ if (!out_file.GetFile().IsValid()) {
+ result.AppendErrorWithFormat("%s: unable to write to file", path.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ // Exporting should not be context sensitive.
+ ExecutionContext clean_ctx;
+
+ if (args.empty()) {
+ m_interpreter.GetDebugger().DumpAllPropertyValues(
+ &clean_ctx, out_file, OptionValue::eDumpGroupExport);
+ return result.Succeeded();
+ }
+
+ for (const auto &arg : args) {
+ Status error(m_interpreter.GetDebugger().DumpPropertyValue(
+ &clean_ctx, out_file, arg.ref, OptionValue::eDumpGroupExport));
+ if (!error.Success()) {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ }
+ }
+
+ return result.Succeeded();
+ }
+
+private:
+ CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectSettingsRead -- Read settings from file
+//-------------------------------------------------------------------------
+
+static constexpr OptionDefinition g_settings_read_options[] = {
+ // clang-format off
+ {LLDB_OPT_SET_ALL, true, "file",'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
+ // clang-format on
+};
+
+class CommandObjectSettingsRead : public CommandObjectParsed {
+public:
+ CommandObjectSettingsRead(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "settings read",
+ "Read settings previously saved to a file with \"settings write\".",
+ nullptr),
+ m_options() {}
+
+ ~CommandObjectSettingsRead() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() : Options() {}
+
+ ~CommandOptions() override = default;
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option) {
+ case 'f':
+ m_filename.assign(option_arg);
+ break;
+ default:
+ error.SetErrorStringWithFormat("unrecognized option '%c'",
+ short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_filename.clear();
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_settings_read_options);
+ }
+
+ // Instance variables to hold the values for command options.
+ std::string m_filename;
+ };
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ FileSpec file(m_options.m_filename);
+ FileSystem::Instance().Resolve(file);
+ ExecutionContext clean_ctx;
+ CommandInterpreterRunOptions options;
+ options.SetAddToHistory(false);
+ options.SetEchoCommands(false);
+ options.SetPrintResults(true);
+ options.SetStopOnError(false);
+ m_interpreter.HandleCommandsFromFile(file, &clean_ctx, options, result);
+ return result.Succeeded();
+ }
+
+private:
+ CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
// CommandObjectSettingsList -- List settable variables
//-------------------------------------------------------------------------
@@ -987,6 +1207,10 @@ CommandObjectMultiwordSettings::CommandObjectMultiwordSettings(
CommandObjectSP(new CommandObjectSettingsAppend(interpreter)));
LoadSubCommand("clear",
CommandObjectSP(new CommandObjectSettingsClear(interpreter)));
+ LoadSubCommand("write",
+ CommandObjectSP(new CommandObjectSettingsWrite(interpreter)));
+ LoadSubCommand("read",
+ CommandObjectSP(new CommandObjectSettingsRead(interpreter)));
}
CommandObjectMultiwordSettings::~CommandObjectMultiwordSettings() = default;
diff --git a/source/Commands/CommandObjectSettings.h b/source/Commands/CommandObjectSettings.h
index 3376cccd1799..df1338600456 100644
--- a/source/Commands/CommandObjectSettings.h
+++ b/source/Commands/CommandObjectSettings.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectSettings_h_
#define liblldb_CommandObjectSettings_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/Options.h"
diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp
index 19e2e441c241..2fce34f9846e 100644
--- a/source/Commands/CommandObjectSource.cpp
+++ b/source/Commands/CommandObjectSource.cpp
@@ -9,10 +9,6 @@
#include "CommandObjectSource.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FileLineResolver.h"
#include "lldb/Core/Module.h"
@@ -41,15 +37,15 @@ using namespace lldb_private;
// CommandObjectSourceInfo - debug line entries dumping command
//----------------------------------------------------------------------
-static OptionDefinition g_source_info_options[] = {
+static constexpr OptionDefinition g_source_info_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of line entries to display." },
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)." },
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." },
- { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "The line number at which to start the displaying lines." },
- { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "The line number at which to stop displaying lines." },
- { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." },
- { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." },
+ { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of line entries to display." },
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)." },
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." },
+ { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the displaying lines." },
+ { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to stop displaying lines." },
+ { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." },
+ { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." },
// clang-format on
};
@@ -517,7 +513,7 @@ protected:
// Dump the line entries found in the file specified in the option.
bool DumpLinesForFile(CommandReturnObject &result) {
- FileSpec file_spec(m_options.file_name, false);
+ FileSpec file_spec(m_options.file_name);
const char *filename = m_options.file_name.c_str();
Target *target = m_exe_ctx.GetTargetPtr();
const ModuleList &module_list =
@@ -596,7 +592,7 @@ protected:
m_module_list.Clear();
if (!m_options.modules.empty()) {
for (size_t i = 0, e = m_options.modules.size(); i < e; ++i) {
- FileSpec module_file_spec(m_options.modules[i], false);
+ FileSpec module_file_spec(m_options.modules[i]);
if (module_file_spec) {
ModuleSpec module_spec(module_file_spec);
if (target->GetImages().FindModules(module_spec, m_module_list) == 0)
@@ -653,16 +649,16 @@ protected:
// CommandObjectSourceList
//-------------------------------------------------------------------------
-static OptionDefinition g_source_list_options[] = {
+static constexpr OptionDefinition g_source_list_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "The number of source lines to display." },
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library." },
- { LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, nullptr, 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, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." },
- { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "The line number at which to start the display source." },
- { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." },
- { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source." },
+ { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of source lines to display." },
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library." },
+ { LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, {}, 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, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." },
+ { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the display source." },
+ { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." },
+ { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source." },
// clang-format on
};
@@ -921,7 +917,7 @@ protected:
if (num_modules > 0) {
ModuleList matching_modules;
for (size_t i = 0; i < num_modules; ++i) {
- FileSpec module_file_spec(m_options.modules[i], false);
+ FileSpec module_file_spec(m_options.modules[i]);
if (module_file_spec) {
ModuleSpec module_spec(module_file_spec);
matching_modules.Clear();
@@ -946,7 +942,7 @@ protected:
if (num_modules > 0) {
ModuleList matching_modules;
for (size_t i = 0; i < num_modules; ++i) {
- FileSpec module_file_spec(m_options.modules[i], false);
+ FileSpec module_file_spec(m_options.modules[i]);
if (module_file_spec) {
ModuleSpec module_spec(module_file_spec);
matching_modules.Clear();
@@ -1203,14 +1199,16 @@ protected:
if (!m_options.modules.empty()) {
ModuleList matching_modules;
for (size_t i = 0, e = m_options.modules.size(); i < e; ++i) {
- FileSpec module_file_spec(m_options.modules[i], false);
+ FileSpec module_file_spec(m_options.modules[i]);
if (module_file_spec) {
ModuleSpec module_spec(module_file_spec);
matching_modules.Clear();
target->GetImages().FindModules(module_spec, matching_modules);
num_matches += matching_modules.ResolveSymbolContextForFilePath(
filename, 0, check_inlines,
- eSymbolContextModule | eSymbolContextCompUnit, sc_list);
+ SymbolContextItem(eSymbolContextModule |
+ eSymbolContextCompUnit),
+ sc_list);
}
}
} else {
diff --git a/source/Commands/CommandObjectSource.h b/source/Commands/CommandObjectSource.h
index e81ac1961d26..b2553832210d 100644
--- a/source/Commands/CommandObjectSource.h
+++ b/source/Commands/CommandObjectSource.h
@@ -11,10 +11,6 @@
#ifndef liblldb_CommandObjectSource_h_
#define liblldb_CommandObjectSource_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/STLUtils.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp
index 8be43cbf9bb0..ee55b22c5ea2 100644
--- a/source/Commands/CommandObjectTarget.cpp
+++ b/source/Commands/CommandObjectTarget.cpp
@@ -9,13 +9,11 @@
#include "CommandObjectTarget.h"
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
@@ -51,13 +49,12 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Timer.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatAdapters.h"
-// C Includes
-// C++ Includes
#include <cerrno>
using namespace lldb;
@@ -138,6 +135,71 @@ static uint32_t DumpTargetList(TargetList &target_list,
return num_targets;
}
+// Note that the negation in the argument name causes a slightly confusing
+// mapping of the enum values,
+static constexpr OptionEnumValueElement g_dependents_enumaration[] = {
+ {eLoadDependentsDefault, "default",
+ "Only load dependents when the target is an executable."},
+ {eLoadDependentsNo, "true",
+ "Don't load dependents, even if the target is an executable."},
+ {eLoadDependentsYes, "false",
+ "Load dependents, even if the target is not an executable."}};
+
+static constexpr OptionDefinition g_dependents_options[] = {
+ {LLDB_OPT_SET_1, false, "no-dependents", 'd',
+ OptionParser::eOptionalArgument, nullptr,
+ OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue,
+ "Whether or not to load dependents when creating a target. If the option "
+ "is not specified, the value is implicitly 'default'. If the option is "
+ "specified but without a value, the value is implicitly 'true'."}};
+
+class OptionGroupDependents : public OptionGroup {
+public:
+ OptionGroupDependents() {}
+
+ ~OptionGroupDependents() override {}
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::makeArrayRef(g_dependents_options);
+ }
+
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
+ ExecutionContext *execution_context) override {
+ Status error;
+
+ // For compatibility no value means don't load dependents.
+ if (option_value.empty()) {
+ m_load_dependent_files = eLoadDependentsNo;
+ return error;
+ }
+
+ const char short_option = g_dependents_options[option_idx].short_option;
+ if (short_option == 'd') {
+ LoadDependentFiles tmp_load_dependents;
+ tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum(
+ option_value, g_dependents_options[option_idx].enum_values, 0, error);
+ if (error.Success())
+ m_load_dependent_files = tmp_load_dependents;
+ } else {
+ error.SetErrorStringWithFormat("unrecognized short option '%c'",
+ short_option);
+ }
+
+ return error;
+ }
+
+ Status SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_load_dependent_files = eLoadDependentsDefault;
+ }
+
+ LoadDependentFiles m_load_dependent_files;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(OptionGroupDependents);
+};
+
#pragma mark CommandObjectTargetCreate
//-------------------------------------------------------------------------
@@ -158,16 +220,14 @@ public:
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."),
+ 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) {
+ m_add_dependents() {
CommandArgumentEntry arg;
CommandArgumentData file_arg;
@@ -211,13 +271,13 @@ protected:
FileSpec remote_file(m_remote_file.GetOptionValue().GetCurrentValue());
if (core_file) {
- if (!core_file.Exists()) {
+ if (!FileSystem::Instance().Exists(core_file)) {
result.AppendErrorWithFormat("core file '%s' doesn't exist",
core_file.GetPath().c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
- if (!core_file.Readable()) {
+ if (!FileSystem::Instance().Readable(core_file)) {
result.AppendErrorWithFormat("core file '%s' is not readable",
core_file.GetPath().c_str());
result.SetStatus(eReturnStatusFailed);
@@ -228,8 +288,8 @@ protected:
if (argc == 1 || core_file || remote_file) {
FileSpec symfile(m_symbol_file.GetOptionValue().GetCurrentValue());
if (symfile) {
- if (symfile.Exists()) {
- if (!symfile.Readable()) {
+ if (FileSystem::Instance().Exists(symfile)) {
+ if (!FileSystem::Instance().Readable(symfile)) {
result.AppendErrorWithFormat("symbol file '%s' is not readable",
symfile.GetPath().c_str());
result.SetStatus(eReturnStatusFailed);
@@ -250,8 +310,10 @@ protected:
Timer scoped_timer(func_cat, "(lldb) target create '%s'", file_path);
FileSpec file_spec;
- if (file_path)
- file_spec.SetFile(file_path, true, FileSpec::Style::native);
+ if (file_path) {
+ file_spec.SetFile(file_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(file_spec);
+ }
bool must_set_platform_path = false;
@@ -259,11 +321,9 @@ protected:
TargetSP target_sp;
llvm::StringRef arch_cstr = m_arch_option.GetArchitectureName();
- const bool get_dependent_files =
- m_add_dependents.GetOptionValue().GetCurrentValue();
Status error(debugger.GetTargetList().CreateTarget(
- debugger, file_path, arch_cstr, get_dependent_files, nullptr,
- target_sp));
+ debugger, file_path, arch_cstr,
+ m_add_dependents.m_load_dependent_files, nullptr, target_sp));
if (target_sp) {
// Only get the platform after we create the target because we might
@@ -275,7 +335,7 @@ protected:
if (remote_file) {
if (platform_sp) {
// I have a remote file.. two possible cases
- if (file_spec && file_spec.Exists()) {
+ if (file_spec && FileSystem::Instance().Exists(file_spec)) {
// if the remote file does not exist, push it there
if (!platform_sp->GetFileExists(remote_file)) {
Status err = platform_sp->PutFile(file_spec, remote_file);
@@ -343,8 +403,8 @@ protected:
if (core_file) {
char core_path[PATH_MAX];
core_file.GetPath(core_path, sizeof(core_path));
- if (core_file.Exists()) {
- if (!core_file.Readable()) {
+ if (FileSystem::Instance().Exists(core_file)) {
+ if (!FileSystem::Instance().Readable(core_file)) {
result.AppendMessageWithFormat(
"Core file '%s' is not readable.\n", core_path);
result.SetStatus(eReturnStatusFailed);
@@ -411,7 +471,7 @@ private:
OptionGroupFile m_platform_path;
OptionGroupFile m_symbol_file;
OptionGroupFile m_remote_file;
- OptionGroupBoolean m_add_dependents;
+ OptionGroupDependents m_add_dependents;
};
#pragma mark CommandObjectTargetList
@@ -1612,12 +1672,11 @@ static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
const uint32_t max_num_matches = UINT32_MAX;
size_t num_matches = 0;
bool name_is_fully_qualified = false;
- SymbolContext sc;
ConstString name(name_cstr);
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
num_matches =
- module->FindTypes(sc, name, name_is_fully_qualified, max_num_matches,
+ module->FindTypes(name, name_is_fully_qualified, max_num_matches,
searched_symbol_files, type_list);
if (num_matches) {
@@ -1655,11 +1714,8 @@ static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm,
}
static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
- const SymbolContext &sym_ctx,
- const char *name_cstr, bool name_is_regex) {
- if (!sym_ctx.module_sp)
- return 0;
-
+ Module &module, const char *name_cstr,
+ bool name_is_regex) {
TypeList type_list;
const uint32_t max_num_matches = UINT32_MAX;
size_t num_matches = 1;
@@ -1667,14 +1723,13 @@ static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm,
ConstString name(name_cstr);
llvm::DenseSet<SymbolFile *> searched_symbol_files;
- num_matches = sym_ctx.module_sp->FindTypes(
- sym_ctx, name, name_is_fully_qualified, max_num_matches,
- searched_symbol_files, type_list);
+ num_matches = module.FindTypes(name, name_is_fully_qualified, max_num_matches,
+ searched_symbol_files, type_list);
if (num_matches) {
strm.Indent();
strm.PutCString("Best match found in ");
- DumpFullpath(strm, &sym_ctx.module_sp->GetFileSpec(), 0);
+ DumpFullpath(strm, &module.GetFileSpec(), 0);
strm.PutCString(":\n");
TypeSP type_sp(type_list.GetTypeAtIndex(0));
@@ -1732,7 +1787,7 @@ static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter,
static size_t FindModulesByName(Target *target, const char *module_name,
ModuleList &module_list,
bool check_global_list) {
- FileSpec module_file_spec(module_name, false);
+ FileSpec module_file_spec(module_name);
ModuleSpec module_spec(module_file_spec);
const size_t initial_size = module_list.GetSize();
@@ -1922,16 +1977,15 @@ protected:
#pragma mark CommandObjectTargetModulesDumpSymtab
-static OptionEnumValueElement g_sort_option_enumeration[4] = {
+static constexpr OptionEnumValueElement g_sort_option_enumeration[] = {
{eSortOrderNone, "none",
"No sorting, use the original symbol table order."},
{eSortOrderByAddress, "address", "Sort output by symbol address."},
- {eSortOrderByName, "name", "Sort output by symbol name."},
- {0, nullptr, nullptr}};
+ {eSortOrderByName, "name", "Sort output by symbol name."} };
-static OptionDefinition g_target_modules_dump_symtab_options[] = {
+static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." }
+ { LLDB_OPT_SET_1, false, "sort", 's', OptionParser::eRequiredArgument, nullptr, OptionEnumValues(g_sort_option_enumeration), 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table." }
// clang-format on
};
@@ -2165,6 +2219,85 @@ protected:
}
};
+#pragma mark CommandObjectTargetModulesDumpSections
+
+//----------------------------------------------------------------------
+// Clang AST dumping command
+//----------------------------------------------------------------------
+
+class CommandObjectTargetModulesDumpClangAST
+ : public CommandObjectTargetModulesModuleAutoComplete {
+public:
+ CommandObjectTargetModulesDumpClangAST(CommandInterpreter &interpreter)
+ : CommandObjectTargetModulesModuleAutoComplete(
+ interpreter, "target modules dump ast",
+ "Dump the clang ast for a given module's symbol file.",
+ //"target modules dump ast [<file1> ...]")
+ nullptr) {}
+
+ ~CommandObjectTargetModulesDumpClangAST() override = default;
+
+protected:
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+ if (target == nullptr) {
+ result.AppendError("invalid target, create a debug target using the "
+ "'target create' command");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ const size_t num_modules = target->GetImages().GetSize();
+ if (num_modules == 0) {
+ result.AppendError("the target has no associated executable images");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 0) {
+ // Dump all ASTs for all modules images
+ result.GetOutputStream().Printf("Dumping clang ast for %" PRIu64
+ " modules.\n",
+ (uint64_t)num_modules);
+ for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
+ if (m_interpreter.WasInterrupted())
+ break;
+ Module *m = target->GetImages().GetModulePointerAtIndex(image_idx);
+ SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile();
+ sf->DumpClangAST(result.GetOutputStream());
+ }
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+ // Dump specified ASTs (by basename or fullpath)
+ for (const Args::ArgEntry &arg : command.entries()) {
+ ModuleList module_list;
+ const size_t num_matches =
+ FindModulesByName(target, arg.c_str(), module_list, true);
+ if (num_matches == 0) {
+ // Check the global list
+ std::lock_guard<std::recursive_mutex> guard(
+ Module::GetAllocationModuleCollectionMutex());
+
+ result.AppendWarningWithFormat(
+ "Unable to find an image that matches '%s'.\n", arg.c_str());
+ continue;
+ }
+
+ for (size_t i = 0; i < num_matches; ++i) {
+ if (m_interpreter.WasInterrupted())
+ break;
+ Module *m = module_list.GetModulePointerAtIndex(i);
+ SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile();
+ sf->DumpClangAST(result.GetOutputStream());
+ }
+ }
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+};
+
#pragma mark CommandObjectTargetModulesDumpSymfile
//----------------------------------------------------------------------
@@ -2292,7 +2425,7 @@ protected:
for (int arg_idx = 0;
(arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr;
++arg_idx) {
- FileSpec file_spec(arg_cstr, false);
+ FileSpec file_spec(arg_cstr);
const ModuleList &target_modules = target->GetImages();
std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex());
@@ -2340,12 +2473,13 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
CommandObjectTargetModulesDump(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "target modules dump",
- "Commands for dumping information about one or "
- "more target modules.",
- "target modules dump "
- "[headers|symtab|sections|symfile|line-table] "
- "[<file1> <file2> ...]") {
+ : CommandObjectMultiword(
+ interpreter, "target modules dump",
+ "Commands for dumping information about one or "
+ "more target modules.",
+ "target modules dump "
+ "[headers|symtab|sections|ast|symfile|line-table] "
+ "[<file1> <file2> ...]") {
LoadSubCommand("objfile",
CommandObjectSP(
new CommandObjectTargetModulesDumpObjfile(interpreter)));
@@ -2358,6 +2492,9 @@ public:
LoadSubCommand("symfile",
CommandObjectSP(
new CommandObjectTargetModulesDumpSymfile(interpreter)));
+ LoadSubCommand(
+ "ast", CommandObjectSP(
+ new CommandObjectTargetModulesDumpClangAST(interpreter)));
LoadSubCommand("line-table",
CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
interpreter)));
@@ -2472,8 +2609,8 @@ protected:
if (entry.ref.empty())
continue;
- FileSpec file_spec(entry.ref, true);
- if (file_spec.Exists()) {
+ FileSpec file_spec(entry.ref);
+ if (FileSystem::Instance().Exists(file_spec)) {
ModuleSpec module_spec(file_spec);
if (m_uuid_option_group.GetOptionValue().OptionWasSet())
module_spec.GetUUID() =
@@ -2740,10 +2877,15 @@ protected:
}
if (set_pc) {
ThreadList &thread_list = process->GetThreadList();
- ThreadSP curr_thread(thread_list.GetSelectedThread());
RegisterContextSP reg_context(
- curr_thread->GetRegisterContext());
- reg_context->SetPC(file_entry.GetLoadAddress(target));
+ thread_list.GetSelectedThread()->GetRegisterContext());
+ addr_t file_entry_addr = file_entry.GetLoadAddress(target);
+ if (!reg_context->SetPC(file_entry_addr)) {
+ result.AppendErrorWithFormat("failed to set PC value to "
+ "0x%" PRIx64 "\n",
+ file_entry_addr);
+ result.SetStatus(eReturnStatusFailed);
+ }
}
}
} else {
@@ -2817,23 +2959,23 @@ protected:
// List images with associated information
//----------------------------------------------------------------------
-static OptionDefinition g_target_modules_list_options[] = {
+static constexpr OptionDefinition g_target_modules_list_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
- { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the architecture when listing images." },
- { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the triple when listing images." },
- { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, nullptr, nullptr, 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, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeNone, "Display the UUID when listing images." },
- { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the fullpath to the image object file." },
- { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." },
- { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." },
- { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." },
- { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeWidth, "Display the modification time with optional width of the module." },
- { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeNone, "Display the module pointer." },
- { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." }
+ { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." },
+ { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the architecture when listing images." },
+ { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the triple when listing images." },
+ { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image base address as a load address if debugging, a file address otherwise." },
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image load address offset from the base file address (the slide amount)." },
+ { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the UUID when listing images." },
+ { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image object file." },
+ { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." },
+ { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." },
+ { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." },
+ { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeWidth, "Display the modification time with optional width of the module." },
+ { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeNone, "Display the module pointer." },
+ { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." }
// clang-format on
};
@@ -3082,13 +3224,13 @@ protected:
ObjectFile *objfile = module->GetObjectFile();
if (objfile) {
- Address header_addr(objfile->GetHeaderAddress());
- if (header_addr.IsValid()) {
+ Address base_addr(objfile->GetBaseAddress());
+ if (base_addr.IsValid()) {
if (target && !target->GetSectionLoadList().IsEmpty()) {
- lldb::addr_t header_load_addr =
- header_addr.GetLoadAddress(target);
- if (header_load_addr == LLDB_INVALID_ADDRESS) {
- header_addr.Dump(&strm, target,
+ lldb::addr_t load_addr =
+ base_addr.GetLoadAddress(target);
+ if (load_addr == LLDB_INVALID_ADDRESS) {
+ base_addr.Dump(&strm, target,
Address::DumpStyleModuleWithFileAddress,
Address::DumpStyleFileAddress);
} else {
@@ -3096,18 +3238,18 @@ protected:
// Show the offset of slide for the image
strm.Printf(
"0x%*.*" PRIx64, addr_nibble_width, addr_nibble_width,
- header_load_addr - header_addr.GetFileAddress());
+ load_addr - base_addr.GetFileAddress());
} else {
// Show the load address of the image
strm.Printf("0x%*.*" PRIx64, addr_nibble_width,
- addr_nibble_width, header_load_addr);
+ addr_nibble_width, load_addr);
}
}
break;
}
// The address was valid, but the image isn't loaded, output the
// address in an appropriate format
- header_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
+ base_addr.Dump(&strm, target, Address::DumpStyleFileAddress);
break;
}
}
@@ -3183,10 +3325,10 @@ protected:
// Lookup unwind information in images
//----------------------------------------------------------------------
-static OptionDefinition g_target_modules_show_unwind_options[] = {
+static constexpr OptionDefinition g_target_modules_show_unwind_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." },
- { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
+ { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." },
+ { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" }
// clang-format on
};
@@ -3489,21 +3631,21 @@ protected:
// Lookup information in images
//----------------------------------------------------------------------
-static OptionDefinition g_target_modules_lookup_options[] = {
+static constexpr OptionDefinition g_target_modules_lookup_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
- { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." },
+ { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup." },
/* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions." },
- { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." },
- { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." },
- { LLDB_OPT_SET_FROM_TO(3,5), false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." },
- { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." },
- { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose lookup information." },
- { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." },
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions." },
+ { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." },
+ { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." },
+ { LLDB_OPT_SET_FROM_TO(3,5), false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." },
+ { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." },
+ { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeNone, "Enable verbose lookup information." },
+ { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." },
// clang-format on
};
@@ -3551,7 +3693,7 @@ public:
break;
case 'f':
- m_file.SetFile(option_arg, false, FileSpec::Style::native);
+ m_file.SetFile(option_arg, FileSpec::Style::native);
m_type = eLookupTypeFileLine;
break;
@@ -3685,8 +3827,9 @@ public:
return false;
case eLookupTypeType:
if (!m_options.m_str.empty()) {
- if (LookupTypeHere(m_interpreter, result.GetOutputStream(), sym_ctx,
- m_options.m_str.c_str(), m_options.m_use_regex)) {
+ if (LookupTypeHere(m_interpreter, result.GetOutputStream(),
+ *sym_ctx.module_sp, m_options.m_str.c_str(),
+ m_options.m_use_regex)) {
result.SetStatus(eReturnStatusSuccessFinishResult);
return true;
}
@@ -4190,7 +4333,8 @@ protected:
ModuleSP frame_module_sp(
frame->GetSymbolContext(eSymbolContextModule).module_sp);
if (frame_module_sp) {
- if (frame_module_sp->GetPlatformFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(
+ frame_module_sp->GetPlatformFileSpec())) {
module_spec.GetArchitecture() =
frame_module_sp->GetArchitecture();
module_spec.GetFileSpec() =
@@ -4237,7 +4381,7 @@ protected:
module_spec.GetArchitecture() = target->GetArchitecture();
}
success |= module_spec.GetUUID().IsValid() ||
- module_spec.GetFileSpec().Exists();
+ FileSystem::Instance().Exists(module_spec.GetFileSpec());
}
}
@@ -4282,8 +4426,9 @@ protected:
for (auto &entry : args.entries()) {
if (!entry.ref.empty()) {
- module_spec.GetSymbolFileSpec().SetFile(entry.ref, true,
- FileSpec::Style::native);
+ auto &symbol_file_spec = module_spec.GetSymbolFileSpec();
+ symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(symbol_file_spec);
if (file_option_set) {
module_spec.GetFileSpec() =
m_file_option.GetOptionValue().GetCurrentValue();
@@ -4297,7 +4442,8 @@ protected:
}
ArchSpec arch;
- bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
+ bool symfile_exists =
+ FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec());
if (symfile_exists) {
if (!AddModuleSymbols(target, module_spec, flush, result))
@@ -4369,19 +4515,19 @@ private:
// CommandObjectTargetStopHookAdd
//-------------------------------------------------------------------------
-static OptionDefinition g_target_stop_hook_add_options[] = {
+static constexpr OptionDefinition g_target_stop_hook_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." },
- { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." },
- { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." },
- { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." },
- { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." },
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." },
- { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." },
- { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." },
- { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." },
- { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." },
+ { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
+ { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." },
+ { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." },
+ { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." },
+ { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." },
+ { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." },
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." },
+ { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." },
+ { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." },
+ { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." },
+ { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." },
// clang-format on
};
diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp
index 3be559963df1..e792887d4ff3 100644
--- a/source/Commands/CommandObjectThread.cpp
+++ b/source/Commands/CommandObjectThread.cpp
@@ -9,12 +9,7 @@
#include "CommandObjectThread.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/SourceManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/OptionParser.h"
@@ -37,6 +32,7 @@
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Utility/State.h"
#include "lldb/lldb-private.h"
using namespace lldb;
@@ -247,11 +243,11 @@ protected:
// CommandObjectThreadBacktrace
//-------------------------------------------------------------------------
-static OptionDefinition g_thread_backtrace_options[] = {
+static constexpr OptionDefinition g_thread_backtrace_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "How many frames to display (-1 for all)" },
- { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" },
- { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Show the extended backtrace, if available" }
+ { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many frames to display (-1 for all)" },
+ { LLDB_OPT_SET_1, false, "start", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFrameIndex, "Frame in which to start the backtrace" },
+ { LLDB_OPT_SET_1, false, "extended", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Show the extended backtrace, if available" }
// clang-format on
};
@@ -402,28 +398,26 @@ protected:
enum StepScope { eStepScopeSource, eStepScopeInstruction };
-static OptionEnumValueElement g_tri_running_mode[] = {
+static constexpr OptionEnumValueElement g_tri_running_mode[] = {
{eOnlyThisThread, "this-thread", "Run only this thread"},
{eAllThreads, "all-threads", "Run all threads"},
{eOnlyDuringStepping, "while-stepping",
- "Run only this thread while stepping"},
- {0, nullptr, nullptr}};
+ "Run only this thread while stepping"} };
-static OptionEnumValueElement g_duo_running_mode[] = {
- {eOnlyThisThread, "this-thread", "Run only this thread"},
- {eAllThreads, "all-threads", "Run all threads"},
- {0, nullptr, nullptr}};
+static constexpr OptionEnumValues TriRunningModes() {
+ return OptionEnumValues(g_tri_running_mode);
+}
-static OptionDefinition g_thread_step_scope_options[] = {
+static constexpr OptionDefinition g_thread_step_scope_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information." },
- { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information." },
- { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst." },
- { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over. You can also pass the string 'block' to step to the end of the current block. This is particularly useful in conjunction with --step-target to step through a complex calling sequence." },
- { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, nullptr, 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, nullptr, nullptr, 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, nullptr, nullptr, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into." },
- { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step." }
+ { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information." },
+ { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information." },
+ { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst." },
+ { LLDB_OPT_SET_1, false, "end-linenumber", 'e', OptionParser::eRequiredArgument, nullptr, {}, 1, eArgTypeLineNum, "The line at which to stop stepping - defaults to the next line and only supported for step-in and step-over. You can also pass the string 'block' to step to the end of the current block. This is particularly useful in conjunction with --step-target to step through a complex calling sequence." },
+ { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, nullptr, TriRunningModes(), 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread." },
+ { LLDB_OPT_SET_1, false, "step-over-regexp", 'r', OptionParser::eRequiredArgument, nullptr, {}, 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, nullptr, {}, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into." },
+ { LLDB_OPT_SET_2, false, "python-class", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that will manage this step - only supported for Scripted Step." }
// clang-format on
};
@@ -483,8 +477,7 @@ public:
break;
case 'm': {
- OptionEnumValueElement *enum_values =
- GetDefinitions()[option_idx].enum_values;
+ auto enum_values = GetDefinitions()[option_idx].enum_values;
m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
option_arg, enum_values, eOnlyDuringStepping, error);
} break;
@@ -657,6 +650,7 @@ protected:
bool_stop_other_threads = true;
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
if (m_step_type == eStepTypeInto) {
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
@@ -706,7 +700,7 @@ protected:
abort_other_plans, range,
frame->GetSymbolContext(eSymbolContextEverything),
m_options.m_step_in_target.c_str(), stop_other_threads,
- m_options.m_step_in_avoid_no_debug,
+ new_plan_status, m_options.m_step_in_avoid_no_debug,
m_options.m_step_out_avoid_no_debug);
if (new_plan_sp && !m_options.m_avoid_regexp.empty()) {
@@ -716,7 +710,7 @@ protected:
}
} else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, bool_stop_other_threads);
+ false, abort_other_plans, bool_stop_other_threads, new_plan_status);
} else if (m_step_type == eStepTypeOver) {
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
@@ -725,25 +719,26 @@ protected:
abort_other_plans,
frame->GetSymbolContext(eSymbolContextEverything).line_entry,
frame->GetSymbolContext(eSymbolContextEverything),
- stop_other_threads, m_options.m_step_out_avoid_no_debug);
+ stop_other_threads, new_plan_status,
+ m_options.m_step_out_avoid_no_debug);
else
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, bool_stop_other_threads);
+ true, abort_other_plans, bool_stop_other_threads, new_plan_status);
} else if (m_step_type == eStepTypeTrace) {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, bool_stop_other_threads);
+ false, abort_other_plans, bool_stop_other_threads, new_plan_status);
} else if (m_step_type == eStepTypeTraceOver) {
new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, bool_stop_other_threads);
+ true, abort_other_plans, bool_stop_other_threads, new_plan_status);
} else if (m_step_type == eStepTypeOut) {
new_plan_sp = thread->QueueThreadPlanForStepOut(
abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes,
- eVoteNoOpinion, thread->GetSelectedFrameIndex(),
+ eVoteNoOpinion, thread->GetSelectedFrameIndex(), new_plan_status,
m_options.m_step_out_avoid_no_debug);
} else if (m_step_type == eStepTypeScripted) {
new_plan_sp = thread->QueueThreadPlanForStepScripted(
abort_other_plans, m_options.m_class_name.c_str(),
- bool_stop_other_threads);
+ bool_stop_other_threads, new_plan_status);
} else {
result.AppendError("step type is not supported");
result.SetStatus(eReturnStatusFailed);
@@ -801,7 +796,7 @@ protected:
result.SetStatus(eReturnStatusSuccessContinuingNoResult);
}
} else {
- result.AppendError("Couldn't find thread plan to implement step type.");
+ result.SetError(new_plan_status);
result.SetStatus(eReturnStatusFailed);
}
return result.Succeeded();
@@ -997,12 +992,20 @@ public:
// CommandObjectThreadUntil
//-------------------------------------------------------------------------
-static OptionDefinition g_thread_until_options[] = {
+static constexpr OptionEnumValueElement g_duo_running_mode[] = {
+ {eOnlyThisThread, "this-thread", "Run only this thread"},
+ {eAllThreads, "all-threads", "Run all threads"} };
+
+static constexpr OptionEnumValues DuoRunningModes() {
+ return OptionEnumValues(g_duo_running_mode);
+}
+
+static constexpr OptionDefinition g_thread_until_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0" },
- { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation" },
- { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, g_duo_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one" },
- { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times." }
+ { LLDB_OPT_SET_1, false, "frame", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFrameIndex, "Frame index for until operation - defaults to 0" },
+ { LLDB_OPT_SET_1, false, "thread", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "Thread index for the thread for until operation" },
+ { LLDB_OPT_SET_1, false, "run-mode",'m', OptionParser::eRequiredArgument, nullptr, DuoRunningModes(), 0, eArgTypeRunMode, "Determine how to run other threads while stepping this one" },
+ { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Run until we reach the specified address, or leave the function - can be specified multiple times." }
// clang-format on
};
@@ -1050,8 +1053,7 @@ public:
}
break;
case 'm': {
- OptionEnumValueElement *enum_values =
- GetDefinitions()[option_idx].enum_values;
+ auto enum_values = GetDefinitions()[option_idx].enum_values;
lldb::RunMode run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum(
option_arg, enum_values, eOnlyDuringStepping, error);
@@ -1190,6 +1192,7 @@ protected:
}
ThreadPlanSP new_plan_sp;
+ Status new_plan_status;
if (frame->HasDebugInformation()) {
// Finally we got here... Translate the given line number to a bunch
@@ -1270,13 +1273,19 @@ protected:
new_plan_sp = thread->QueueThreadPlanForStepUntil(
abort_other_plans, &address_list.front(), address_list.size(),
- m_options.m_stop_others, m_options.m_frame_idx);
- // User level plans should be master plans so they can be interrupted
- // (e.g. by hitting a breakpoint) and other plans executed by the user
- // (stepping around the breakpoint) and then a "continue" will resume
- // the original plan.
- new_plan_sp->SetIsMasterPlan(true);
- new_plan_sp->SetOkayToDiscard(false);
+ m_options.m_stop_others, m_options.m_frame_idx, new_plan_status);
+ if (new_plan_sp) {
+ // User level plans should be master plans so they can be interrupted
+ // (e.g. by hitting a breakpoint) and other plans executed by the
+ // user (stepping around the breakpoint) and then a "continue" will
+ // resume the original plan.
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+ } else {
+ result.SetError(new_plan_status);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
} else {
result.AppendErrorWithFormat(
"Frame index %u of thread %u has no debug information.\n",
@@ -1419,10 +1428,10 @@ protected:
// CommandObjectThreadInfo
//-------------------------------------------------------------------------
-static OptionDefinition g_thread_info_options[] = {
+static constexpr OptionDefinition g_thread_info_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "json", 'j', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the thread info in JSON format." },
- { LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display the extended stop info in JSON format." }
+ { LLDB_OPT_SET_ALL, false, "json", 'j', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the thread info in JSON format." },
+ { LLDB_OPT_SET_ALL, false, "stop-info", 's', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the extended stop info in JSON format." }
// clang-format on
};
@@ -1511,12 +1520,57 @@ public:
};
//-------------------------------------------------------------------------
+// CommandObjectThreadException
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadException : public CommandObjectIterateOverThreads {
+ public:
+ CommandObjectThreadException(CommandInterpreter &interpreter)
+ : CommandObjectIterateOverThreads(
+ interpreter, "thread exception",
+ "Display the current exception object for a thread. Defaults to "
+ "the current thread.",
+ "thread exception",
+ eCommandRequiresProcess | eCommandTryTargetAPILock |
+ eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
+
+ ~CommandObjectThreadException() override = default;
+
+ bool HandleOneThread(lldb::tid_t tid, CommandReturnObject &result) override {
+ ThreadSP thread_sp =
+ m_exe_ctx.GetProcessPtr()->GetThreadList().FindThreadByID(tid);
+ if (!thread_sp) {
+ result.AppendErrorWithFormat("thread no longer exists: 0x%" PRIx64 "\n",
+ tid);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ Stream &strm = result.GetOutputStream();
+ ValueObjectSP exception_object_sp = thread_sp->GetCurrentException();
+ if (exception_object_sp) {
+ exception_object_sp->Dump(strm);
+ }
+
+ ThreadSP exception_thread_sp = thread_sp->GetCurrentExceptionBacktrace();
+ if (exception_thread_sp && exception_thread_sp->IsValid()) {
+ const uint32_t num_frames_with_source = 0;
+ const bool stop_format = false;
+ exception_thread_sp->GetStatus(strm, 0, UINT32_MAX,
+ num_frames_with_source, stop_format);
+ }
+
+ return true;
+ }
+};
+
+//-------------------------------------------------------------------------
// CommandObjectThreadReturn
//-------------------------------------------------------------------------
-static OptionDefinition g_thread_return_options[] = {
+static constexpr OptionDefinition g_thread_return_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Return from the innermost expression evaluation." }
+ { LLDB_OPT_SET_ALL, false, "from-expression", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Return from the innermost expression evaluation." }
// clang-format on
};
@@ -1692,13 +1746,13 @@ protected:
// CommandObjectThreadJump
//-------------------------------------------------------------------------
-static OptionDefinition g_thread_jump_options[] = {
+static constexpr OptionDefinition g_thread_jump_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file to jump to." },
- { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number to jump to." },
- { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOffset, "Jumps by a relative line offset from the current line." },
- { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Jumps to a specific address." },
- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allows the PC to leave the current function." }
+ { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file to jump to." },
+ { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number to jump to." },
+ { LLDB_OPT_SET_2, true, "by", 'b', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "Jumps by a relative line offset from the current line." },
+ { LLDB_OPT_SET_3, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Jumps to a specific address." },
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allows the PC to leave the current function." }
// clang-format on
};
@@ -1725,7 +1779,7 @@ public:
switch (short_option) {
case 'f':
- m_filenames.AppendIfUnique(FileSpec(option_arg, false));
+ m_filenames.AppendIfUnique(FileSpec(option_arg));
if (m_filenames.GetSize() > 1)
return Status("only one source file expected.");
break;
@@ -1844,10 +1898,10 @@ protected:
// CommandObjectThreadPlanList
//-------------------------------------------------------------------------
-static OptionDefinition g_thread_plan_list_options[] = {
+static constexpr OptionDefinition g_thread_plan_list_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display more information about the thread plans" },
- { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display internal as well as user thread plans" }
+ { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display more information about the thread plans" },
+ { LLDB_OPT_SET_1, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display internal as well as user thread plans" }
// clang-format on
};
@@ -2055,6 +2109,9 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread(
CommandObjectSP(new CommandObjectThreadUntil(interpreter)));
LoadSubCommand("info",
CommandObjectSP(new CommandObjectThreadInfo(interpreter)));
+ LoadSubCommand(
+ "exception",
+ CommandObjectSP(new CommandObjectThreadException(interpreter)));
LoadSubCommand("step-in",
CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope(
interpreter, "thread step-in",
diff --git a/source/Commands/CommandObjectThread.h b/source/Commands/CommandObjectThread.h
index 589031e0a038..5da31cec58e1 100644
--- a/source/Commands/CommandObjectThread.h
+++ b/source/Commands/CommandObjectThread.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectThread_h_
#define liblldb_CommandObjectThread_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp
index 6bcc334198fc..815e563197b0 100644
--- a/source/Commands/CommandObjectType.cpp
+++ b/source/Commands/CommandObjectType.cpp
@@ -9,16 +9,12 @@
#include "CommandObjectType.h"
-// C Includes
-// C++ Includes
#include <algorithm>
#include <cctype>
#include <functional>
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/IOHandler.h"
-#include "lldb/Core/State.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -39,9 +35,9 @@
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StringList.h"
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
@@ -99,23 +95,23 @@ static bool WarnOnPotentialUnquotedUnsignedType(Args &command,
return false;
}
-static OptionDefinition g_type_summary_add_options[] = {
+static constexpr OptionDefinition g_type_summary_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
- { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type." },
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." },
- { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, inline all child values into summary string." },
- { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If true, omit value names in the summary display." },
- { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." },
- { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command." },
- { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type." },
- { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Input Python code to use for this type manually." },
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines." },
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Do not expand aggregate data types with no children." },
- { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "A name for this summary string." }
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
+ { LLDB_OPT_SET_ALL, false, "no-value", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't show the value, just show the summary, for this type." },
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." },
+ { LLDB_OPT_SET_1, true, "inline-children", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, inline all child values into summary string." },
+ { LLDB_OPT_SET_1, false, "omit-names", 'O', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, omit value names in the summary display." },
+ { LLDB_OPT_SET_2, true, "summary-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSummaryString, "Summary string used to display text and object contents." },
+ { LLDB_OPT_SET_3, false, "python-script", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonScript, "Give a one-liner Python script as part of the command." },
+ { LLDB_OPT_SET_3, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to use for this type." },
+ { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Input Python code to use for this type manually." },
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "expand", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Expand aggregate data types to show children on separate lines." },
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "hide-empty", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Do not expand aggregate data types with no children." },
+ { LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "A name for this summary string." }
// clang-format on
};
@@ -301,15 +297,15 @@ static const char *g_synth_addreader_instructions =
" '''Optional'''\n"
"class synthProvider:\n";
-static OptionDefinition g_type_synth_add_options[] = {
+static constexpr OptionDefinition g_type_synth_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
- { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." },
- { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children." },
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
+ { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Use this Python class to produce synthetic children." },
+ { LLDB_OPT_SET_3, false, "input-python", 'P', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type Python code to generate a class that provides synthetic children." },
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." }
// clang-format on
};
@@ -531,14 +527,14 @@ public:
// CommandObjectTypeFormatAdd
//-------------------------------------------------------------------------
-static OptionDefinition g_type_format_add_options[] = {
+static constexpr OptionDefinition g_type_format_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." },
- { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Format variables as if they were of this type." }
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." },
+ { LLDB_OPT_SET_2, false, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Format variables as if they were of this type." }
// clang-format on
};
@@ -754,11 +750,11 @@ protected:
}
};
-static OptionDefinition g_type_formatter_delete_options[] = {
+static constexpr OptionDefinition g_type_formatter_delete_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete from every category." },
- { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Delete from given category." },
- { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Delete from given language's category." }
+ { LLDB_OPT_SET_1, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete from every category." },
+ { LLDB_OPT_SET_2, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Delete from given category." },
+ { LLDB_OPT_SET_3, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Delete from given language's category." }
// clang-format on
};
@@ -896,9 +892,9 @@ protected:
}
};
-static OptionDefinition g_type_formatter_clear_options[] = {
+static constexpr OptionDefinition g_type_formatter_clear_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Clear every category." }
+ { LLDB_OPT_SET_ALL, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Clear every category." }
// clang-format on
};
@@ -1013,6 +1009,14 @@ public:
"type format clear", "Delete all existing format styles.") {}
};
+
+static constexpr OptionDefinition g_type_formatter_list_options[] = {
+ // clang-format off
+ {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Only show categories matching this filter."},
+ {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Only show the category for a specific language."}
+ // clang-format on
+};
+
template <typename FormatterType>
class CommandObjectTypeFormatterList : public CommandObjectParsed {
typedef typename FormatterType::SharedPointer FormatterSharedPointer;
@@ -1055,13 +1059,7 @@ class CommandObjectTypeFormatterList : public CommandObjectParsed {
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
- static OptionDefinition g_option_table[] = {
- // clang-format off
- {LLDB_OPT_SET_1, false, "category-regex", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Only show categories matching this filter."},
- {LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Only show the category for a specific language."}
- // clang-format on
- };
- return llvm::ArrayRef<OptionDefinition>(g_option_table);
+ return llvm::makeArrayRef(g_type_formatter_list_options);
}
// Instance variables to hold the values for command options.
@@ -1784,10 +1782,10 @@ protected:
// CommandObjectTypeCategoryDefine
//-------------------------------------------------------------------------
-static OptionDefinition g_type_category_define_options[] = {
+static constexpr OptionDefinition g_type_category_define_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "If specified, this category will be created enabled." },
- { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specify the language that this category is supported for." }
+ { LLDB_OPT_SET_ALL, false, "enabled", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If specified, this category will be created enabled." },
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specify the language that this category is supported for." }
// clang-format on
};
@@ -1891,9 +1889,9 @@ protected:
// CommandObjectTypeCategoryEnable
//-------------------------------------------------------------------------
-static OptionDefinition g_type_category_enable_options[] = {
+static constexpr OptionDefinition g_type_category_enable_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." },
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Enable the category for this language." },
// clang-format on
};
@@ -2068,9 +2066,9 @@ protected:
// CommandObjectTypeCategoryDisable
//-------------------------------------------------------------------------
-OptionDefinition g_type_category_disable_options[] = {
+OptionDefinition constexpr g_type_category_disable_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Enable the category for this language." }
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Enable the category for this language." }
// clang-format on
};
@@ -2492,14 +2490,14 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
#endif // LLDB_DISABLE_PYTHON
-static OptionDefinition g_type_filter_add_options[] = {
+static constexpr OptionDefinition g_type_filter_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
- { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
- { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName, "Add this to the given category instead of the default one." },
- { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." },
- { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Type names are actually regular expressions." }
+ { LLDB_OPT_SET_ALL, false, "cascade", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, cascade through typedef chains." },
+ { LLDB_OPT_SET_ALL, false, "skip-pointers", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for pointers-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "skip-references", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Don't use this format for references-to-type objects." },
+ { LLDB_OPT_SET_ALL, false, "category", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Add this to the given category instead of the default one." },
+ { LLDB_OPT_SET_ALL, false, "child", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpressionPath, "Include this expression path in the synthetic view." },
+ { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Type names are actually regular expressions." }
// clang-format on
};
@@ -2747,10 +2745,10 @@ protected:
//----------------------------------------------------------------------
// "type lookup"
//----------------------------------------------------------------------
-static OptionDefinition g_type_lookup_options[] = {
+static constexpr OptionDefinition g_type_lookup_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Display available help for types" },
- { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Which language's types should the search scope be" }
+ { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display available help for types" },
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Which language's types should the search scope be" }
// clang-format on
};
@@ -2909,7 +2907,7 @@ public:
if (StackFrame *frame = m_exe_ctx.GetFramePtr()) {
guessed_language = GuessLanguage(frame);
if (guessed_language != eLanguageTypeUnknown) {
- std::sort(
+ llvm::sort(
languages.begin(), languages.end(),
[guessed_language](Language *lang1, Language *lang2) -> bool {
if (!lang1 || !lang2)
diff --git a/source/Commands/CommandObjectType.h b/source/Commands/CommandObjectType.h
index f2f9ce7c1b61..a9223f842b30 100644
--- a/source/Commands/CommandObjectType.h
+++ b/source/Commands/CommandObjectType.h
@@ -10,11 +10,7 @@
#ifndef liblldb_CommandObjectType_h_
#define liblldb_CommandObjectType_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/Options.h"
diff --git a/source/Commands/CommandObjectVersion.cpp b/source/Commands/CommandObjectVersion.cpp
index 8b1f25bfc521..6155f49e9762 100644
--- a/source/Commands/CommandObjectVersion.cpp
+++ b/source/Commands/CommandObjectVersion.cpp
@@ -9,10 +9,6 @@
#include "CommandObjectVersion.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/lldb-private.h"
diff --git a/source/Commands/CommandObjectVersion.h b/source/Commands/CommandObjectVersion.h
index 5f661cc341c0..d1afafc69bf8 100644
--- a/source/Commands/CommandObjectVersion.h
+++ b/source/Commands/CommandObjectVersion.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectVersion_h_
#define liblldb_CommandObjectVersion_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
namespace lldb_private {
diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp
index 96ae18b35743..d2600a462203 100644
--- a/source/Commands/CommandObjectWatchpoint.cpp
+++ b/source/Commands/CommandObjectWatchpoint.cpp
@@ -10,14 +10,10 @@
#include "CommandObjectWatchpoint.h"
#include "CommandObjectWatchpointCommand.h"
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Breakpoint/WatchpointList.h"
#include "lldb/Core/ValueObject.h"
@@ -142,11 +138,9 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
return false;
wp_ids.push_back(beg);
}
- // It is an error if after the loop, we're still in_range.
- if (in_range)
- return false;
- return true; // Success!
+ // It is an error if after the loop, we're still in_range.
+ return !in_range;
}
//-------------------------------------------------------------------------
@@ -158,11 +152,11 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
//-------------------------------------------------------------------------
#pragma mark List::CommandOptions
-static OptionDefinition g_watchpoint_list_options[] = {
+static constexpr OptionDefinition g_watchpoint_list_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." },
- { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." },
- { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." }
+ { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." },
+ { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." },
+ { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." }
// clang-format on
};
@@ -529,9 +523,9 @@ protected:
//-------------------------------------------------------------------------
#pragma mark Ignore::CommandOptions
-static OptionDefinition g_watchpoint_ignore_options[] = {
+static constexpr OptionDefinition g_watchpoint_ignore_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }
+ { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }
// clang-format on
};
@@ -651,9 +645,9 @@ private:
#pragma mark Modify::CommandOptions
-static OptionDefinition g_watchpoint_modify_options[] = {
+static constexpr OptionDefinition g_watchpoint_modify_options[] = {
// clang-format off
- { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." }
+ { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." }
// clang-format on
};
diff --git a/source/Commands/CommandObjectWatchpoint.h b/source/Commands/CommandObjectWatchpoint.h
index adc0a81fa69c..bc0a2c0c6a7d 100644
--- a/source/Commands/CommandObjectWatchpoint.h
+++ b/source/Commands/CommandObjectWatchpoint.h
@@ -10,11 +10,7 @@
#ifndef liblldb_CommandObjectWatchpoint_h_
#define liblldb_CommandObjectWatchpoint_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/OptionGroupWatchpoint.h"
#include "lldb/Interpreter/Options.h"
diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp
index 74015a433831..3a9ebfbd15d0 100644
--- a/source/Commands/CommandObjectWatchpointCommand.cpp
+++ b/source/Commands/CommandObjectWatchpointCommand.cpp
@@ -7,24 +7,20 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "CommandObjectWatchpoint.h"
#include "CommandObjectWatchpointCommand.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/IOHandler.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -38,20 +34,23 @@ using namespace lldb_private;
// language to lldb and have it pickable here without having to change this
// enumeration by hand and rebuild lldb proper.
-static OptionEnumValueElement g_script_option_enumeration[4] = {
+static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
{eScriptLanguageNone, "command",
"Commands are in the lldb command interpreter language"},
{eScriptLanguagePython, "python", "Commands are in the Python language."},
{eSortOrderByName, "default-script",
- "Commands are in the default scripting language."},
- {0, nullptr, nullptr}};
+ "Commands are in the default scripting language."} };
-static OptionDefinition g_watchpoint_command_add_options[] = {
+static constexpr OptionEnumValues ScriptOptionEnum() {
+ return OptionEnumValues(g_script_option_enumeration);
+}
+
+static constexpr OptionDefinition g_watchpoint_command_add_options[] = {
// clang-format off
- { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner, "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
- { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Specify whether watchpoint command execution should terminate on error." },
- { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." },
- { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, 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." }
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether watchpoint command execution should terminate on error." },
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." },
+ { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 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." }
// clang-format on
};
diff --git a/source/Commands/CommandObjectWatchpointCommand.h b/source/Commands/CommandObjectWatchpointCommand.h
index 63152f2f68a6..e079220d0efe 100644
--- a/source/Commands/CommandObjectWatchpointCommand.h
+++ b/source/Commands/CommandObjectWatchpointCommand.h
@@ -10,11 +10,7 @@
#ifndef liblldb_CommandObjectWatchpointCommand_h_
#define liblldb_CommandObjectWatchpointCommand_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/Options.h"
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp
index f183245f7d36..a4dc364b701b 100644
--- a/source/Core/Address.cpp
+++ b/source/Core/Address.cpp
@@ -10,43 +10,43 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h" // for ModuleList
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
-#include "lldb/Symbol/Declaration.h" // for Declaration
-#include "lldb/Symbol/LineEntry.h" // for LineEntry
+#include "lldb/Symbol/Declaration.h"
+#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Symbol.h" // for Symbol
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/Symtab.h" // for Symtab
-#include "lldb/Symbol/Type.h" // for Type
+#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextScope
+#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/DataExtractor.h" // for DataExtractor
-#include "lldb/Utility/Endian.h" // for InlHostByteOrder
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/Utility/Stream.h" // for Stream
-#include "lldb/Utility/StreamString.h" // for StreamString
-
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StreamString.h"
+
+#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
+#include "llvm/Support/Compiler.h"
-#include <cstdint> // for uint8_t, uint32_t
-#include <memory> // for shared_ptr, operator!=
-#include <vector> // for vector
+#include <cstdint>
+#include <memory>
+#include <vector>
-#include <assert.h> // for assert
-#include <inttypes.h> // for PRIu64, PRIx64
-#include <string.h> // for size_t, strlen
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
namespace lldb_private {
class CompileUnit;
@@ -779,8 +779,9 @@ bool Address::SectionWasDeletedPrivate() const {
m_section_wp.owner_before(empty_section_wp);
}
-uint32_t Address::CalculateSymbolContext(SymbolContext *sc,
- uint32_t resolve_scope) const {
+uint32_t
+Address::CalculateSymbolContext(SymbolContext *sc,
+ SymbolContextItem resolve_scope) const {
sc->Clear(false);
// Absolute addresses don't have enough information to reconstruct even their
// target.
@@ -987,8 +988,10 @@ AddressClass Address::GetAddressClass() const {
if (module_sp) {
ObjectFile *obj_file = module_sp->GetObjectFile();
if (obj_file) {
- // Give the symbol vendor a chance to add to the unified section list.
- module_sp->GetSymbolVendor();
+ // Give the symbol vendor a chance to add to the unified section list
+ // and to symtab from symbol file
+ if (SymbolVendor *vendor = module_sp->GetSymbolVendor())
+ vendor->GetSymtab();
return obj_file->GetAddressClass(GetFileAddress());
}
}
diff --git a/source/Core/AddressRange.cpp b/source/Core/AddressRange.cpp
index e125b693d6f6..1afe4fa223db 100644
--- a/source/Core/AddressRange.cpp
+++ b/source/Core/AddressRange.cpp
@@ -10,16 +10,16 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
+#include "lldb/lldb-defines.h"
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
+#include "llvm/Support/Compiler.h"
-#include <memory> // for shared_ptr
+#include <memory>
-#include <inttypes.h> // for PRIx64
+#include <inttypes.h>
namespace lldb_private {
class SectionList;
diff --git a/source/Core/AddressResolverFileLine.cpp b/source/Core/AddressResolverFileLine.cpp
index 798a9b50079e..203ab2787fe3 100644
--- a/source/Core/AddressResolverFileLine.cpp
+++ b/source/Core/AddressResolverFileLine.cpp
@@ -9,21 +9,21 @@
#include "lldb/Core/AddressResolverFileLine.h"
-#include "lldb/Core/Address.h" // for Address
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/LineEntry.h" // for LineEntry
+#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet, LIB...
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "lldb/lldb-enumerations.h" // for SymbolContextItem::eSymbolCon...
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
-#include <inttypes.h> // for PRIx64
-#include <vector> // for vector
+#include <inttypes.h>
+#include <vector>
using namespace lldb;
using namespace lldb_private;
@@ -78,8 +78,8 @@ AddressResolverFileLine::SearchCallback(SearchFilter &filter,
return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth AddressResolverFileLine::GetDepth() {
- return Searcher::eDepthCompUnit;
+lldb::SearchDepth AddressResolverFileLine::GetDepth() {
+ return lldb::eSearchDepthCompUnit;
}
void AddressResolverFileLine::GetDescription(Stream *s) {
diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp
index c3dab6d10810..7683e391e0cf 100644
--- a/source/Core/AddressResolverName.cpp
+++ b/source/Core/AddressResolverName.cpp
@@ -9,25 +9,25 @@
#include "lldb/Core/AddressResolverName.h"
-#include "lldb/Core/Address.h" // for Address, operator==
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet, LIB...
-#include "lldb/Utility/Stream.h" // for Stream
-#include "lldb/lldb-enumerations.h" // for SymbolType::eSymbolTypeCode
-#include "lldb/lldb-forward.h" // for ModuleSP
-#include "lldb/lldb-types.h" // for addr_t
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/StringRef.h"
-#include <memory> // for shared_ptr
-#include <string> // for string
-#include <vector> // for vector
+#include <memory>
+#include <string>
+#include <vector>
-#include <stdint.h> // for uint32_t
+#include <stdint.h>
using namespace lldb;
using namespace lldb_private;
@@ -186,8 +186,8 @@ AddressResolverName::SearchCallback(SearchFilter &filter,
return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth AddressResolverName::GetDepth() {
- return Searcher::eDepthModule;
+lldb::SearchDepth AddressResolverName::GetDepth() {
+ return lldb::eSearchDepthModule;
}
void AddressResolverName::GetDescription(Stream *s) {
diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt
index 927a0dcc2ec1..15f2dcf6ed99 100644
--- a/source/Core/CMakeLists.txt
+++ b/source/Core/CMakeLists.txt
@@ -13,7 +13,6 @@ add_lldb_library(lldbCore
AddressResolver.cpp
AddressResolverFileLine.cpp
AddressResolverName.cpp
- Broadcaster.cpp
Communication.cpp
Debugger.cpp
Disassembler.cpp
@@ -21,24 +20,21 @@ add_lldb_library(lldbCore
DumpRegisterValue.cpp
DynamicLoader.cpp
EmulateInstruction.cpp
- Event.cpp
FileLineResolver.cpp
FileSpecList.cpp
FormatEntity.cpp
+ Highlighter.cpp
IOHandler.cpp
- Listener.cpp
Mangled.cpp
Module.cpp
ModuleChild.cpp
ModuleList.cpp
Opcode.cpp
PluginManager.cpp
- RegisterValue.cpp
- Scalar.cpp
+ RichManglingContext.cpp
SearchFilter.cpp
Section.cpp
SourceManager.cpp
- State.cpp
StreamAsynchronousIO.cpp
StreamFile.cpp
UserSettingsController.cpp
@@ -81,3 +77,7 @@ add_lldb_library(lldbCore
# Needed to properly resolve references in a debug build.
# TODO: Remove once we have better layering
set_target_properties(lldbCore PROPERTIES LINK_INTERFACE_MULTIPLICITY 4)
+
+if (NOT LLDB_DISABLE_LIBEDIT)
+ target_include_directories(lldbCore PRIVATE ${libedit_INCLUDE_DIRS})
+endif()
diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp
index 5ca338639de0..afdabc0c7ce5 100644
--- a/source/Core/Communication.cpp
+++ b/source/Core/Communication.cpp
@@ -9,28 +9,28 @@
#include "lldb/Core/Communication.h"
-#include "lldb/Core/Event.h"
-#include "lldb/Core/Listener.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Utility/Connection.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/Listener.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for LogIfAnyCategoriesSet, LIBLLDB...
-#include "lldb/Utility/Status.h" // for Status
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/Status.h"
-#include "llvm/ADT/None.h" // for None
-#include "llvm/ADT/Optional.h" // for Optional
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/Support/Compiler.h"
-#include <algorithm> // for min
-#include <chrono> // for duration, seconds
+#include <algorithm>
+#include <chrono>
#include <cstring>
-#include <memory> // for shared_ptr
+#include <memory>
-#include <errno.h> // for EIO
-#include <inttypes.h> // for PRIu64
-#include <stdio.h> // for snprintf
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp
index 972d0bc0a6d7..765b59c8865e 100644
--- a/source/Core/Debugger.cpp
+++ b/source/Core/Debugger.cpp
@@ -9,67 +9,71 @@
#include "lldb/Core/Debugger.h"
-#include "lldb/Breakpoint/Breakpoint.h" // for Breakpoint, Brea...
-#include "lldb/Core/Event.h" // for Event, EventData...
+#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/FormatEntity.h"
-#include "lldb/Core/Listener.h" // for Listener
-#include "lldb/Core/Mangled.h" // for Mangled
-#include "lldb/Core/ModuleList.h" // for Mangled
+#include "lldb/Core/Mangled.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamAsynchronousIO.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Expression/REPL.h"
-#include "lldb/Host/File.h" // for File, File::kInv...
+#include "lldb/Host/File.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Terminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/OptionValue.h" // for OptionValue, Opt...
+#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueSInt64.h"
#include "lldb/Interpreter/OptionValueString.h"
-#include "lldb/Interpreter/Property.h" // for PropertyDefinition
-#include "lldb/Interpreter/ScriptInterpreter.h" // for ScriptInterpreter
+#include "lldb/Interpreter/Property.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Target/ThreadList.h" // for ThreadList
+#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/AnsiTerminal.h"
-#include "lldb/Utility/Log.h" // for LLDB_LOG_OPTION_...
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/Listener.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Reproducer.h"
+#include "lldb/Utility/State.h"
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamCallback.h"
#include "lldb/Utility/StreamString.h"
#if defined(_WIN32)
-#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
+#include "lldb/Host/windows/PosixApi.h"
+#include "lldb/Host/windows/windows.h"
#endif
-#include "llvm/ADT/None.h" // for None
-#include "llvm/ADT/STLExtras.h" // for make_unique
+#include "llvm/ADT/None.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator.h" // for iterator_facade_...
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Threading.h"
-#include "llvm/Support/raw_ostream.h" // for raw_fd_ostream
+#include "llvm/Support/raw_ostream.h"
-#include <list> // for list
-#include <memory> // for make_shared
+#include <list>
+#include <memory>
#include <mutex>
-#include <set> // for set
-#include <stdio.h> // for size_t, NULL
-#include <stdlib.h> // for getenv
-#include <string.h> // for strcmp
-#include <string> // for string
-#include <system_error> // for error_code
+#include <set>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <system_error>
namespace lldb_private {
class Address;
@@ -89,7 +93,7 @@ static std::recursive_mutex *g_debugger_list_mutex_ptr =
static DebuggerList *g_debugger_list_ptr =
nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain
-OptionEnumValueElement g_show_disassembly_enum_values[] = {
+static constexpr OptionEnumValueElement g_show_disassembly_enum_values[] = {
{Debugger::eStopDisassemblyTypeNever, "never",
"Never show disassembly when displaying a stop context."},
{Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo",
@@ -98,16 +102,14 @@ OptionEnumValueElement g_show_disassembly_enum_values[] = {
"Show disassembly when there is no source information, or the source file "
"is missing when displaying a stop context."},
{Debugger::eStopDisassemblyTypeAlways, "always",
- "Always show disassembly when displaying a stop context."},
- {0, nullptr, nullptr}};
+ "Always show disassembly when displaying a stop context."} };
-OptionEnumValueElement g_language_enumerators[] = {
+static constexpr OptionEnumValueElement g_language_enumerators[] = {
{eScriptLanguageNone, "none", "Disable scripting languages."},
{eScriptLanguagePython, "python",
"Select python as the default scripting language."},
{eScriptLanguageDefault, "default",
- "Select the lldb default as the default scripting language."},
- {0, nullptr, nullptr}};
+ "Select the lldb default as the default scripting language."} };
#define MODULE_WITH_FUNC \
"{ " \
@@ -119,9 +121,12 @@ OptionEnumValueElement g_language_enumerators[] = {
"${module.file.basename}{`${function.name-without-args}" \
"{${frame.no-debug}${function.pc-offset}}}}"
-#define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}"
+#define FILE_AND_LINE \
+ "{ at ${line.file.basename}:${line.number}{:${line.column}}}"
#define IS_OPTIMIZED "{${function.is-optimized} [opt]}"
+#define IS_ARTIFICIAL "{${frame.is-artificial} [artificial]}"
+
#define DEFAULT_THREAD_FORMAT \
"thread #${thread.index}: tid = ${thread.id%tid}" \
"{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE \
@@ -146,11 +151,11 @@ OptionEnumValueElement g_language_enumerators[] = {
#define DEFAULT_FRAME_FORMAT \
"frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC FILE_AND_LINE \
- IS_OPTIMIZED "\\n"
+ IS_OPTIMIZED IS_ARTIFICIAL "\\n"
#define DEFAULT_FRAME_FORMAT_NO_ARGS \
"frame #${frame.index}: ${frame.pc}" MODULE_WITH_FUNC_NO_ARGS FILE_AND_LINE \
- IS_OPTIMIZED "\\n"
+ IS_OPTIMIZED IS_ARTIFICIAL "\\n"
// Three parts to this disassembly format specification:
// 1. If this is a new function/symbol (no previous symbol/function), print
@@ -162,8 +167,8 @@ OptionEnumValueElement g_language_enumerators[] = {
// address <+offset>:
#define DEFAULT_DISASSEMBLY_FORMAT \
"{${function.initial-function}{${module.file.basename}`}{${function.name-" \
- "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${" \
- "function.name-without-args}}:\n}{${current-pc-arrow} " \
+ "without-args}}:\\n}{${function.changed}\\n{${module.file.basename}`}{${" \
+ "function.name-without-args}}:\\n}{${current-pc-arrow} " \
"}${addr-file-or-load}{ " \
"<${function.concrete-only-addr-offset-no-padding}>}: "
@@ -177,10 +182,7 @@ OptionEnumValueElement g_language_enumerators[] = {
// args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-
// without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}:
-#define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}"
-#define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}"
-
-static OptionEnumValueElement s_stop_show_column_values[] = {
+static constexpr OptionEnumValueElement s_stop_show_column_values[] = {
{eStopShowColumnAnsiOrCaret, "ansi-or-caret",
"Highlight the stop column with ANSI terminal codes when color/ANSI mode "
"is enabled; otherwise, fall back to using a text-only caret (^) as if "
@@ -192,98 +194,95 @@ static OptionEnumValueElement s_stop_show_column_values[] = {
"Highlight the stop column with a caret character (^) underneath the stop "
"column. This method introduces a new line in source listings that "
"display thread stop locations."},
- {eStopShowColumnNone, "none", "Do not highlight the stop column."},
- {0, nullptr, nullptr}};
+ {eStopShowColumnNone, "none", "Do not highlight the stop column."}};
-static PropertyDefinition g_properties[] = {
- {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
+static constexpr PropertyDefinition g_properties[] = {
+ {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, {},
"If true all confirmation prompts will receive their default reply."},
{"disassembly-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_DISASSEMBLY_FORMAT, nullptr,
+ DEFAULT_DISASSEMBLY_FORMAT, {},
"The default disassembly format "
"string to use when disassembling "
"instruction sequences."},
{"frame-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_FRAME_FORMAT, nullptr,
+ DEFAULT_FRAME_FORMAT, {},
"The default frame format string to use "
"when displaying stack frame information "
"for threads."},
- {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, nullptr,
+ {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, {},
"Notify the user explicitly if an expression returns void (default: "
"false)."},
{"prompt", OptionValue::eTypeString, true,
- OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ",
- nullptr, "The debugger command line prompt displayed for the user."},
+ OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", {},
+ "The debugger command line prompt displayed for the user."},
{"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython,
- nullptr, g_language_enumerators,
+ nullptr, OptionEnumValues(g_language_enumerators),
"The script language to be used for evaluating user-written scripts."},
- {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr,
- nullptr,
+ {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, {},
"The number of disassembly lines to show when displaying a "
"stopped context."},
{"stop-disassembly-display", OptionValue::eTypeEnum, true,
Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr,
- g_show_disassembly_enum_values,
+ OptionEnumValues(g_show_disassembly_enum_values),
"Control when to display disassembly when displaying a stopped context."},
- {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr,
- nullptr,
+ {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, {},
"The number of sources lines to display that come after the "
"current source line when displaying a stopped context."},
- {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr,
- nullptr,
+ {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, {},
"The number of sources lines to display that come before the "
"current source line when displaying a stopped context."},
+ {"highlight-source", OptionValue::eTypeBoolean, true, true, nullptr, {},
+ "If true, LLDB will highlight the displayed source code."},
{"stop-show-column", OptionValue::eTypeEnum, false,
- eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values,
+ eStopShowColumnAnsiOrCaret, nullptr, OptionEnumValues(s_stop_show_column_values),
"If true, LLDB will use the column information from the debug info to "
"mark the current position when displaying a stopped context."},
- {"stop-show-column-ansi-prefix", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX, nullptr,
+ {"stop-show-column-ansi-prefix", OptionValue::eTypeString, true, 0,
+ "${ansi.underline}", {},
"When displaying the column marker in a color-enabled (i.e. ANSI) "
"terminal, use the ANSI terminal code specified in this format at the "
"immediately before the column to be marked."},
- {"stop-show-column-ansi-suffix", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX, nullptr,
+ {"stop-show-column-ansi-suffix", OptionValue::eTypeString, true, 0,
+ "${ansi.normal}", {},
"When displaying the column marker in a color-enabled (i.e. ANSI) "
"terminal, use the ANSI terminal code specified in this format "
"immediately after the column to be marked."},
- {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr,
+ {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, {},
"The maximum number of columns to use for displaying text."},
{"thread-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_THREAD_FORMAT, nullptr,
+ DEFAULT_THREAD_FORMAT, {},
"The default thread format string to use "
"when displaying thread information."},
{"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_THREAD_STOP_FORMAT, nullptr,
+ DEFAULT_THREAD_STOP_FORMAT, {},
"The default thread format "
"string to use when displaying thread "
"information as part of the stop display."},
- {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "Whether to use an external editor or not."},
- {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, {},
+ "Whether to use an external editor or not."},
+ {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, {},
"Whether to use Ansi color codes or not."},
{"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
+ {},
"If true, LLDB will automatically display small structs in "
"one-liner format (default: true)."},
- {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, {},
"If true, LLDB will auto indent/outdent code. Currently only supported in "
"the REPL (default: true)."},
- {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+ {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, {},
"If true, LLDB will print the values of variables declared in an "
"expression. Currently only supported in the REPL (default: true)."},
- {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, nullptr,
+ {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, {},
"The tab size to use when indenting code in multi-line input mode "
"(default: 4)."},
{"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
+ {},
"If true, LLDB will automatically escape non-printable and "
"escape characters when formatting strings."},
{"frame-format-unique", OptionValue::eTypeFormatEntity, true, 0,
- DEFAULT_FRAME_FORMAT_NO_ARGS, nullptr,
+ DEFAULT_FRAME_FORMAT_NO_ARGS, {},
"The default frame format string to use when displaying stack frame"
- "information for threads from thread backtrace unique."},
- {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
+ "information for threads from thread backtrace unique."}};
enum {
ePropertyAutoConfirm = 0,
@@ -296,6 +295,7 @@ enum {
ePropertyStopDisassemblyDisplay,
ePropertyStopLineCountAfter,
ePropertyStopLineCountBefore,
+ ePropertyHighlightSource,
ePropertyStopShowColumn,
ePropertyStopShowColumnAnsiPrefix,
ePropertyStopShowColumnAnsiSuffix,
@@ -413,6 +413,11 @@ void Debugger::SetPrompt(llvm::StringRef p) {
GetCommandInterpreter().UpdatePrompt(new_prompt);
}
+llvm::StringRef Debugger::GetReproducerPath() const {
+ auto &r = repro::Reproducer::Instance();
+ return r.GetReproducerPath().GetCString();
+}
+
const FormatEntity::Entry *Debugger::GetThreadFormat() const {
const uint32_t idx = ePropertyThreadFormat;
return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
@@ -470,20 +475,26 @@ bool Debugger::SetUseColor(bool b) {
return ret;
}
+bool Debugger::GetHighlightSource() const {
+ const uint32_t idx = ePropertyHighlightSource;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value);
+}
+
StopShowColumn Debugger::GetStopShowColumn() const {
const uint32_t idx = ePropertyStopShowColumn;
return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration(
nullptr, idx, g_properties[idx].default_uint_value);
}
-const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiPrefix() const {
+llvm::StringRef Debugger::GetStopShowColumnAnsiPrefix() const {
const uint32_t idx = ePropertyStopShowColumnAnsiPrefix;
- return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
+ return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
}
-const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiSuffix() const {
+llvm::StringRef Debugger::GetStopShowColumnAnsiSuffix() const {
const uint32_t idx = ePropertyStopShowColumnAnsiSuffix;
- return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx);
+ return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, "");
}
uint32_t Debugger::GetStopSourceLineCount(bool before) const {
@@ -600,16 +611,16 @@ bool Debugger::LoadPlugin(const FileSpec &spec, Status &error) {
return false;
}
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &file_spec) {
+ llvm::StringRef path) {
Status error;
static ConstString g_dylibext(".dylib");
static ConstString g_solibext(".so");
if (!baton)
- return FileSpec::eEnumerateDirectoryResultQuit;
+ return FileSystem::eEnumerateDirectoryResultQuit;
Debugger *debugger = (Debugger *)baton;
@@ -620,18 +631,18 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
// file type information.
if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
ft == fs::file_type::type_unknown) {
- FileSpec plugin_file_spec(file_spec);
- plugin_file_spec.ResolvePath();
+ FileSpec plugin_file_spec(path);
+ FileSystem::Instance().Resolve(plugin_file_spec);
if (plugin_file_spec.GetFileNameExtension() != g_dylibext &&
plugin_file_spec.GetFileNameExtension() != g_solibext) {
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
Status plugin_load_error;
debugger->LoadPlugin(plugin_file_spec, plugin_load_error);
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} else if (ft == fs::file_type::directory_file ||
ft == fs::file_type::symlink_file ||
ft == fs::file_type::type_unknown) {
@@ -639,10 +650,10 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
// also do this for unknown as sometimes the directory enumeration might be
// enumerating a file system that doesn't have correct file type
// information.
- return FileSpec::eEnumerateDirectoryResultEnter;
+ return FileSystem::eEnumerateDirectoryResultEnter;
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
void Debugger::InstanceInitialize() {
@@ -651,16 +662,20 @@ void Debugger::InstanceInitialize() {
const bool find_other = true;
char dir_path[PATH_MAX];
if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
- if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
- FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
- find_other, LoadPluginCallback, this);
+ if (FileSystem::Instance().Exists(dir_spec) &&
+ dir_spec.GetPath(dir_path, sizeof(dir_path))) {
+ FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
+ find_files, find_other,
+ LoadPluginCallback, this);
}
}
if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
- if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
- FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
- find_other, LoadPluginCallback, this);
+ if (FileSystem::Instance().Exists(dir_spec) &&
+ dir_spec.GetPath(dir_path, sizeof(dir_path))) {
+ FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
+ find_files, find_other,
+ LoadPluginCallback, this);
}
}
@@ -795,6 +810,15 @@ Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton)
const char *term = getenv("TERM");
if (term && !strcmp(term, "dumb"))
SetUseColor(false);
+ // Turn off use-color if we don't write to a terminal with color support.
+ if (!m_output_file_sp->GetFile().GetIsTerminalWithColors())
+ SetUseColor(false);
+
+#if defined(_WIN32) && defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+ // Enabling use of ANSI color codes because LLDB is using them to highlight
+ // text.
+ llvm::sys::Process::UseANSIEscapeCodes(true);
+#endif
}
Debugger::~Debugger() { Clear(); }
@@ -1068,7 +1092,8 @@ void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in,
}
}
-void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
+void Debugger::PushIOHandler(const IOHandlerSP &reader_sp,
+ bool cancel_top_handler) {
if (!reader_sp)
return;
@@ -1089,7 +1114,8 @@ void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) {
// this new input reader take over
if (top_reader_sp) {
top_reader_sp->Deactivate();
- top_reader_sp->Cancel();
+ if (cancel_top_handler)
+ top_reader_sp->Cancel();
}
}
diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp
index d41a19465280..a34b8038c589 100644
--- a/source/Core/Disassembler.cpp
+++ b/source/Core/Disassembler.cpp
@@ -9,14 +9,14 @@
#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/Mangled.h" // for Mangled, Mangled...
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h" // for ModuleList
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/SourceManager.h" // for SourceManager
+#include "lldb/Core/SourceManager.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Interpreter/OptionValueArray.h"
@@ -25,31 +25,31 @@
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/Symbol.h" // for Symbol
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h" // for Thread
+#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Status.h"
-#include "lldb/Utility/Stream.h" // for Stream
-#include "lldb/Utility/StreamString.h" // for StreamString
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
-#include "lldb/lldb-private-enumerations.h" // for InstructionType:...
-#include "lldb/lldb-private-interfaces.h" // for DisassemblerCrea...
-#include "lldb/lldb-private-types.h" // for RegisterInfo
-#include "llvm/ADT/Triple.h" // for Triple, Triple::...
-#include "llvm/Support/Compiler.h" // for LLVM_PRETTY_FUNC...
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-private-interfaces.h"
+#include "lldb/lldb-private-types.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
-#include <cstdint> // for uint32_t, UINT32...
+#include <cstdint>
#include <cstring>
-#include <utility> // for pair
+#include <utility>
-#include <assert.h> // for assert
+#include <assert.h>
#define DEFAULT_DISASM_BYTE_SIZE 32
@@ -429,9 +429,9 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
const Address &addr = inst->GetAddress();
ModuleSP module_sp(addr.GetModule());
if (module_sp) {
- const uint32_t resolve_mask = eSymbolContextFunction |
- eSymbolContextSymbol |
- eSymbolContextLineEntry;
+ const SymbolContextItem resolve_mask = eSymbolContextFunction |
+ eSymbolContextSymbol |
+ eSymbolContextLineEntry;
uint32_t resolved_mask =
module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc);
if (resolved_mask) {
@@ -452,8 +452,7 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
if (mixed_source_and_assembly && sc.line_entry.IsValid()) {
if (sc.symbol != previous_symbol) {
SourceLine decl_line = GetFunctionDeclLineEntry(sc);
- if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) ==
- false)
+ if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line))
AddLineToSourceLineTables(decl_line, source_lines_seen);
}
if (sc.line_entry.IsValid()) {
@@ -461,8 +460,7 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
this_line.file = sc.line_entry.file;
this_line.line = sc.line_entry.line;
this_line.column = sc.line_entry.column;
- if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) ==
- false)
+ if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line))
AddLineToSourceLineTables(this_line, source_lines_seen);
}
}
@@ -506,8 +504,8 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
previous_symbol = sc.symbol;
if (sc.function && sc.line_entry.IsValid()) {
LineEntry prologue_end_line = sc.line_entry;
- if (ElideMixedSourceAndDisassemblyLine(
- exe_ctx, sc, prologue_end_line) == false) {
+ if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
+ prologue_end_line)) {
FileSpec func_decl_file;
uint32_t func_decl_line;
sc.function->GetStartLineSourceInfo(func_decl_file,
@@ -547,8 +545,8 @@ bool Disassembler::PrintInstructions(Disassembler *disasm_ptr,
this_line.file = sc.line_entry.file;
this_line.line = sc.line_entry.line;
- if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
- this_line) == false) {
+ if (!ElideMixedSourceAndDisassemblyLine(exe_ctx, sc,
+ this_line)) {
// Only print this source line if it is different from the
// last source line we printed. There may have been inlined
// functions between these lines that we elided, resulting in
@@ -934,7 +932,7 @@ bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) {
out_stream->Printf("Instruction::TestEmulation: Missing file_name.");
return false;
}
- FILE *test_file = FileSystem::Fopen(file_name, "r");
+ FILE *test_file = FileSystem::Instance().Fopen(file_name, "r");
if (!test_file) {
out_stream->Printf(
"Instruction::TestEmulation: Attempt to open test file failed.");
diff --git a/source/Core/DumpDataExtractor.cpp b/source/Core/DumpDataExtractor.cpp
index 049f4d3805a1..43a026d0dcb2 100644
--- a/source/Core/DumpDataExtractor.cpp
+++ b/source/Core/DumpDataExtractor.cpp
@@ -9,12 +9,12 @@
#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-forward.h" // for TargetSP, DisassemblerSP
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
-#include "lldb/Core/ModuleList.h" // for ModuleList
+#include "lldb/Core/ModuleList.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ExecutionContextScope.h"
@@ -23,22 +23,22 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Stream.h"
-#include "clang/AST/ASTContext.h" // for ASTContext
-#include "clang/AST/CanonicalType.h" // for CanQualType
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CanonicalType.h"
-#include "llvm/ADT/APFloat.h" // for APFloat, APFloatBase:...
-#include "llvm/ADT/APInt.h" // for APInt
-#include "llvm/ADT/ArrayRef.h" // for ArrayRef
-#include "llvm/ADT/SmallVector.h" // for SmallVector
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
-#include <limits> // for numeric_limits, numer...
-#include <memory> // for shared_ptr
-#include <string> // for string, basic_string
+#include <limits>
+#include <memory>
+#include <string>
-#include <assert.h> // for assert
-#include <ctype.h> // for isprint
-#include <inttypes.h> // for PRIu64, PRIx64, PRIX64
-#include <math.h> // for ldexpf
+#include <assert.h>
+#include <ctype.h>
+#include <inttypes.h>
+#include <math.h>
#include <bitset>
#include <sstream>
diff --git a/source/Core/DumpRegisterValue.cpp b/source/Core/DumpRegisterValue.cpp
index 99334ca78a6d..d7196a585667 100644
--- a/source/Core/DumpRegisterValue.cpp
+++ b/source/Core/DumpRegisterValue.cpp
@@ -9,8 +9,8 @@
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-private-types.h"
diff --git a/source/Core/DynamicLoader.cpp b/source/Core/DynamicLoader.cpp
index 16f1ffca1a20..72ee3cfd6d5b 100644
--- a/source/Core/DynamicLoader.cpp
+++ b/source/Core/DynamicLoader.cpp
@@ -10,22 +10,22 @@
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h" // for ModuleList
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Symbol/ObjectFile.h" // for ObjectFile
+#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/lldb-private-interfaces.h" // for DynamicLoaderCreateInstance
+#include "lldb/Utility/ConstString.h"
+#include "lldb/lldb-private-interfaces.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
-#include <memory> // for shared_ptr, unique_ptr
+#include <memory>
-#include <assert.h> // for assert
+#include <assert.h>
using namespace lldb;
using namespace lldb_private;
@@ -81,7 +81,7 @@ ModuleSP DynamicLoader::GetTargetExecutable() {
ModuleSP executable = target.GetExecutableModule();
if (executable) {
- if (executable->GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
ModuleSpec module_spec(executable->GetFileSpec(),
executable->GetArchitecture());
auto module_sp = std::make_shared<Module>(module_spec);
@@ -101,8 +101,7 @@ ModuleSP DynamicLoader::GetTargetExecutable() {
if (executable.get() != target.GetExecutableModulePointer()) {
// Don't load dependent images since we are in dyld where we will
// know and find out about all images that are loaded
- const bool get_dependent_images = false;
- target.SetExecutableModule(executable, get_dependent_images);
+ target.SetExecutableModule(executable, eLoadDependentsNo);
}
}
}
@@ -196,9 +195,8 @@ ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
if (error.Success() && memory_info.GetMapped() &&
memory_info.GetRange().GetRangeBase() == base_addr &&
!(memory_info.GetName().IsEmpty())) {
- ModuleSpec new_module_spec(
- FileSpec(memory_info.GetName().AsCString(), false),
- target.GetArchitecture());
+ ModuleSpec new_module_spec(FileSpec(memory_info.GetName().AsCString()),
+ target.GetArchitecture());
if ((module_sp = modules.FindFirstModule(new_module_spec))) {
UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
diff --git a/source/Core/EmulateInstruction.cpp b/source/Core/EmulateInstruction.cpp
index 469022119c9e..0fcb2eb7e8ce 100644
--- a/source/Core/EmulateInstruction.cpp
+++ b/source/Core/EmulateInstruction.cpp
@@ -12,27 +12,27 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/StackFrame.h" // for StackFrame
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
-#include "lldb/Utility/Stream.h" // for Stream, Stream::::eBinary
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "lldb/lldb-forward.h" // for ProcessSP
-#include "lldb/lldb-private-interfaces.h" // for EmulateInstructionCreateIn...
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-interfaces.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#include <cstring>
-#include <memory> // for shared_ptr
+#include <memory>
-#include <inttypes.h> // for PRIx64, PRId64, PRIu64
-#include <stdio.h> // for stdout
+#include <inttypes.h>
+#include <stdio.h>
namespace lldb_private {
class Target;
diff --git a/source/Core/FileLineResolver.cpp b/source/Core/FileLineResolver.cpp
index 7f0f440252e7..0f4120711b24 100644
--- a/source/Core/FileLineResolver.cpp
+++ b/source/Core/FileLineResolver.cpp
@@ -9,14 +9,13 @@
#include "lldb/Core/FileLineResolver.h"
-// Project includes
-#include "lldb/Core/FileSpecList.h" // for FileSpecList
+#include "lldb/Core/FileSpecList.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/LineTable.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Stream.h"
-#include <string> // for string
+#include <string>
namespace lldb_private {
class Address;
@@ -68,8 +67,8 @@ FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context,
return Searcher::eCallbackReturnContinue;
}
-Searcher::Depth FileLineResolver::GetDepth() {
- return Searcher::eDepthCompUnit;
+lldb::SearchDepth FileLineResolver::GetDepth() {
+ return lldb::eSearchDepthCompUnit;
}
void FileLineResolver::GetDescription(Stream *s) {
diff --git a/source/Core/FileSpecList.cpp b/source/Core/FileSpecList.cpp
index 66e27b197447..ae4831b6efa6 100644
--- a/source/Core/FileSpecList.cpp
+++ b/source/Core/FileSpecList.cpp
@@ -9,12 +9,12 @@
#include "lldb/Core/FileSpecList.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Stream.h"
-#include <utility> // for find
+#include <utility>
-#include <stdint.h> // for UINT32_MAX
+#include <stdint.h>
using namespace lldb_private;
using namespace std;
diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp
index 743c7c404994..200008dcff5f 100644
--- a/source/Core/FormatEntity.cpp
+++ b/source/Core/FormatEntity.cpp
@@ -10,29 +10,28 @@
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Address.h"
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h" // for RegisterValue
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/FormatClasses.h" // for TypeNameSpecifier...
+#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/DataFormatters/FormatManager.h"
-#include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryImpl::...
+#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/CompilerType.h" // for CompilerType
+#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextS...
+#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -42,31 +41,32 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/AnsiTerminal.h"
-#include "lldb/Utility/ArchSpec.h" // for ArchSpec
-#include "lldb/Utility/ConstString.h" // for ConstString, oper...
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/Log.h" // for Log
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCatego...
-#include "lldb/Utility/SharingPtr.h" // for SharingPtr
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/SharingPtr.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "lldb/Utility/StringList.h" // for StringList
-#include "lldb/Utility/StructuredData.h" // for StructuredData::O...
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-forward.h" // for ValueObjectSP
+#include "lldb/Utility/StringList.h"
+#include "lldb/Utility/StructuredData.h"
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h" // for Triple, Triple::O...
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
-
-#include <ctype.h> // for isxdigit
-#include <inttypes.h> // for PRIu64, PRIx64
-#include <memory> // for shared_ptr, opera...
-#include <stdio.h> // for sprintf
-#include <stdlib.h> // for strtoul
-#include <string.h> // for size_t, strchr
-#include <type_traits> // for move
-#include <utility> // for pair
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Compiler.h"
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <memory>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <type_traits>
+#include <utility>
namespace lldb_private {
class ScriptInterpreter;
@@ -128,6 +128,7 @@ static FormatEntity::Entry::Definition g_frame_child_entries[] = {
ENTRY("flags", FrameRegisterFlags, UInt64),
ENTRY("no-debug", FrameNoDebug, None),
ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry),
+ ENTRY("is-artificial", FrameIsArtificial, UInt32),
};
static FormatEntity::Entry::Definition g_function_child_entries[] = {
@@ -146,6 +147,7 @@ static FormatEntity::Entry::Definition g_function_child_entries[] = {
static FormatEntity::Entry::Definition g_line_child_entries[] = {
ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries),
ENTRY("number", LineEntryLineNumber, UInt32),
+ ENTRY("column", LineEntryColumn, UInt32),
ENTRY("start-addr", LineEntryStartAddress, UInt64),
ENTRY("end-addr", LineEntryEndAddress, UInt64),
};
@@ -356,6 +358,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
ENUM_TO_CSTR(FrameRegisterFP);
ENUM_TO_CSTR(FrameRegisterFlags);
ENUM_TO_CSTR(FrameRegisterByName);
+ ENUM_TO_CSTR(FrameIsArtificial);
ENUM_TO_CSTR(ScriptFrame);
ENUM_TO_CSTR(FunctionID);
ENUM_TO_CSTR(FunctionDidChange);
@@ -372,6 +375,7 @@ const char *FormatEntity::Entry::TypeToCString(Type t) {
ENUM_TO_CSTR(FunctionIsOptimized);
ENUM_TO_CSTR(LineEntryFile);
ENUM_TO_CSTR(LineEntryLineNumber);
+ ENUM_TO_CSTR(LineEntryColumn);
ENUM_TO_CSTR(LineEntryStartAddress);
ENUM_TO_CSTR(LineEntryEndAddress);
ENUM_TO_CSTR(CurrentPCArrow);
@@ -1487,6 +1491,13 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
}
return false;
+ case Entry::Type::FrameIsArtificial: {
+ if (exe_ctx)
+ if (StackFrame *frame = exe_ctx->GetFramePtr())
+ return frame->IsArtificial();
+ return false;
+ }
+
case Entry::Type::ScriptFrame:
if (exe_ctx) {
StackFrame *frame = exe_ctx->GetFramePtr();
@@ -1814,6 +1825,16 @@ bool FormatEntity::Format(const Entry &entry, Stream &s,
}
return false;
+ case Entry::Type::LineEntryColumn:
+ if (sc && sc->line_entry.IsValid() && sc->line_entry.column) {
+ const char *format = "%" PRIu32;
+ if (!entry.printf_format.empty())
+ format = entry.printf_format.c_str();
+ s.Printf(format, sc->line_entry.column);
+ return true;
+ }
+ return false;
+
case Entry::Type::LineEntryStartAddress:
case Entry::Type::LineEntryEndAddress:
if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) {
diff --git a/source/Core/Highlighter.cpp b/source/Core/Highlighter.cpp
new file mode 100644
index 000000000000..c7dd0db83645
--- /dev/null
+++ b/source/Core/Highlighter.cpp
@@ -0,0 +1,81 @@
+//===-- Highlighter.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/Highlighter.h"
+
+#include "lldb/Target/Language.h"
+#include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb_private;
+
+void HighlightStyle::ColorStyle::Apply(Stream &s, llvm::StringRef value) const {
+ s << m_prefix << value << m_suffix;
+}
+
+void HighlightStyle::ColorStyle::Set(llvm::StringRef prefix,
+ llvm::StringRef suffix) {
+ m_prefix = lldb_utility::ansi::FormatAnsiTerminalCodes(prefix);
+ m_suffix = lldb_utility::ansi::FormatAnsiTerminalCodes(suffix);
+}
+
+void DefaultHighlighter::Highlight(const HighlightStyle &options,
+ llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines,
+ Stream &s) const {
+ // If we don't have a valid cursor, then we just print the line as-is.
+ if (!cursor_pos || *cursor_pos >= line.size()) {
+ s << line;
+ return;
+ }
+
+ // If we have a valid cursor, we have to apply the 'selected' style around
+ // the character below the cursor.
+
+ // Split the line around the character which is below the cursor.
+ size_t column = *cursor_pos;
+ // Print the characters before the cursor.
+ s << line.substr(0, column);
+ // Print the selected character with the defined color codes.
+ options.selected.Apply(s, line.substr(column, 1));
+ // Print the rest of the line.
+ s << line.substr(column + 1U);
+}
+
+static HighlightStyle::ColorStyle GetColor(const char *c) {
+ return HighlightStyle::ColorStyle(c, "${ansi.normal}");
+}
+
+HighlightStyle HighlightStyle::MakeVimStyle() {
+ HighlightStyle result;
+ result.comment = GetColor("${ansi.fg.purple}");
+ result.scalar_literal = GetColor("${ansi.fg.red}");
+ result.keyword = GetColor("${ansi.fg.green}");
+ return result;
+}
+
+const Highlighter &
+HighlighterManager::getHighlighterFor(lldb::LanguageType language_type,
+ llvm::StringRef path) const {
+ Language *language = lldb_private::Language::FindPlugin(language_type, path);
+ if (language && language->GetHighlighter())
+ return *language->GetHighlighter();
+ return m_default;
+}
+
+std::string Highlighter::Highlight(const HighlightStyle &options,
+ llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines) const {
+ StreamString s;
+ Highlight(options, line, cursor_pos, previous_lines, s);
+ s.Flush();
+ return s.GetString().str();
+}
diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp
index e7ebeea1b88d..5c0eea5ea1a3 100644
--- a/source/Core/IOHandler.cpp
+++ b/source/Core/IOHandler.cpp
@@ -9,28 +9,24 @@
#include "lldb/Core/IOHandler.h"
-// C Includes
#ifndef LLDB_DISABLE_CURSES
#include <curses.h>
#include <panel.h>
#endif
-// C++ Includes
#if defined(__APPLE__)
#include <deque>
#endif
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Host/File.h" // for File
-#include "lldb/Host/Predicate.h" // for Predicate, ::eBroad...
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/Utility/StreamString.h" // for StreamString
-#include "lldb/Utility/StringList.h" // for StringList
-#include "lldb/lldb-forward.h" // for StreamFileSP
+#include "lldb/Host/File.h"
+#include "lldb/Utility/Predicate.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/StringList.h"
+#include "lldb/lldb-forward.h"
#ifndef LLDB_DISABLE_LIBEDIT
#include "lldb/Host/Editline.h"
@@ -40,7 +36,6 @@
#ifndef LLDB_DISABLE_CURSES
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Symbol/Block.h"
@@ -53,25 +48,26 @@
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
#endif
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
#ifdef _MSC_VER
#include "lldb/Host/windows/windows.h"
#endif
-#include <memory> // for shared_ptr
-#include <mutex> // for recursive_mutex
+#include <memory>
+#include <mutex>
-#include <assert.h> // for assert
-#include <ctype.h> // for isspace
-#include <errno.h> // for EINTR, errno
-#include <locale.h> // for setlocale
-#include <stdint.h> // for uint32_t, UINT32_MAX
-#include <stdio.h> // for size_t, fprintf, feof
-#include <string.h> // for strlen
-#include <type_traits> // for move
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <locale.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <type_traits>
using namespace lldb;
using namespace lldb_private;
@@ -172,12 +168,10 @@ IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt,
IOHandlerConfirm::~IOHandlerConfirm() = default;
-int IOHandlerConfirm::IOHandlerComplete(IOHandler &io_handler,
- const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches, StringList &matches) {
+int IOHandlerConfirm::IOHandlerComplete(
+ IOHandler &io_handler, const char *current_line, const char *cursor,
+ const char *last_char, int skip_first_n_matches, int max_matches,
+ StringList &matches, StringList &descriptions) {
if (current_line == cursor) {
if (m_default_response) {
matches.AppendString("y");
@@ -223,12 +217,10 @@ void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler,
}
}
-int IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler,
- const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches, StringList &matches) {
+int IOHandlerDelegate::IOHandlerComplete(
+ IOHandler &io_handler, const char *current_line, const char *cursor,
+ const char *last_char, int skip_first_n_matches, int max_matches,
+ StringList &matches, StringList &descriptions) {
switch (m_completion) {
case Completion::None:
break;
@@ -236,14 +228,16 @@ int IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler,
case Completion::LLDBCommand:
return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion(
current_line, cursor, last_char, skip_first_n_matches, max_matches,
- matches);
-
+ matches, descriptions);
case Completion::Expression: {
+ CompletionResult result;
CompletionRequest request(current_line, current_line - cursor,
- skip_first_n_matches, max_matches, matches);
+ skip_first_n_matches, max_matches, result);
CommandCompletions::InvokeCommonCompletionCallbacks(
io_handler.GetDebugger().GetCommandInterpreter(),
CommandCompletions::eVariablePathCompletion, request, nullptr);
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
size_t num_matches = request.GetNumberOfMatches();
if (num_matches > 0) {
@@ -432,17 +426,15 @@ int IOHandlerEditline::FixIndentationCallback(Editline *editline,
*editline_reader, lines, cursor_position);
}
-int IOHandlerEditline::AutoCompleteCallback(const char *current_line,
- const char *cursor,
- const char *last_char,
- int skip_first_n_matches,
- int max_matches,
- StringList &matches, void *baton) {
+int IOHandlerEditline::AutoCompleteCallback(
+ const char *current_line, const char *cursor, const char *last_char,
+ int skip_first_n_matches, int max_matches, StringList &matches,
+ StringList &descriptions, void *baton) {
IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton;
if (editline_reader)
return editline_reader->m_delegate.IOHandlerComplete(
*editline_reader, current_line, cursor, last_char, skip_first_n_matches,
- max_matches, matches);
+ max_matches, matches, descriptions);
return 0;
}
#endif
@@ -1060,7 +1052,7 @@ public:
Windows::iterator pos, end = m_subwindows.end();
size_t i = 0;
for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) {
- if ((*pos)->m_name.compare(name) == 0)
+ if ((*pos)->m_name == name)
return *pos;
}
return WindowSP();
@@ -1752,11 +1744,7 @@ public:
void Initialize() {
::setlocale(LC_ALL, "");
::setlocale(LC_CTYPE, "");
-#if 0
- ::initscr();
-#else
m_screen = ::newterm(nullptr, m_out, m_in);
-#endif
::start_color();
::curs_set(0);
::noecho();
@@ -4340,6 +4328,7 @@ public:
m_file_sp->GetFileSpec(), // Source file
m_selected_line +
1, // Source line number (m_selected_line is zero based)
+ 0, // Unspecified column.
0, // No offset
eLazyBoolCalculate, // Check inlines using global setting
eLazyBoolCalculate, // Skip prologue using global setting,
@@ -4379,6 +4368,7 @@ public:
m_file_sp->GetFileSpec(), // Source file
m_selected_line +
1, // Source line number (m_selected_line is zero based)
+ 0, // No column specified.
0, // No offset
eLazyBoolCalculate, // Check inlines using global setting
eLazyBoolCalculate, // Skip prologue using global setting,
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
index 545ac51c870f..943df008edad 100644
--- a/source/Core/Mangled.cpp
+++ b/source/Core/Mangled.cpp
@@ -16,6 +16,7 @@
#pragma comment(lib, "dbghelp.lib")
#endif
+#include "lldb/Core/RichManglingContext.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
@@ -195,7 +196,7 @@ void Mangled::Clear() {
int Mangled::Compare(const Mangled &a, const Mangled &b) {
return ConstString::Compare(
a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled),
- a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
+ b.GetName(lldb::eLanguageTypeUnknown, ePreferMangled));
}
//----------------------------------------------------------------------
@@ -233,6 +234,130 @@ void Mangled::SetValue(const ConstString &name) {
}
//----------------------------------------------------------------------
+// Local helpers for different demangling implementations.
+//----------------------------------------------------------------------
+static char *GetMSVCDemangledStr(const char *M) {
+#if defined(_MSC_VER)
+ const size_t demangled_length = 2048;
+ char *demangled_cstr = static_cast<char *>(::malloc(demangled_length));
+ ::ZeroMemory(demangled_cstr, demangled_length);
+ DWORD result = safeUndecorateName(M, demangled_cstr, demangled_length);
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
+ if (demangled_cstr && demangled_cstr[0])
+ log->Printf("demangled msvc: %s -> \"%s\"", M, demangled_cstr);
+ else
+ log->Printf("demangled msvc: %s -> error: 0x%lu", M, result);
+ }
+
+ if (result != 0) {
+ return demangled_cstr;
+ } else {
+ ::free(demangled_cstr);
+ return nullptr;
+ }
+#else
+ return nullptr;
+#endif
+}
+
+static char *GetItaniumDemangledStr(const char *M) {
+ char *demangled_cstr = nullptr;
+
+ llvm::ItaniumPartialDemangler ipd;
+ bool err = ipd.partialDemangle(M);
+ if (!err) {
+ // Default buffer and size (will realloc in case it's too small).
+ size_t demangled_size = 80;
+ demangled_cstr = static_cast<char *>(std::malloc(demangled_size));
+ demangled_cstr = ipd.finishDemangle(demangled_cstr, &demangled_size);
+
+ assert(demangled_cstr &&
+ "finishDemangle must always succeed if partialDemangle did");
+ assert(demangled_cstr[demangled_size - 1] == '\0' &&
+ "Expected demangled_size to return length including trailing null");
+ }
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
+ if (demangled_cstr)
+ log->Printf("demangled itanium: %s -> \"%s\"", M, demangled_cstr);
+ else
+ log->Printf("demangled itanium: %s -> error: failed to demangle", M);
+ }
+
+ return demangled_cstr;
+}
+
+//----------------------------------------------------------------------
+// Explicit demangling for scheduled requests during batch processing. This
+// makes use of ItaniumPartialDemangler's rich demangle info
+//----------------------------------------------------------------------
+bool Mangled::DemangleWithRichManglingInfo(
+ RichManglingContext &context, SkipMangledNameFn *skip_mangled_name) {
+ // We need to generate and cache the demangled name.
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat,
+ "Mangled::DemangleWithRichNameIndexInfo (m_mangled = %s)",
+ m_mangled.GetCString());
+
+ // Others are not meant to arrive here. ObjC names or C's main() for example
+ // have their names stored in m_demangled, while m_mangled is empty.
+ assert(m_mangled);
+
+ // Check whether or not we are interested in this name at all.
+ ManglingScheme scheme = cstring_mangling_scheme(m_mangled.GetCString());
+ if (skip_mangled_name && skip_mangled_name(m_mangled.GetStringRef(), scheme))
+ return false;
+
+ switch (scheme) {
+ case eManglingSchemeNone:
+ // The current mangled_name_filter would allow llvm_unreachable here.
+ return false;
+
+ case eManglingSchemeItanium:
+ // We want the rich mangling info here, so we don't care whether or not
+ // there is a demangled string in the pool already.
+ if (context.FromItaniumName(m_mangled)) {
+ // If we got an info, we have a name. Copy to string pool and connect the
+ // counterparts to accelerate later access in GetDemangledName().
+ context.ParseFullName();
+ m_demangled.SetStringWithMangledCounterpart(context.GetBufferRef(),
+ m_mangled);
+ return true;
+ } else {
+ m_demangled.SetCString("");
+ return false;
+ }
+
+ case eManglingSchemeMSVC: {
+ // We have no rich mangling for MSVC-mangled names yet, so first try to
+ // demangle it if necessary.
+ if (!m_demangled && !m_mangled.GetMangledCounterpart(m_demangled)) {
+ if (char *d = GetMSVCDemangledStr(m_mangled.GetCString())) {
+ // If we got an info, we have a name. Copy to string pool and connect
+ // the counterparts to accelerate later access in GetDemangledName().
+ m_demangled.SetStringWithMangledCounterpart(llvm::StringRef(d),
+ m_mangled);
+ ::free(d);
+ } else {
+ m_demangled.SetCString("");
+ }
+ }
+
+ if (m_demangled.IsEmpty()) {
+ // Cannot demangle it, so don't try parsing.
+ return false;
+ } else {
+ // Demangled successfully, we can try and parse it with
+ // CPlusPlusLanguage::MethodName.
+ return context.FromCxxMethodName(m_demangled);
+ }
+ }
+ }
+ llvm_unreachable("Fully covered switch above!");
+}
+
+//----------------------------------------------------------------------
// Generate the demangled name on demand using this accessor. Code in this
// class will need to use this accessor if it wishes to decode the demangled
// name. The result is cached and will be kept until a new string value is
@@ -242,14 +367,12 @@ const ConstString &
Mangled::GetDemangledName(lldb::LanguageType language) const {
// Check to make sure we have a valid mangled name and that we haven't
// already decoded our mangled name.
- if (m_mangled && !m_demangled) {
+ if (m_mangled && m_demangled.IsNull()) {
// We need to generate and cache the demangled name.
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "Mangled::GetDemangledName (m_mangled = %s)",
m_mangled.GetCString());
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE);
-
// Don't bother running anything that isn't mangled
const char *mangled_name = m_mangled.GetCString();
ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)};
@@ -259,60 +382,23 @@ Mangled::GetDemangledName(lldb::LanguageType language) const {
// add it to our map.
char *demangled_name = nullptr;
switch (mangling_scheme) {
- case eManglingSchemeMSVC: {
-#if defined(_MSC_VER)
- if (log)
- log->Printf("demangle msvc: %s", mangled_name);
- const size_t demangled_length = 2048;
- demangled_name = static_cast<char *>(::malloc(demangled_length));
- ::ZeroMemory(demangled_name, demangled_length);
- DWORD result =
- safeUndecorateName(mangled_name, demangled_name, demangled_length);
- if (log) {
- if (demangled_name && demangled_name[0])
- log->Printf("demangled msvc: %s -> \"%s\"", mangled_name,
- demangled_name);
- else
- log->Printf("demangled msvc: %s -> error: 0x%lu", mangled_name,
- result);
- }
-
- if (result == 0) {
- free(demangled_name);
- demangled_name = nullptr;
- }
-#endif
+ case eManglingSchemeMSVC:
+ demangled_name = GetMSVCDemangledStr(mangled_name);
break;
- }
case eManglingSchemeItanium: {
- llvm::ItaniumPartialDemangler IPD;
- bool demangle_err = IPD.partialDemangle(mangled_name);
- if (!demangle_err) {
- // Default buffer and size (realloc is used in case it's too small).
- size_t demangled_size = 80;
- demangled_name = static_cast<char *>(::malloc(demangled_size));
- demangled_name = IPD.finishDemangle(demangled_name, &demangled_size);
- }
-
- if (log) {
- if (demangled_name)
- log->Printf("demangled itanium: %s -> \"%s\"", mangled_name,
- demangled_name);
- else
- log->Printf("demangled itanium: %s -> error: failed to demangle",
- mangled_name);
- }
+ demangled_name = GetItaniumDemangledStr(mangled_name);
break;
}
case eManglingSchemeNone:
- break;
+ llvm_unreachable("eManglingSchemeNone was handled already");
}
if (demangled_name) {
- m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
+ m_demangled.SetStringWithMangledCounterpart(
+ llvm::StringRef(demangled_name), m_mangled);
free(demangled_name);
}
}
- if (!m_demangled) {
+ if (m_demangled.IsNull()) {
// Set the demangled string to the empty string to indicate we tried to
// parse it once and failed.
m_demangled.SetCString("");
@@ -333,9 +419,7 @@ bool Mangled::NameMatches(const RegularExpression &regex,
return true;
ConstString demangled = GetDemangledName(language);
- if (demangled && regex.Execute(demangled.AsCString()))
- return true;
- return false;
+ return demangled && regex.Execute(demangled.AsCString());
}
//----------------------------------------------------------------------
diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp
index 3b1a4fd7be0f..b48d3cca092b 100644
--- a/source/Core/Module.cpp
+++ b/source/Core/Module.cpp
@@ -9,65 +9,65 @@
#include "lldb/Core/Module.h"
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/AddressRange.h"
#include "lldb/Core/AddressResolverFileLine.h"
-#include "lldb/Core/Debugger.h" // for Debugger
-#include "lldb/Core/FileSpecList.h" // for FileSpecList
-#include "lldb/Core/Mangled.h" // for Mangled
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Mangled.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/SearchFilter.h" // for SearchFilt...
+#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/Function.h" // for Function
+#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Symbol.h" // for Symbol
+#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
-#include "lldb/Symbol/Symtab.h" // for Symtab
-#include "lldb/Symbol/Type.h" // for Type
-#include "lldb/Symbol/TypeList.h" // for TypeList
+#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Language.h"
-#include "lldb/Target/Platform.h" // for Platform
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAn...
+#include "lldb/Utility/Logging.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Status.h"
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#if defined(_WIN32)
-#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
+#include "lldb/Host/windows/PosixApi.h"
#endif
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
-#include "llvm/ADT/STLExtras.h" // for make_unique
-#include "llvm/Support/Compiler.h" // for LLVM_PRETT...
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
-#include "llvm/Support/raw_ostream.h" // for raw_string...
+#include "llvm/Support/raw_ostream.h"
-#include <assert.h> // for assert
-#include <cstdint> // for uint32_t
-#include <inttypes.h> // for PRIx64
-#include <map> // for map
-#include <stdarg.h> // for va_end
-#include <string.h> // for size_t
-#include <type_traits> // for move
-#include <utility> // for find, pair
+#include <assert.h>
+#include <cstdint>
+#include <inttypes.h>
+#include <map>
+#include <stdarg.h>
+#include <string.h>
+#include <type_traits>
+#include <utility>
namespace lldb_private {
class CompilerDeclContext;
@@ -162,15 +162,19 @@ Module::Module(const ModuleSpec &module_spec)
// fill any ivars in so we don't accidentally grab the wrong file later since
// they don't match...
ModuleSpec matching_module_spec;
- if (modules_specs.FindMatchingModuleSpec(module_spec, matching_module_spec) ==
- 0)
+ if (!modules_specs.FindMatchingModuleSpec(module_spec,
+ matching_module_spec)) {
+ if (log) {
+ log->Printf("Found local object file but the specs didn't match");
+ }
return;
+ }
if (module_spec.GetFileSpec())
- m_mod_time = FileSystem::GetModificationTime(module_spec.GetFileSpec());
+ m_mod_time = FileSystem::Instance().GetModificationTime(module_spec.GetFileSpec());
else if (matching_module_spec.GetFileSpec())
m_mod_time =
- FileSystem::GetModificationTime(matching_module_spec.GetFileSpec());
+ FileSystem::Instance().GetModificationTime(matching_module_spec.GetFileSpec());
// Copy the architecture from the actual spec if we got one back, else use
// the one that was specified
@@ -215,7 +219,7 @@ Module::Module(const ModuleSpec &module_spec)
Module::Module(const FileSpec &file_spec, const ArchSpec &arch,
const ConstString *object_name, lldb::offset_t object_offset,
const llvm::sys::TimePoint<> &object_mod_time)
- : m_mod_time(FileSystem::GetModificationTime(file_spec)), m_arch(arch),
+ : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), m_arch(arch),
m_file(file_spec), m_object_offset(object_offset),
m_object_mod_time(object_mod_time), m_file_has_changed(false),
m_first_file_changed_log(false) {
@@ -305,7 +309,7 @@ ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp,
// Once we get the object file, update our module with the object
// file's architecture since it might differ in vendor/os if some
// parts were unknown.
- m_objfile_sp->GetArchitecture(m_arch);
+ m_arch = m_objfile_sp->GetArchitecture();
} else {
error.SetErrorString("unable to find suitable object file plug-in");
}
@@ -361,26 +365,24 @@ void Module::ParseAllDebugSymbols() {
for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) {
sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get();
- if (sc.comp_unit) {
- sc.function = nullptr;
- symbols->ParseVariablesForContext(sc);
+ if (!sc.comp_unit)
+ continue;
- symbols->ParseCompileUnitFunctions(sc);
+ symbols->ParseVariablesForContext(sc);
- for (size_t func_idx = 0;
- (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) !=
- nullptr;
- ++func_idx) {
- symbols->ParseFunctionBlocks(sc);
+ symbols->ParseFunctions(*sc.comp_unit);
- // Parse the variables for this function and all its blocks
- symbols->ParseVariablesForContext(sc);
- }
+ sc.comp_unit->ForeachFunction([&sc, &symbols](const FunctionSP &f) {
+ symbols->ParseBlocksRecursive(*f);
- // Parse all types for this compile unit
- sc.function = nullptr;
- symbols->ParseTypes(sc);
- }
+ // Parse the variables for this function and all its blocks
+ sc.function = f.get();
+ symbols->ParseVariablesForContext(sc);
+ return false;
+ });
+
+ // Parse all types for this compile unit
+ symbols->ParseTypes(*sc.comp_unit);
}
}
@@ -431,8 +433,8 @@ bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) {
}
uint32_t Module::ResolveSymbolContextForAddress(
- const Address &so_addr, uint32_t resolve_scope, SymbolContext &sc,
- bool resolve_tail_call_address) {
+ const Address &so_addr, lldb::SymbolContextItem resolve_scope,
+ SymbolContext &sc, bool resolve_tail_call_address) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
uint32_t resolved_flags = 0;
@@ -564,21 +566,17 @@ uint32_t Module::ResolveSymbolContextForAddress(
return resolved_flags;
}
-uint32_t Module::ResolveSymbolContextForFilePath(const char *file_path,
- uint32_t line,
- bool check_inlines,
- uint32_t resolve_scope,
- SymbolContextList &sc_list) {
- FileSpec file_spec(file_path, false);
+uint32_t Module::ResolveSymbolContextForFilePath(
+ const char *file_path, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
+ FileSpec file_spec(file_path);
return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
resolve_scope, sc_list);
}
-uint32_t Module::ResolveSymbolContextsForFileSpec(const FileSpec &file_spec,
- uint32_t line,
- bool check_inlines,
- uint32_t resolve_scope,
- SymbolContextList &sc_list) {
+uint32_t Module::ResolveSymbolContextsForFileSpec(
+ const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat,
@@ -637,9 +635,11 @@ size_t Module::FindCompileUnits(const FileSpec &path, bool append,
return sc_list.GetSize() - start_size;
}
-Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask,
- lldb::LanguageType language)
- : m_name(name), m_lookup_name(), m_language(language), m_name_type_mask(0),
+Module::LookupInfo::LookupInfo(const ConstString &name,
+ FunctionNameType name_type_mask,
+ LanguageType language)
+ : m_name(name), m_lookup_name(), m_language(language),
+ m_name_type_mask(eFunctionNameTypeNone),
m_match_name_after_lookup(false) {
const char *name_cstr = name.GetCString();
llvm::StringRef basename;
@@ -783,7 +783,7 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
qualified_name = cpp_method.GetBasename().str();
else
qualified_name = cpp_method.GetScopeQualifiedName();
- if (qualified_name.compare(m_name.GetCString()) != 0) {
+ if (qualified_name != m_name.GetCString()) {
sc_list.RemoveContextAtIndex(i);
continue;
}
@@ -797,9 +797,9 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
size_t Module::FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_symbols,
- bool include_inlines, bool append,
- SymbolContextList &sc_list) {
+ FunctionNameType name_type_mask,
+ bool include_symbols, bool include_inlines,
+ bool append, SymbolContextList &sc_list) {
if (!append)
sc_list.Clear();
@@ -943,33 +943,33 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp,
}
size_t Module::FindTypes_Impl(
- const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches,
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
- if (!sc.module_sp || sc.module_sp.get() == this) {
- SymbolVendor *symbols = GetSymbolVendor();
- if (symbols)
- return symbols->FindTypes(sc, name, parent_decl_ctx, append, max_matches,
- searched_symbol_files, types);
- }
+ SymbolVendor *symbols = GetSymbolVendor();
+ if (symbols)
+ return symbols->FindTypes(name, parent_decl_ctx, append, max_matches,
+ searched_symbol_files, types);
return 0;
}
-size_t Module::FindTypesInNamespace(const SymbolContext &sc,
- const ConstString &type_name,
+size_t Module::FindTypesInNamespace(const ConstString &type_name,
const CompilerDeclContext *parent_decl_ctx,
size_t max_matches, TypeList &type_list) {
const bool append = true;
TypeMap types_map;
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
size_t num_types =
- FindTypes_Impl(sc, type_name, parent_decl_ctx, append, max_matches,
+ FindTypes_Impl(type_name, parent_decl_ctx, append, max_matches,
searched_symbol_files, types_map);
- if (num_types > 0)
+ if (num_types > 0) {
+ SymbolContext sc;
+ sc.module_sp = shared_from_this();
sc.SortTypeList(types_map, type_list);
+ }
return num_types;
}
@@ -978,15 +978,14 @@ lldb::TypeSP Module::FindFirstType(const SymbolContext &sc,
TypeList type_list;
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
const size_t num_matches =
- FindTypes(sc, name, exact_match, 1, searched_symbol_files, type_list);
+ FindTypes(name, exact_match, 1, searched_symbol_files, type_list);
if (num_matches)
return type_list.GetTypeAtIndex(0);
return TypeSP();
}
size_t Module::FindTypes(
- const SymbolContext &sc, const ConstString &name, bool exact_match,
- size_t max_matches,
+ const ConstString &name, bool exact_match, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeList &types) {
size_t num_matches = 0;
@@ -1006,8 +1005,8 @@ size_t Module::FindTypes(
exact_match = type_scope.consume_front("::");
ConstString type_basename_const_str(type_basename);
- if (FindTypes_Impl(sc, type_basename_const_str, nullptr, append,
- max_matches, searched_symbol_files, typesmap)) {
+ if (FindTypes_Impl(type_basename_const_str, nullptr, append, max_matches,
+ searched_symbol_files, typesmap)) {
typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
exact_match);
num_matches = typesmap.GetSize();
@@ -1018,13 +1017,13 @@ size_t Module::FindTypes(
if (type_class != eTypeClassAny && !type_basename.empty()) {
// The "type_name_cstr" will have been modified if we have a valid type
// class prefix (like "struct", "class", "union", "typedef" etc).
- FindTypes_Impl(sc, ConstString(type_basename), nullptr, append,
- UINT_MAX, searched_symbol_files, typesmap);
+ FindTypes_Impl(ConstString(type_basename), nullptr, append, UINT_MAX,
+ searched_symbol_files, typesmap);
typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class,
exact_match);
num_matches = typesmap.GetSize();
} else {
- num_matches = FindTypes_Impl(sc, name, nullptr, append, UINT_MAX,
+ num_matches = FindTypes_Impl(name, nullptr, append, UINT_MAX,
searched_symbol_files, typesmap);
if (exact_match) {
std::string name_str(name.AsCString(""));
@@ -1034,8 +1033,11 @@ size_t Module::FindTypes(
}
}
}
- if (num_matches > 0)
+ if (num_matches > 0) {
+ SymbolContext sc;
+ sc.module_sp = shared_from_this();
sc.SortTypeList(typesmap, types);
+ }
return num_matches;
}
@@ -1062,7 +1064,7 @@ void Module::SetFileSpecAndObjectName(const FileSpec &file,
// Container objects whose paths do not specify a file directly can call this
// function to correct the file and object names.
m_file = file;
- m_mod_time = FileSystem::GetModificationTime(file);
+ m_mod_time = FileSystem::Instance().GetModificationTime(file);
m_object_name = object_name;
}
@@ -1125,7 +1127,7 @@ void Module::ReportError(const char *format, ...) {
bool Module::FileHasChanged() const {
if (!m_file_has_changed)
m_file_has_changed =
- (FileSystem::GetModificationTime(m_file) != m_mod_time);
+ (FileSystem::Instance().GetModificationTime(m_file) != m_mod_time);
return m_file_has_changed;
}
@@ -1252,7 +1254,8 @@ ObjectFile *Module::GetObjectFile() {
GetFileSpec().GetFilename().AsCString(""));
DataBufferSP data_sp;
lldb::offset_t data_offset = 0;
- const lldb::offset_t file_size = m_file.GetByteSize();
+ const lldb::offset_t file_size =
+ FileSystem::Instance().GetByteSize(m_file);
if (file_size > m_object_offset) {
m_did_load_objfile = true;
m_objfile_sp = ObjectFile::FindPlugin(
@@ -1264,9 +1267,7 @@ ObjectFile *Module::GetObjectFile() {
// parts were unknown. But since the matching arch might already be
// more specific than the generic COFF architecture, only merge in
// those values that overwrite unspecified unknown values.
- ArchSpec new_arch;
- m_objfile_sp->GetArchitecture(new_arch);
- m_arch.MergeFrom(new_arch);
+ m_arch.MergeFrom(m_objfile_sp->GetArchitecture());
} else {
ReportError("failed to load objfile for %s",
GetFileSpec().GetPath().c_str());
@@ -1417,7 +1418,7 @@ void Module::PreloadSymbols() {
}
void Module::SetSymbolFileFileSpec(const FileSpec &file) {
- if (!file.Exists())
+ if (!FileSystem::Instance().Exists(file))
return;
if (m_symfile_ap) {
// Remove any sections in the unified section list that come from the
@@ -1447,7 +1448,7 @@ void Module::SetSymbolFileFileSpec(const FileSpec &file) {
// ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to
// check this
- if (llvm::sys::fs::is_directory(file.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(file)) {
std::string new_path(file.GetPath());
std::string old_path(obj_file->GetFileSpec().GetPath());
if (old_path.find(new_path) == 0) {
@@ -1536,7 +1537,8 @@ bool Module::LoadScriptingResourceInTarget(Target *target, Status &error,
if (script_interpreter) {
for (uint32_t i = 0; i < num_specs; ++i) {
FileSpec scripting_fspec(file_specs.GetFileSpecAtIndex(i));
- if (scripting_fspec && scripting_fspec.Exists()) {
+ if (scripting_fspec &&
+ FileSystem::Instance().Exists(scripting_fspec)) {
if (should_load == eLoadScriptFromSymFileWarn) {
if (feedback_stream)
feedback_stream->Printf(
diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp
index d2896da1adca..b8de86f4eadc 100644
--- a/source/Core/ModuleList.cpp
+++ b/source/Core/ModuleList.cpp
@@ -8,39 +8,39 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/ModuleList.h"
-#include "lldb/Core/FileSpecList.h" // for FileSpecList
+#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Symbols.h"
-#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/OptionValueFileSpec.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContextList, SymbolCon...
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/VariableList.h"
-#include "lldb/Utility/ArchSpec.h" // for ArchSpec
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAnyCategoriesSet
-#include "lldb/Utility/UUID.h" // for UUID, operator!=, operator==
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_INDEX32
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/UUID.h"
+#include "lldb/lldb-defines.h"
#if defined(_WIN32)
-#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
+#include "lldb/Host/windows/PosixApi.h"
#endif
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "clang/Driver/Driver.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.h"
-#include "llvm/Support/raw_ostream.h" // for fs
-#include "clang/Driver/Driver.h"
+#include "llvm/Support/raw_ostream.h"
-#include <chrono> // for operator!=, time_point
-#include <memory> // for shared_ptr
+#include <chrono>
+#include <memory>
#include <mutex>
-#include <string> // for string
-#include <utility> // for distance
+#include <string>
+#include <utility>
namespace lldb_private {
class Function;
@@ -66,16 +66,22 @@ using namespace lldb_private;
namespace {
-PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"enable-external-lookup", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
- "Control the use of external tools or libraries to locate symbol files. "
- "On macOS, Spotlight is used to locate a matching .dSYM bundle based on "
- "the UUID of the executable."},
+ {},
+ "Control the use of external tools and repositories to locate symbol "
+ "files. Directories listed in target.debug-file-search-paths and "
+ "directory of the executable are always checked first for separate debug "
+ "info files. Then depending on this setting: "
+ "On macOS, Spotlight would be also used to locate a matching .dSYM "
+ "bundle based on the UUID of the executable. "
+ "On NetBSD, directory /usr/libdata/debug would be also searched. "
+ "On platforms other than NetBSD directory /usr/lib/debug would be "
+ "also searched."
+ },
{"clang-modules-cache-path", OptionValue::eTypeFileSpec, true, 0, nullptr,
- nullptr,
- "The path to the clang modules cache directory (-fmodules-cache-path)."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {},
+ "The path to the clang modules cache directory (-fmodules-cache-path)."}};
enum { ePropertyEnableExternalLookup, ePropertyClangModulesCachePath };
@@ -339,8 +345,9 @@ ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const {
}
size_t ModuleList::FindFunctions(const ConstString &name,
- uint32_t name_type_mask, bool include_symbols,
- bool include_inlines, bool append,
+ FunctionNameType name_type_mask,
+ bool include_symbols, bool include_inlines,
+ bool append,
SymbolContextList &sc_list) const {
if (!append)
sc_list.Clear();
@@ -374,7 +381,7 @@ size_t ModuleList::FindFunctions(const ConstString &name,
}
size_t ModuleList::FindFunctionSymbols(const ConstString &name,
- uint32_t name_type_mask,
+ lldb::FunctionNameType name_type_mask,
SymbolContextList &sc_list) {
const size_t old_size = sc_list.GetSize();
@@ -535,7 +542,7 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const {
}
size_t
-ModuleList::FindTypes(const SymbolContext &sc, const ConstString &name,
+ModuleList::FindTypes(Module *search_first, const ConstString &name,
bool name_is_fully_qualified, size_t max_matches,
llvm::DenseSet<SymbolFile *> &searched_symbol_files,
TypeList &types) const {
@@ -543,14 +550,12 @@ ModuleList::FindTypes(const SymbolContext &sc, const ConstString &name,
size_t total_matches = 0;
collection::const_iterator pos, end = m_modules.end();
- if (sc.module_sp) {
- // The symbol context "sc" contains a module so we want to search that one
- // first if it is in our list...
+ if (search_first) {
for (pos = m_modules.begin(); pos != end; ++pos) {
- if (sc.module_sp.get() == (*pos).get()) {
+ if (search_first == pos->get()) {
total_matches +=
- (*pos)->FindTypes(sc, name, name_is_fully_qualified, max_matches,
- searched_symbol_files, types);
+ search_first->FindTypes(name, name_is_fully_qualified, max_matches,
+ searched_symbol_files, types);
if (total_matches >= max_matches)
break;
@@ -559,15 +564,14 @@ ModuleList::FindTypes(const SymbolContext &sc, const ConstString &name,
}
if (total_matches < max_matches) {
- SymbolContext world_sc;
for (pos = m_modules.begin(); pos != end; ++pos) {
// Search the module if the module is not equal to the one in the symbol
// context "sc". If "sc" contains a empty module shared pointer, then the
// comparison will always be true (valid_module_ptr != nullptr).
- if (sc.module_sp.get() != (*pos).get())
+ if (search_first != pos->get())
total_matches +=
- (*pos)->FindTypes(world_sc, name, name_is_fully_qualified,
- max_matches, searched_symbol_files, types);
+ (*pos)->FindTypes(name, name_is_fully_qualified, max_matches,
+ searched_symbol_files, types);
if (total_matches >= max_matches)
break;
@@ -663,9 +667,10 @@ bool ModuleList::ResolveFileAddress(lldb::addr_t vm_addr,
return false;
}
-uint32_t ModuleList::ResolveSymbolContextForAddress(const Address &so_addr,
- uint32_t resolve_scope,
- SymbolContext &sc) const {
+uint32_t
+ModuleList::ResolveSymbolContextForAddress(const Address &so_addr,
+ SymbolContextItem resolve_scope,
+ SymbolContext &sc) const {
// The address is already section offset so it has a module
uint32_t resolved_flags = 0;
ModuleSP module_sp(so_addr.GetModule());
@@ -688,15 +693,15 @@ uint32_t ModuleList::ResolveSymbolContextForAddress(const Address &so_addr,
uint32_t ModuleList::ResolveSymbolContextForFilePath(
const char *file_path, uint32_t line, bool check_inlines,
- uint32_t resolve_scope, SymbolContextList &sc_list) const {
- FileSpec file_spec(file_path, false);
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
+ FileSpec file_spec(file_path);
return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
resolve_scope, sc_list);
}
uint32_t ModuleList::ResolveSymbolContextsForFileSpec(
const FileSpec &file_spec, uint32_t line, bool check_inlines,
- uint32_t resolve_scope, SymbolContextList &sc_list) const {
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) const {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
collection::const_iterator pos, end = m_modules.end();
for (pos = m_modules.begin(); pos != end; ++pos) {
@@ -856,14 +861,13 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
const auto num_directories = module_search_paths_ptr->GetSize();
for (size_t idx = 0; idx < num_directories; ++idx) {
auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx);
- if (!search_path_spec.ResolvePath())
- continue;
+ FileSystem::Instance().Resolve(search_path_spec);
namespace fs = llvm::sys::fs;
- if (!fs::is_directory(search_path_spec.GetPath()))
+ if (!FileSystem::Instance().IsDirectory(search_path_spec))
continue;
search_path_spec.AppendPathComponent(
module_spec.GetFileSpec().GetFilename().AsCString());
- if (!search_path_spec.Exists())
+ if (!FileSystem::Instance().Exists(search_path_spec))
continue;
auto resolved_module_spec(module_spec);
@@ -904,13 +908,15 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
// Don't look for the file if it appears to be the same one we already
// checked for above...
if (located_binary_modulespec.GetFileSpec() != module_file_spec) {
- if (!located_binary_modulespec.GetFileSpec().Exists()) {
+ if (!FileSystem::Instance().Exists(
+ located_binary_modulespec.GetFileSpec())) {
located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path));
if (path[0] == '\0')
module_file_spec.GetPath(path, sizeof(path));
// How can this check ever be true? This branch it is false, and we
// haven't modified file_spec.
- if (located_binary_modulespec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(
+ located_binary_modulespec.GetFileSpec())) {
std::string uuid_str;
if (uuid_ptr && uuid_ptr->IsValid())
uuid_str = uuid_ptr->GetAsString();
@@ -951,7 +957,7 @@ Status ModuleList::GetSharedModule(const ModuleSpec &module_spec,
// If we didn't have a UUID in mind when looking for the object file,
// then we should make sure the modification time hasn't changed!
if (platform_module_spec.GetUUIDPtr() == nullptr) {
- auto file_spec_mod_time = FileSystem::GetModificationTime(
+ auto file_spec_mod_time = FileSystem::Instance().GetModificationTime(
located_binary_modulespec.GetFileSpec());
if (file_spec_mod_time != llvm::sys::TimePoint<>()) {
if (file_spec_mod_time != module_sp->GetModificationTime()) {
diff --git a/source/Core/Opcode.cpp b/source/Core/Opcode.cpp
index d15fdb3b17be..ed8be78a6d67 100644
--- a/source/Core/Opcode.cpp
+++ b/source/Core/Opcode.cpp
@@ -13,50 +13,51 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-forward.h" // for DataBufferSP
+#include "lldb/lldb-forward.h"
-#include <memory> // for make_shared
+#include <memory>
-#include <inttypes.h> // for PRIx64
+#include <inttypes.h>
using namespace lldb;
using namespace lldb_private;
int Opcode::Dump(Stream *s, uint32_t min_byte_width) {
- int bytes_written = 0;
+ const uint32_t previous_bytes = s->GetWrittenBytes();
switch (m_type) {
case Opcode::eTypeInvalid:
- bytes_written = s->PutCString("<invalid>");
+ s->PutCString("<invalid>");
break;
case Opcode::eType8:
- bytes_written = s->Printf("0x%2.2x", m_data.inst8);
+ s->Printf("0x%2.2x", m_data.inst8);
break;
case Opcode::eType16:
- bytes_written = s->Printf("0x%4.4x", m_data.inst16);
+ 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);
+ s->Printf("0x%8.8x", m_data.inst32);
break;
case Opcode::eType64:
- bytes_written = s->Printf("0x%16.16" PRIx64, m_data.inst64);
+ s->Printf("0x%16.16" PRIx64, m_data.inst64);
break;
case Opcode::eTypeBytes:
for (uint32_t i = 0; i < m_data.inst.length; ++i) {
if (i > 0)
- bytes_written += s->PutChar(' ');
- bytes_written += s->Printf("%2.2x", m_data.inst.bytes[i]);
+ s->PutChar(' ');
+ 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 (static_cast<uint32_t>(bytes_written) < min_byte_width)
- bytes_written = s->Printf("%*s", min_byte_width - bytes_written, "");
- return bytes_written;
+ uint32_t bytes_written_so_far = s->GetWrittenBytes() - previous_bytes;
+ // Add spaces to make sure bytes display comes out even in case opcodes aren't
+ // all the same size.
+ if (bytes_written_so_far < min_byte_width)
+ s->Printf("%*s", min_byte_width - bytes_written_so_far, "");
+ return s->GetWrittenBytes() - previous_bytes;
}
lldb::ByteOrder Opcode::GetDataByteOrder() const {
diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp
index 55affb6a1030..fbb258039882 100644
--- a/source/Core/PluginManager.cpp
+++ b/source/Core/PluginManager.cpp
@@ -10,30 +10,31 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Debugger.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/OptionValueProperties.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
-#include "lldb/Utility/StringList.h" // for StringList
+#include "lldb/Utility/StringList.h"
#if defined(_WIN32)
-#include "lldb/Host/windows/PosixApi.h" // for PATH_MAX
+#include "lldb/Host/windows/PosixApi.h"
#endif
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/FileSystem.h" // for file_type, file_...
-#include "llvm/Support/raw_ostream.h" // for fs
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
-#include <map> // for map<>::const_ite...
-#include <memory> // for shared_ptr
+#include <map>
+#include <memory>
#include <mutex>
#include <string>
-#include <utility> // for pair
+#include <utility>
#include <vector>
-#include <assert.h> // for assert
+#include <assert.h>
namespace lldb_private {
class CommandInterpreter;
@@ -89,9 +90,9 @@ template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) {
return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr));
}
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &file_spec) {
+ llvm::StringRef path) {
// PluginManager *plugin_manager = (PluginManager *)baton;
Status error;
@@ -102,11 +103,11 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
// file type information.
if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file ||
ft == fs::file_type::type_unknown) {
- FileSpec plugin_file_spec(file_spec);
- plugin_file_spec.ResolvePath();
+ FileSpec plugin_file_spec(path);
+ FileSystem::Instance().Resolve(plugin_file_spec);
if (PluginIsLoaded(plugin_file_spec))
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
else {
PluginInfo plugin_info;
@@ -138,7 +139,7 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
// plug-in info so we don't try to load it again and again.
SetPluginInfo(plugin_file_spec, plugin_info);
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
}
}
@@ -149,10 +150,10 @@ LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft,
// also do this for unknown as sometimes the directory enumeration might be
// enumerating a file system that doesn't have correct file type
// information.
- return FileSpec::eEnumerateDirectoryResultEnter;
+ return FileSystem::eEnumerateDirectoryResultEnter;
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
void PluginManager::Initialize() {
@@ -162,16 +163,20 @@ void PluginManager::Initialize() {
const bool find_other = true;
char dir_path[PATH_MAX];
if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) {
- if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
- FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
- find_other, LoadPluginCallback, nullptr);
+ if (FileSystem::Instance().Exists(dir_spec) &&
+ dir_spec.GetPath(dir_path, sizeof(dir_path))) {
+ FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
+ find_files, find_other,
+ LoadPluginCallback, nullptr);
}
}
if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) {
- if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) {
- FileSpec::EnumerateDirectory(dir_path, find_directories, find_files,
- find_other, LoadPluginCallback, nullptr);
+ if (FileSystem::Instance().Exists(dir_spec) &&
+ dir_spec.GetPath(dir_path, sizeof(dir_path))) {
+ FileSystem::Instance().EnumerateDirectory(dir_path, find_directories,
+ find_files, find_other,
+ LoadPluginCallback, nullptr);
}
}
#endif
@@ -281,7 +286,10 @@ struct ArchitectureInstance {
typedef std::vector<ArchitectureInstance> ArchitectureInstances;
-static std::mutex g_architecture_mutex;
+static std::mutex &GetArchitectureMutex() {
+ static std::mutex g_architecture_mutex;
+ return g_architecture_mutex;
+}
static ArchitectureInstances &GetArchitectureInstances() {
static ArchitectureInstances g_instances;
@@ -291,13 +299,13 @@ static ArchitectureInstances &GetArchitectureInstances() {
void PluginManager::RegisterPlugin(const ConstString &name,
llvm::StringRef description,
ArchitectureCreateInstance create_callback) {
- std::lock_guard<std::mutex> guard(g_architecture_mutex);
+ std::lock_guard<std::mutex> guard(GetArchitectureMutex());
GetArchitectureInstances().push_back({name, description, create_callback});
}
void PluginManager::UnregisterPlugin(
ArchitectureCreateInstance create_callback) {
- std::lock_guard<std::mutex> guard(g_architecture_mutex);
+ std::lock_guard<std::mutex> guard(GetArchitectureMutex());
auto &instances = GetArchitectureInstances();
for (auto pos = instances.begin(), end = instances.end(); pos != end; ++pos) {
@@ -311,7 +319,7 @@ void PluginManager::UnregisterPlugin(
std::unique_ptr<Architecture>
PluginManager::CreateArchitectureInstance(const ArchSpec &arch) {
- std::lock_guard<std::mutex> guard(g_architecture_mutex);
+ std::lock_guard<std::mutex> guard(GetArchitectureMutex());
for (const auto &instances : GetArchitectureInstances()) {
if (auto plugin_up = instances.create_callback(arch))
return plugin_up;
diff --git a/source/Core/RichManglingContext.cpp b/source/Core/RichManglingContext.cpp
new file mode 100644
index 000000000000..f5fbe38a49fb
--- /dev/null
+++ b/source/Core/RichManglingContext.cpp
@@ -0,0 +1,175 @@
+//===-- RichManglingContext.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/RichManglingContext.h"
+
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Logging.h"
+
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+
+#include "llvm/ADT/StringRef.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// RichManglingContext
+//----------------------------------------------------------------------
+void RichManglingContext::ResetProvider(InfoProvider new_provider) {
+ // If we want to support parsers for other languages some day, we need a
+ // switch here to delete the correct parser type.
+ if (m_cxx_method_parser.hasValue()) {
+ assert(m_provider == PluginCxxLanguage);
+ delete get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser);
+ m_cxx_method_parser.reset();
+ }
+
+ assert(new_provider != None && "Only reset to a valid provider");
+ m_provider = new_provider;
+}
+
+bool RichManglingContext::FromItaniumName(const ConstString &mangled) {
+ bool err = m_ipd.partialDemangle(mangled.GetCString());
+ if (!err) {
+ ResetProvider(ItaniumPartialDemangler);
+ }
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE)) {
+ if (!err) {
+ ParseFullName();
+ LLDB_LOG(log, "demangled itanium: {0} -> \"{1}\"", mangled, m_ipd_buf);
+ } else {
+ LLDB_LOG(log, "demangled itanium: {0} -> error: failed to demangle",
+ mangled);
+ }
+ }
+
+ return !err; // true == success
+}
+
+bool RichManglingContext::FromCxxMethodName(const ConstString &demangled) {
+ ResetProvider(PluginCxxLanguage);
+ m_cxx_method_parser = new CPlusPlusLanguage::MethodName(demangled);
+ return true;
+}
+
+bool RichManglingContext::IsCtorOrDtor() const {
+ assert(m_provider != None && "Initialize a provider first");
+ switch (m_provider) {
+ case ItaniumPartialDemangler:
+ return m_ipd.isCtorOrDtor();
+ case PluginCxxLanguage: {
+ // We can only check for destructors here.
+ auto base_name =
+ get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
+ return base_name.startswith("~");
+ }
+ case None:
+ return false;
+ }
+ llvm_unreachable("Fully covered switch above!");
+}
+
+bool RichManglingContext::IsFunction() const {
+ assert(m_provider != None && "Initialize a provider first");
+ switch (m_provider) {
+ case ItaniumPartialDemangler:
+ return m_ipd.isFunction();
+ case PluginCxxLanguage:
+ return get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->IsValid();
+ case None:
+ return false;
+ }
+ llvm_unreachable("Fully covered switch above!");
+}
+
+void RichManglingContext::processIPDStrResult(char *ipd_res, size_t res_size) {
+ // Error case: Clear the buffer.
+ if (LLVM_UNLIKELY(ipd_res == nullptr)) {
+ assert(res_size == m_ipd_buf_size &&
+ "Failed IPD queries keep the original size in the N parameter");
+
+ m_ipd_buf[0] = '\0';
+ m_buffer = llvm::StringRef(m_ipd_buf, 0);
+ return;
+ }
+
+ // IPD's res_size includes null terminator.
+ assert(ipd_res[res_size - 1] == '\0' &&
+ "IPD returns null-terminated strings and we rely on that");
+
+ // Update buffer/size on realloc.
+ if (LLVM_UNLIKELY(ipd_res != m_ipd_buf || res_size > m_ipd_buf_size)) {
+ m_ipd_buf = ipd_res; // std::realloc freed or reused the old buffer.
+ m_ipd_buf_size = res_size; // May actually be bigger, but we can't know.
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE))
+ LLDB_LOG(log, "ItaniumPartialDemangler Realloc: new buffer size is {0}",
+ m_ipd_buf_size);
+ }
+
+ // 99% case: Just remember the string length.
+ m_buffer = llvm::StringRef(m_ipd_buf, res_size - 1);
+}
+
+void RichManglingContext::ParseFunctionBaseName() {
+ assert(m_provider != None && "Initialize a provider first");
+ switch (m_provider) {
+ case ItaniumPartialDemangler: {
+ auto n = m_ipd_buf_size;
+ auto buf = m_ipd.getFunctionBaseName(m_ipd_buf, &n);
+ processIPDStrResult(buf, n);
+ return;
+ }
+ case PluginCxxLanguage:
+ m_buffer =
+ get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetBasename();
+ return;
+ case None:
+ return;
+ }
+}
+
+void RichManglingContext::ParseFunctionDeclContextName() {
+ assert(m_provider != None && "Initialize a provider first");
+ switch (m_provider) {
+ case ItaniumPartialDemangler: {
+ auto n = m_ipd_buf_size;
+ auto buf = m_ipd.getFunctionDeclContextName(m_ipd_buf, &n);
+ processIPDStrResult(buf, n);
+ return;
+ }
+ case PluginCxxLanguage:
+ m_buffer =
+ get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)->GetContext();
+ return;
+ case None:
+ return;
+ }
+}
+
+void RichManglingContext::ParseFullName() {
+ assert(m_provider != None && "Initialize a provider first");
+ switch (m_provider) {
+ case ItaniumPartialDemangler: {
+ auto n = m_ipd_buf_size;
+ auto buf = m_ipd.finishDemangle(m_ipd_buf, &n);
+ processIPDStrResult(buf, n);
+ return;
+ }
+ case PluginCxxLanguage:
+ m_buffer = get<CPlusPlusLanguage::MethodName>(m_cxx_method_parser)
+ ->GetFullName()
+ .GetStringRef();
+ return;
+ case None:
+ return;
+ }
+}
diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp
index 0701955233a1..5d26c715bec6 100644
--- a/source/Core/SearchFilter.cpp
+++ b/source/Core/SearchFilter.cpp
@@ -9,26 +9,27 @@
#include "lldb/Core/SearchFilter.h"
-#include "lldb/Breakpoint/Breakpoint.h" // for Breakpoint
+#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h" // for ModuleList
+#include "lldb/Core/ModuleList.h"
#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/Utility/Stream.h" // for Stream
-#include "lldb/lldb-enumerations.h" // for SymbolContextItem::eSymbolCo...
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-enumerations.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
-#include "llvm/Support/ErrorHandling.h" // for llvm_unreachable
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
-#include <memory> // for shared_ptr
-#include <mutex> // for recursive_mutex, lock_guard
-#include <string> // for string
+#include <memory>
+#include <mutex>
+#include <string>
-#include <inttypes.h> // for PRIu64
-#include <string.h> // for size_t, strcmp
+#include <inttypes.h>
+#include <string.h>
namespace lldb_private {
class Address;
@@ -147,6 +148,15 @@ bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; }
bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; }
+bool SearchFilter::FunctionPasses(Function &function) {
+ // This is a slightly cheesy job, but since we don't have finer grained
+ // filters yet, just checking that the start address passes is probably
+ // good enough for the base class behavior.
+ Address addr = function.GetAddressRange().GetBaseAddress();
+ return AddressPasses(addr);
+}
+
+
uint32_t SearchFilter::GetFilterRequiredItems() {
return (lldb::SymbolContextItem)0;
}
@@ -207,7 +217,7 @@ void SearchFilter::Search(Searcher &searcher) {
return;
empty_sc.target_sp = m_target_sp;
- if (searcher.GetDepth() == Searcher::eDepthTarget)
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget)
searcher.SearchCallback(*this, empty_sc, nullptr, false);
else
DoModuleIteration(empty_sc, searcher);
@@ -220,7 +230,7 @@ void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) {
return;
empty_sc.target_sp = m_target_sp;
- if (searcher.GetDepth() == Searcher::eDepthTarget)
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget)
searcher.SearchCallback(*this, empty_sc, nullptr, false);
else {
std::lock_guard<std::recursive_mutex> guard(modules.GetMutex());
@@ -247,9 +257,9 @@ SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp,
Searcher::CallbackReturn
SearchFilter::DoModuleIteration(const SymbolContext &context,
Searcher &searcher) {
- if (searcher.GetDepth() >= Searcher::eDepthModule) {
+ if (searcher.GetDepth() >= lldb::eSearchDepthModule) {
if (context.module_sp) {
- if (searcher.GetDepth() == Searcher::eDepthModule) {
+ if (searcher.GetDepth() == lldb::eSearchDepthModule) {
SymbolContext matchingContext(context.module_sp.get());
searcher.SearchCallback(*this, matchingContext, nullptr, false);
} else {
@@ -267,7 +277,7 @@ SearchFilter::DoModuleIteration(const SymbolContext &context,
if (!ModulePasses(module_sp))
continue;
- if (searcher.GetDepth() == Searcher::eDepthModule) {
+ if (searcher.GetDepth() == lldb::eSearchDepthModule) {
SymbolContext matchingContext(m_target_sp, module_sp);
Searcher::CallbackReturn shouldContinue =
@@ -301,7 +311,7 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp,
if (!CompUnitPasses(*(cu_sp.get())))
continue;
- if (searcher.GetDepth() == Searcher::eDepthCompUnit) {
+ if (searcher.GetDepth() == lldb::eSearchDepthCompUnit) {
SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get());
shouldContinue =
@@ -312,7 +322,30 @@ SearchFilter::DoCUIteration(const ModuleSP &module_sp,
else if (shouldContinue == Searcher::eCallbackReturnStop)
return shouldContinue;
} else {
- // FIXME Descend to block.
+ // First make sure this compile unit's functions are parsed
+ // since CompUnit::ForeachFunction only iterates over already
+ // parsed functions.
+ SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
+ if (!sym_vendor)
+ continue;
+ if (!sym_vendor->ParseFunctions(*cu_sp))
+ continue;
+ // If we got any functions, use ForeachFunction to do the iteration.
+ cu_sp->ForeachFunction([&](const FunctionSP &func_sp) {
+ if (!FunctionPasses(*func_sp.get()))
+ return false; // Didn't pass the filter, just keep going.
+ if (searcher.GetDepth() == lldb::eSearchDepthFunction) {
+ SymbolContext matchingContext(m_target_sp, module_sp,
+ cu_sp.get(), func_sp.get());
+ shouldContinue = searcher.SearchCallback(*this,
+ matchingContext,
+ nullptr, false);
+ } else {
+ shouldContinue = DoFunctionIteration(func_sp.get(), context,
+ searcher);
+ }
+ return shouldContinue != Searcher::eCallbackReturnContinue;
+ });
}
}
}
@@ -353,10 +386,7 @@ SearchFilterForUnconstrainedSearches::SerializeToStructuredData() {
bool SearchFilterForUnconstrainedSearches::ModulePasses(
const FileSpec &module_spec) {
- if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec))
- return false;
- else
- return true;
+ return !m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec);
}
bool SearchFilterForUnconstrainedSearches::ModulePasses(
@@ -421,7 +451,7 @@ void SearchFilterByModule::Search(Searcher &searcher) {
if (!m_target_sp)
return;
- if (searcher.GetDepth() == Searcher::eDepthTarget) {
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
SymbolContext empty_sc;
empty_sc.target_sp = m_target_sp;
searcher.SearchCallback(*this, empty_sc, nullptr, false);
@@ -489,7 +519,7 @@ SearchFilterSP SearchFilterByModule::CreateFromStructuredData(
error.SetErrorString("SFBM::CFSD: filter module item not a string.");
return nullptr;
}
- FileSpec module_spec(module, false);
+ FileSpec module_spec(module);
return std::make_shared<SearchFilterByModule>(target.shared_from_this(),
module_spec);
@@ -535,22 +565,15 @@ bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) {
if (m_module_spec_list.GetSize() == 0)
return true;
- if (module_sp &&
- m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) !=
- UINT32_MAX)
- return true;
- else
- return false;
+ return module_sp && m_module_spec_list.FindFileIndex(
+ 0, module_sp->GetFileSpec(), false) != UINT32_MAX;
}
bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) {
if (m_module_spec_list.GetSize() == 0)
return true;
- if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX)
- return true;
- else
- return false;
+ return m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX;
}
bool SearchFilterByModuleList::AddressPasses(Address &address) {
@@ -570,7 +593,7 @@ void SearchFilterByModuleList::Search(Searcher &searcher) {
if (!m_target_sp)
return;
- if (searcher.GetDepth() == Searcher::eDepthTarget) {
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
SymbolContext empty_sc;
empty_sc.target_sp = m_target_sp;
searcher.SearchCallback(*this, empty_sc, nullptr, false);
@@ -645,7 +668,7 @@ SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData(
"SFBM::CFSD: filter module item %zu not a string.", i);
return nullptr;
}
- modules.Append(FileSpec(module, false));
+ modules.Append(FileSpec(module));
}
}
@@ -710,7 +733,7 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
"SFBM::CFSD: filter module item %zu not a string.", i);
return result_sp;
}
- modules.Append(FileSpec(module, false));
+ modules.Append(FileSpec(module));
}
}
@@ -732,7 +755,7 @@ lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData(
"SFBM::CFSD: filter cu item %zu not a string.", i);
return nullptr;
}
- cus.Append(FileSpec(cu, false));
+ cus.Append(FileSpec(cu));
}
return std::make_shared<SearchFilterByModuleListAndCU>(
@@ -748,7 +771,15 @@ SearchFilterByModuleListAndCU::SerializeToStructuredData() {
}
bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) {
- return true;
+ SymbolContext sym_ctx;
+ address.CalculateSymbolContext(&sym_ctx, eSymbolContextEverything);
+ if (!sym_ctx.comp_unit) {
+ if (m_cu_spec_list.GetSize() != 0)
+ return false; // Has no comp_unit so can't pass the file check.
+ }
+ if (m_cu_spec_list.FindFileIndex(0, sym_ctx.comp_unit, false) == UINT32_MAX)
+ return false; // Fails the file check
+ return SearchFilterByModuleList::ModulePasses(sym_ctx.module_sp);
}
bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) {
@@ -773,7 +804,7 @@ void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
if (!m_target_sp)
return;
- if (searcher.GetDepth() == Searcher::eDepthTarget) {
+ if (searcher.GetDepth() == lldb::eSearchDepthTarget) {
SymbolContext empty_sc;
empty_sc.target_sp = m_target_sp;
searcher.SearchCallback(*this, empty_sc, nullptr, false);
@@ -797,7 +828,7 @@ void SearchFilterByModuleListAndCU::Search(Searcher &searcher) {
SymbolContext matchingContext(m_target_sp, module_sp);
Searcher::CallbackReturn shouldContinue;
- if (searcher.GetDepth() == Searcher::eDepthModule) {
+ if (searcher.GetDepth() == lldb::eSearchDepthModule) {
shouldContinue = DoModuleIteration(matchingContext, searcher);
if (shouldContinue == Searcher::eCallbackReturnStop)
return;
diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp
index d9c5d32ee13c..87f75e1f50ac 100644
--- a/source/Core/Section.cpp
+++ b/source/Core/Section.cpp
@@ -8,18 +8,18 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/Section.h"
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/FileSpec.h" // for FileSpec
-#include "lldb/Utility/Stream.h" // for Stream
-#include "lldb/Utility/VMRange.h" // for VMRange
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/VMRange.h"
-#include <inttypes.h> // for PRIx64
-#include <limits> // for numeric_limits
-#include <utility> // for distance
+#include <inttypes.h>
+#include <limits>
+#include <utility>
namespace lldb_private {
class DataExtractor;
@@ -61,6 +61,8 @@ const char *Section::GetTypeAsCString() const {
return "objc-cfstrings";
case eSectionTypeDWARFDebugAbbrev:
return "dwarf-abbrev";
+ case eSectionTypeDWARFDebugAbbrevDwo:
+ return "dwarf-abbrev-dwo";
case eSectionTypeDWARFDebugAddr:
return "dwarf-addr";
case eSectionTypeDWARFDebugAranges:
@@ -71,10 +73,16 @@ const char *Section::GetTypeAsCString() const {
return "dwarf-frame";
case eSectionTypeDWARFDebugInfo:
return "dwarf-info";
+ case eSectionTypeDWARFDebugInfoDwo:
+ return "dwarf-info-dwo";
case eSectionTypeDWARFDebugLine:
return "dwarf-line";
+ case eSectionTypeDWARFDebugLineStr:
+ return "dwarf-line-str";
case eSectionTypeDWARFDebugLoc:
return "dwarf-loc";
+ case eSectionTypeDWARFDebugLocLists:
+ return "dwarf-loclists";
case eSectionTypeDWARFDebugMacInfo:
return "dwarf-macinfo";
case eSectionTypeDWARFDebugMacro:
@@ -85,10 +93,16 @@ const char *Section::GetTypeAsCString() const {
return "dwarf-pubtypes";
case eSectionTypeDWARFDebugRanges:
return "dwarf-ranges";
+ case eSectionTypeDWARFDebugRngLists:
+ return "dwarf-rnglists";
case eSectionTypeDWARFDebugStr:
return "dwarf-str";
+ case eSectionTypeDWARFDebugStrDwo:
+ return "dwarf-str-dwo";
case eSectionTypeDWARFDebugStrOffsets:
return "dwarf-str-offsets";
+ case eSectionTypeDWARFDebugStrOffsetsDwo:
+ return "dwarf-str-offsets-dwo";
case eSectionTypeDWARFDebugTypes:
return "dwarf-types";
case eSectionTypeDWARFDebugNames:
diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp
index a6afd64f3054..fe603c5a44e6 100644
--- a/source/Core/SourceManager.cpp
+++ b/source/Core/SourceManager.cpp
@@ -9,33 +9,34 @@
#include "lldb/Core/SourceManager.h"
-#include "lldb/Core/Address.h" // for Address
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/FormatEntity.h" // for FormatEntity
+#include "lldb/Core/FormatEntity.h"
+#include "lldb/Core/Highlighter.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/ModuleList.h" // for ModuleList
+#include "lldb/Core/ModuleList.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/LineEntry.h" // for LineEntry
+#include "lldb/Symbol/LineEntry.h"
#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Target/PathMappingList.h" // for PathMappingList
+#include "lldb/Target/PathMappingList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-enumerations.h" // for StopShowColumn::eStopSho...
+#include "lldb/lldb-enumerations.h"
-#include "llvm/ADT/Twine.h" // for Twine
+#include "llvm/ADT/Twine.h"
#include <memory>
-#include <utility> // for pair
+#include <utility>
-#include <assert.h> // for assert
-#include <stdio.h> // for size_t, NULL, snprintf
+#include <assert.h>
+#include <stdio.h>
namespace lldb_private {
class ExecutionContext;
@@ -91,7 +92,7 @@ SourceManager::FileSP SourceManager::GetFile(const FileSpec &file_spec) {
file_sp->UpdateIfNeeded();
// If file_sp is no good or it points to a non-existent file, reset it.
- if (!file_sp || !file_sp->GetFileSpec().Exists()) {
+ if (!file_sp || !FileSystem::Instance().Exists(file_sp->GetFileSpec())) {
if (target_sp)
file_sp = std::make_shared<File>(file_spec, target_sp.get());
else
@@ -103,6 +104,18 @@ SourceManager::FileSP SourceManager::GetFile(const FileSpec &file_spec) {
return file_sp;
}
+static bool should_highlight_source(DebuggerSP debugger_sp) {
+ if (!debugger_sp)
+ return false;
+
+ // We don't use ANSI stop column formatting if the debugger doesn't think it
+ // should be using color.
+ if (!debugger_sp->GetUseColor())
+ return false;
+
+ return debugger_sp->GetHighlightSource();
+}
+
static bool should_show_stop_column_with_ansi(DebuggerSP debugger_sp) {
// We don't use ANSI stop column formatting if we can't lookup values from
// the debugger.
@@ -145,7 +158,9 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile(
const SymbolContextList *bp_locs) {
if (count == 0)
return 0;
- size_t return_value = 0;
+
+ Stream::ByteDelta delta(*s);
+
if (start_line == 0) {
if (m_last_line != 0 && m_last_line != UINT32_MAX)
start_line = m_last_line + m_last_count;
@@ -180,31 +195,37 @@ size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile(
::snprintf(prefix, sizeof(prefix), " ");
}
- return_value +=
- s->Printf("%s%2.2s %-4u\t", prefix,
- line == curr_line ? current_line_cstr : "", line);
- size_t this_line_size = m_last_file_sp->DisplaySourceLines(
- line, line == curr_line ? column : 0, 0, 0, s);
+ s->Printf("%s%2.2s %-4u\t", prefix,
+ line == curr_line ? current_line_cstr : "", line);
+
+ // So far we treated column 0 as a special 'no column value', but
+ // DisplaySourceLines starts counting columns from 0 (and no column is
+ // expressed by passing an empty optional).
+ llvm::Optional<size_t> columnToHighlight;
+ if (line == curr_line && column)
+ columnToHighlight = column - 1;
+
+ size_t this_line_size =
+ m_last_file_sp->DisplaySourceLines(line, columnToHighlight, 0, 0, s);
if (column != 0 && line == curr_line &&
should_show_stop_column_with_caret(m_debugger_wp.lock())) {
// Display caret cursor.
std::string src_line;
m_last_file_sp->GetLine(line, src_line);
- return_value += s->Printf(" \t");
+ s->Printf(" \t");
// Insert a space for every non-tab character in the source line.
for (size_t i = 0; i + 1 < column && i < src_line.length(); ++i)
- return_value += s->PutChar(src_line[i] == '\t' ? '\t' : ' ');
+ s->PutChar(src_line[i] == '\t' ? '\t' : ' ');
// Now add the caret.
- return_value += s->Printf("^\n");
+ s->Printf("^\n");
}
if (this_line_size == 0) {
m_last_line = UINT32_MAX;
break;
- } else
- return_value += this_line_size;
+ }
}
}
- return return_value;
+ return *delta;
}
size_t SourceManager::DisplaySourceLinesWithLineNumbers(
@@ -349,14 +370,14 @@ void SourceManager::FindLinesMatchingRegex(FileSpec &file_spec,
SourceManager::File::File(const FileSpec &file_spec,
lldb::DebuggerSP debugger_sp)
: m_file_spec_orig(file_spec), m_file_spec(file_spec),
- m_mod_time(FileSystem::GetModificationTime(file_spec)),
+ m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
m_debugger_wp(debugger_sp) {
CommonInitializer(file_spec, nullptr);
}
SourceManager::File::File(const FileSpec &file_spec, Target *target)
: m_file_spec_orig(file_spec), m_file_spec(file_spec),
- m_mod_time(FileSystem::GetModificationTime(file_spec)),
+ m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)),
m_debugger_wp(target ? target->GetDebugger().shared_from_this()
: DebuggerSP()) {
CommonInitializer(file_spec, target);
@@ -376,7 +397,8 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec,
size_t num_matches =
target->GetImages().ResolveSymbolContextForFilePath(
file_spec.GetFilename().AsCString(), 0, check_inlines,
- lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit,
+ SymbolContextItem(eSymbolContextModule |
+ eSymbolContextCompUnit),
sc_list);
bool got_multiple = false;
if (num_matches != 0) {
@@ -400,12 +422,12 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec,
SymbolContext sc;
sc_list.GetContextAtIndex(0, sc);
m_file_spec = sc.comp_unit;
- m_mod_time = FileSystem::GetModificationTime(m_file_spec);
+ m_mod_time = FileSystem::Instance().GetModificationTime(m_file_spec);
}
}
}
// Try remapping if m_file_spec does not correspond to an existing file.
- if (!m_file_spec.Exists()) {
+ if (!FileSystem::Instance().Exists(m_file_spec)) {
FileSpec new_file_spec;
// Check target specific source remappings first, then fall back to
// modules objects can have individual path remappings that were
@@ -413,14 +435,14 @@ void SourceManager::File::CommonInitializer(const FileSpec &file_spec,
if (target->GetSourcePathMap().FindFile(m_file_spec, new_file_spec) ||
target->GetImages().FindSourceFile(m_file_spec, new_file_spec)) {
m_file_spec = new_file_spec;
- m_mod_time = FileSystem::GetModificationTime(m_file_spec);
+ m_mod_time = FileSystem::Instance().GetModificationTime(m_file_spec);
}
}
}
}
if (m_mod_time != llvm::sys::TimePoint<>())
- m_data_sp = DataBufferLLVM::CreateFromPath(m_file_spec.GetPath());
+ m_data_sp = FileSystem::Instance().CreateDataBuffer(m_file_spec);
}
uint32_t SourceManager::File::GetLineOffset(uint32_t line) {
@@ -464,7 +486,7 @@ uint32_t SourceManager::File::GetLineLength(uint32_t line,
if (end_offset > start_offset) {
uint32_t length = end_offset - start_offset;
- if (include_newline_chars == false) {
+ if (!include_newline_chars) {
const char *line_start =
(const char *)m_data_sp->GetBytes() + start_offset;
while (length > 0) {
@@ -493,17 +515,18 @@ void SourceManager::File::UpdateIfNeeded() {
// TODO: use host API to sign up for file modifications to anything in our
// source cache and only update when we determine a file has been updated.
// For now we check each time we want to display info for the file.
- auto curr_mod_time = FileSystem::GetModificationTime(m_file_spec);
+ auto curr_mod_time = FileSystem::Instance().GetModificationTime(m_file_spec);
if (curr_mod_time != llvm::sys::TimePoint<>() &&
m_mod_time != curr_mod_time) {
m_mod_time = curr_mod_time;
- m_data_sp = DataBufferLLVM::CreateFromPath(m_file_spec.GetPath());
+ m_data_sp = FileSystem::Instance().CreateDataBuffer(m_file_spec);
m_offsets.clear();
}
}
-size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
+size_t SourceManager::File::DisplaySourceLines(uint32_t line,
+ llvm::Optional<size_t> column,
uint32_t context_before,
uint32_t context_after,
Stream *s) {
@@ -515,6 +538,27 @@ size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
if (!m_data_sp)
return 0;
+ size_t bytes_written = s->GetWrittenBytes();
+
+ auto debugger_sp = m_debugger_wp.lock();
+
+ HighlightStyle style;
+ // Use the default Vim style if source highlighting is enabled.
+ if (should_highlight_source(debugger_sp))
+ style = HighlightStyle::MakeVimStyle();
+
+ // If we should mark the stop column with color codes, then copy the prefix
+ // and suffix to our color style.
+ if (should_show_stop_column_with_ansi(debugger_sp))
+ style.selected.Set(debugger_sp->GetStopShowColumnAnsiPrefix(),
+ debugger_sp->GetStopShowColumnAnsiSuffix());
+
+ HighlighterManager mgr;
+ std::string path = GetFileSpec().GetPath(/*denormalize*/ false);
+ // FIXME: Find a way to get the definitive language this file was written in
+ // and pass it to the highlighter.
+ const auto &h = mgr.getHighlighterFor(lldb::eLanguageTypeUnknown, path);
+
const uint32_t start_line =
line <= context_before ? 1 : line - context_before;
const uint32_t start_line_offset = GetLineOffset(start_line);
@@ -525,71 +569,20 @@ size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column,
end_line_offset = m_data_sp->GetByteSize();
assert(start_line_offset <= end_line_offset);
- size_t bytes_written = 0;
if (start_line_offset < end_line_offset) {
size_t count = end_line_offset - start_line_offset;
const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset;
- bool displayed_line = false;
-
- if (column && (column < count)) {
- auto debugger_sp = m_debugger_wp.lock();
- if (should_show_stop_column_with_ansi(debugger_sp) && debugger_sp) {
- // Check if we have any ANSI codes with which to mark this column. If
- // not, no need to do this work.
- auto ansi_prefix_entry = debugger_sp->GetStopShowColumnAnsiPrefix();
- auto ansi_suffix_entry = debugger_sp->GetStopShowColumnAnsiSuffix();
-
- // We only bother breaking up the line to format the marked column if
- // there is any marking specified on both sides of the marked column.
- // In ANSI-terminal-sequence land, there must be a post if there is a
- // pre format, and vice versa.
- if (ansi_prefix_entry && ansi_suffix_entry) {
- // Mark the current column with the desired escape sequence for
- // formatting the column (e.g. underline, inverse, etc.)
-
- // First print the part before the column to mark.
- bytes_written = s->Write(cstr, column - 1);
-
- // Write the pre escape sequence.
- const SymbolContext *sc = nullptr;
- const ExecutionContext *exe_ctx = nullptr;
- const Address addr = LLDB_INVALID_ADDRESS;
- ValueObject *valobj = nullptr;
- const bool function_changed = false;
- const bool initial_function = false;
-
- FormatEntity::Format(*ansi_prefix_entry, *s, sc, exe_ctx, &addr,
- valobj, function_changed, initial_function);
-
- // Write the marked column.
- bytes_written += s->Write(cstr + column - 1, 1);
-
- // Write the post escape sequence.
- FormatEntity::Format(*ansi_suffix_entry, *s, sc, exe_ctx, &addr,
- valobj, function_changed, initial_function);
-
- // And finish up with the rest of the line.
- bytes_written += s->Write(cstr + column, count - column);
-
- // Keep track of the fact that we just wrote the line.
- displayed_line = true;
- }
- }
- }
+ auto ref = llvm::StringRef(reinterpret_cast<const char *>(cstr), count);
- // If we didn't end up displaying the line with ANSI codes for whatever
- // reason, display it now sans codes.
- if (!displayed_line)
- bytes_written = s->Write(cstr, count);
+ h.Highlight(style, ref, column, "", *s);
// Ensure we get an end of line character one way or another.
- if (!is_newline_char(cstr[count - 1]))
- bytes_written += s->EOL();
+ if (!is_newline_char(ref.back()))
+ s->EOL();
}
- return bytes_written;
}
- return 0;
+ return s->GetWrittenBytes() - bytes_written;
}
void SourceManager::File::FindLinesMatchingRegex(
diff --git a/source/Core/StreamAsynchronousIO.cpp b/source/Core/StreamAsynchronousIO.cpp
index aae8636bff09..b8938bd3fc4e 100644
--- a/source/Core/StreamAsynchronousIO.cpp
+++ b/source/Core/StreamAsynchronousIO.cpp
@@ -10,7 +10,7 @@
#include "lldb/Core/StreamAsynchronousIO.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/lldb-enumerations.h" // for ByteOrder::eByteOrderBig
+#include "lldb/lldb-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -31,7 +31,7 @@ void StreamAsynchronousIO::Flush() {
}
}
-size_t StreamAsynchronousIO::Write(const void *s, size_t length) {
+size_t StreamAsynchronousIO::WriteImpl(const void *s, size_t length) {
m_data.append((const char *)s, length);
return length;
}
diff --git a/source/Core/StreamFile.cpp b/source/Core/StreamFile.cpp
index f59415485021..d24634598c36 100644
--- a/source/Core/StreamFile.cpp
+++ b/source/Core/StreamFile.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/StreamFile.h"
+#include "lldb/Host/FileSystem.h"
#include <stdio.h>
@@ -28,20 +29,24 @@ StreamFile::StreamFile(int fd, bool transfer_ownership)
StreamFile::StreamFile(FILE *fh, bool transfer_ownership)
: Stream(), m_file(fh, transfer_ownership) {}
-StreamFile::StreamFile(const char *path)
- : Stream(),
- m_file(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
- File::eOpenOptionCloseOnExec,
- lldb::eFilePermissionsFileDefault) {}
+StreamFile::StreamFile(const char *path) : Stream(), m_file() {
+ FileSystem::Instance().Open(m_file, FileSpec(path),
+ File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate |
+ File::eOpenOptionCloseOnExec);
+}
StreamFile::StreamFile(const char *path, uint32_t options, uint32_t permissions)
- : Stream(), m_file(path, options, permissions) {}
+ : Stream(), m_file() {
+
+ FileSystem::Instance().Open(m_file, FileSpec(path), options, permissions);
+}
StreamFile::~StreamFile() {}
void StreamFile::Flush() { m_file.Flush(); }
-size_t StreamFile::Write(const void *s, size_t length) {
+size_t StreamFile::WriteImpl(const void *s, size_t length) {
m_file.Write(s, length);
return length;
}
diff --git a/source/Core/UserSettingsController.cpp b/source/Core/UserSettingsController.cpp
index a4661a6c9e8c..4406057ca6b9 100644
--- a/source/Core/UserSettingsController.cpp
+++ b/source/Core/UserSettingsController.cpp
@@ -13,7 +13,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
-#include <memory> // for shared_ptr
+#include <memory>
namespace lldb_private {
class CommandInterpreter;
diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp
index 254c9008babb..8e18458b90c2 100644
--- a/source/Core/Value.cpp
+++ b/source/Core/Value.cpp
@@ -9,9 +9,8 @@
#include "lldb/Core/Value.h"
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -21,20 +20,21 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/Endian.h" // for InlHostByteOrder
-#include "lldb/Utility/FileSpec.h" // for FileSpec
+#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-forward.h" // for DataBufferSP, ModuleSP
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
-#include <memory> // for make_shared
-#include <string> // for string
+#include <memory>
+#include <string>
-#include <inttypes.h> // for PRIx64
+#include <inttypes.h>
using namespace lldb;
using namespace lldb_private;
@@ -210,34 +210,31 @@ bool Value::ValueOf(ExecutionContext *exe_ctx) {
}
uint64_t Value::GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx) {
- uint64_t byte_size = 0;
-
switch (m_context_type) {
case eContextTypeRegisterInfo: // RegisterInfo *
- if (GetRegisterInfo())
- byte_size = GetRegisterInfo()->byte_size;
+ if (GetRegisterInfo()) {
+ if (error_ptr)
+ error_ptr->Clear();
+ return GetRegisterInfo()->byte_size;
+ }
break;
case eContextTypeInvalid:
case eContextTypeLLDBType: // Type *
case eContextTypeVariable: // Variable *
{
- const CompilerType &ast_type = GetCompilerType();
- if (ast_type.IsValid())
- byte_size = ast_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
- } break;
- }
-
- if (error_ptr) {
- if (byte_size == 0) {
- if (error_ptr->Success())
- error_ptr->SetErrorString("Unable to determine byte size.");
- } else {
- error_ptr->Clear();
+ auto *scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
+ if (llvm::Optional<uint64_t> size = GetCompilerType().GetByteSize(scope)) {
+ if (error_ptr)
+ error_ptr->Clear();
+ return *size;
}
+ break;
}
- return byte_size;
+ }
+ if (error_ptr && error_ptr->Success())
+ error_ptr->SetErrorString("Unable to determine byte size.");
+ return 0;
}
const CompilerType &Value::GetCompilerType() {
@@ -344,10 +341,9 @@ Status Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data,
uint32_t limit_byte_size = UINT32_MAX;
- if (ast_type.IsValid()) {
- limit_byte_size = ast_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
- }
+ if (llvm::Optional<uint64_t> size = ast_type.GetByteSize(
+ exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr))
+ limit_byte_size = *size;
if (limit_byte_size <= m_value.GetByteSize()) {
if (m_value.GetData(data, limit_byte_size))
diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp
index 244ea2936fb4..95e944b22b87 100644
--- a/source/Core/ValueObject.cpp
+++ b/source/Core/ValueObject.cpp
@@ -9,9 +9,8 @@
#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/Address.h" // for Address
+#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/Scalar.h" // for Scalar
#include "lldb/Core/ValueObjectCast.h"
#include "lldb/Core/ValueObjectChild.h"
#include "lldb/Core/ValueObjectConstResult.h"
@@ -19,51 +18,52 @@
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectSyntheticFilter.h"
#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/DumpValueObjectOptions.h" // for DumpValueObj...
-#include "lldb/DataFormatters/FormatManager.h" // for FormatManager
+#include "lldb/DataFormatters/DumpValueObjectOptions.h"
+#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/DataFormatters/StringPrinter.h"
-#include "lldb/DataFormatters/TypeFormat.h" // for TypeFormatImpl_F...
-#include "lldb/DataFormatters/TypeSummary.h" // for TypeSummaryOptions
-#include "lldb/DataFormatters/TypeValidator.h" // for TypeValidatorImp...
+#include "lldb/DataFormatters/TypeFormat.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
-#include "lldb/Expression/ExpressionVariable.h" // for ExpressionVariable
+#include "lldb/Expression/ExpressionVariable.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/Declaration.h" // for Declaration
-#include "lldb/Symbol/SymbolContext.h" // for SymbolContext
+#include "lldb/Symbol/Declaration.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
-#include "lldb/Target/StackFrame.h" // for StackFrame
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Target/ThreadList.h" // for ThreadList
-#include "lldb/Utility/DataBuffer.h" // for DataBuffer
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/Flags.h" // for Flags
+#include "lldb/Utility/Flags.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCateg...
-#include "lldb/Utility/SharingPtr.h" // for SharingPtr
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/SharingPtr.h"
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "lldb/lldb-private-types.h" // for RegisterInfo
+#include "lldb/lldb-private-types.h"
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
+#include "llvm/Support/Compiler.h"
-#include <algorithm> // for min
-#include <cstdint> // for uint32_t, uint64_t
-#include <cstdlib> // for size_t, NULL
-#include <memory> // for shared_ptr, oper...
-#include <tuple> // for tie, tuple
+#include <algorithm>
+#include <cstdint>
+#include <cstdlib>
+#include <memory>
+#include <tuple>
-#include <assert.h> // for assert
-#include <inttypes.h> // for PRIu64, PRIx64
-#include <stdio.h> // for snprintf
-#include <string.h> // for memcpy, memcmp
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
namespace lldb_private {
class ExecutionContextScope;
@@ -214,7 +214,7 @@ bool ValueObject::UpdateValueIfNeeded(bool update_format) {
if (first_update)
SetValueDidChange(false);
- else if (!m_value_did_change && success == false) {
+ else if (!m_value_did_change && !success) {
// The value wasn't gotten successfully, so we mark this as changed if
// the value used to be valid and now isn't
SetValueDidChange(value_was_valid);
@@ -442,10 +442,7 @@ bool ValueObject::IsLogicalTrue(Status &error) {
}
bool ret;
- if (scalar_value.ULongLong(1) == 0)
- ret = false;
- else
- ret = true;
+ ret = scalar_value.ULongLong(1) != 0;
error.Clear();
return ret;
}
@@ -639,7 +636,7 @@ ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
bool child_is_deref_of_parent = false;
uint64_t language_flags = 0;
- const bool transparent_pointers = synthetic_array_member == false;
+ const bool transparent_pointers = !synthetic_array_member;
CompilerType child_compiler_type;
ExecutionContext exe_ctx(GetExecutionContextRef());
@@ -662,8 +659,6 @@ ValueObject *ValueObject::CreateChildAtIndex(size_t idx,
child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid,
language_flags);
- // if (valobj)
- // valobj->SetAddressTypeOfChildren(eAddressTypeInvalid);
}
return valobj;
@@ -761,10 +756,13 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
ExecutionContext exe_ctx(GetExecutionContextRef());
- const uint64_t item_type_size = pointee_or_element_compiler_type.GetByteSize(
- exe_ctx.GetBestExecutionContextScope());
- const uint64_t bytes = item_count * item_type_size;
- const uint64_t offset = item_idx * item_type_size;
+ llvm::Optional<uint64_t> item_type_size =
+ pointee_or_element_compiler_type.GetByteSize(
+ exe_ctx.GetBestExecutionContextScope());
+ if (!item_type_size)
+ return 0;
+ const uint64_t bytes = item_count * *item_type_size;
+ const uint64_t offset = item_idx * *item_type_size;
if (item_idx == 0 && item_count == 1) // simply a deref
{
@@ -827,10 +825,10 @@ size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx,
}
} break;
case eAddressTypeHost: {
- const uint64_t max_bytes =
+ auto max_bytes =
GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope());
- if (max_bytes > offset) {
- size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes);
+ if (max_bytes && *max_bytes > offset) {
+ size_t bytes_read = std::min<uint64_t>(*max_bytes - offset, bytes);
addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
if (addr == 0 || addr == LLDB_INVALID_ADDRESS)
break;
@@ -1823,14 +1821,16 @@ ValueObjectSP ValueObject::GetSyntheticChildAtOffset(
return synthetic_child_sp;
if (!can_create)
- return ValueObjectSP();
+ return {};
ExecutionContext exe_ctx(GetExecutionContextRef());
-
- ValueObjectChild *synthetic_child = new ValueObjectChild(
- *this, type, name_const_str,
- type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), offset, 0, 0,
- false, false, eAddressTypeInvalid, 0);
+ llvm::Optional<uint64_t> size =
+ type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ if (!size)
+ return {};
+ ValueObjectChild *synthetic_child =
+ new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
+ false, false, eAddressTypeInvalid, 0);
if (synthetic_child) {
AddSyntheticChild(name_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();
@@ -1861,16 +1861,18 @@ ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset,
return synthetic_child_sp;
if (!can_create)
- return ValueObjectSP();
+ return {};
const bool is_base_class = true;
ExecutionContext exe_ctx(GetExecutionContextRef());
-
- ValueObjectChild *synthetic_child = new ValueObjectChild(
- *this, type, name_const_str,
- type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), offset, 0, 0,
- is_base_class, false, eAddressTypeInvalid, 0);
+ llvm::Optional<uint64_t> size =
+ type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ if (!size)
+ return {};
+ ValueObjectChild *synthetic_child =
+ new ValueObjectChild(*this, type, name_const_str, *size, offset, 0, 0,
+ is_base_class, false, eAddressTypeInvalid, 0);
if (synthetic_child) {
AddSyntheticChild(name_const_str, synthetic_child);
synthetic_child_sp = synthetic_child->GetSP();
@@ -1923,11 +1925,11 @@ ValueObject::GetSyntheticExpressionPathChild(const char *expression,
}
void ValueObject::CalculateSyntheticValue(bool use_synthetic) {
- if (use_synthetic == false)
+ if (!use_synthetic)
return;
TargetSP target_sp(GetTargetSP());
- if (target_sp && target_sp->GetEnableSyntheticValue() == false) {
+ if (target_sp && !target_sp->GetEnableSyntheticValue()) {
m_synthetic_value = NULL;
return;
}
@@ -1978,7 +1980,7 @@ ValueObjectSP ValueObject::GetStaticValue() { return GetSP(); }
lldb::ValueObjectSP ValueObject::GetNonSyntheticValue() { return GetSP(); }
ValueObjectSP ValueObject::GetSyntheticValue(bool use_synthetic) {
- if (use_synthetic == false)
+ if (!use_synthetic)
return ValueObjectSP();
CalculateSyntheticValue(use_synthetic);
@@ -1997,10 +1999,7 @@ bool ValueObject::HasSyntheticValue() {
CalculateSyntheticValue(true);
- if (m_synthetic_value)
- return true;
- else
- return false;
+ return m_synthetic_value != nullptr;
}
bool ValueObject::GetBaseClassPath(Stream &s) {
@@ -2806,31 +2805,6 @@ ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable(
return result_sp;
}
-lldb::addr_t ValueObject::GetCPPVTableAddress(AddressType &address_type) {
- CompilerType pointee_type;
- CompilerType this_type(GetCompilerType());
- uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
- if (type_info) {
- bool ptr_or_ref = false;
- if (type_info & (eTypeIsPointer | eTypeIsReference)) {
- ptr_or_ref = true;
- type_info = pointee_type.GetTypeInfo();
- }
-
- const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus;
- if ((type_info & cpp_class) == cpp_class) {
- if (ptr_or_ref) {
- address_type = GetAddressTypeOfChildren();
- return GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- } else
- return GetAddressOf(false, &address_type);
- }
- }
-
- address_type = eAddressTypeInvalid;
- return LLDB_INVALID_ADDRESS;
-}
-
ValueObjectSP ValueObject::Dereference(Status &error) {
if (m_deref_valobj)
return m_deref_valobj->GetSP();
@@ -3222,7 +3196,7 @@ ValueObject *
ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) {
ValueObject *vo = this;
while (vo) {
- if (f(vo) == false)
+ if (!f(vo))
break;
vo = vo->m_parent;
}
@@ -3291,8 +3265,7 @@ bool ValueObject::CanProvideValue() {
// board debugging scenarios have no notion of types, but still manage to
// have raw numeric values for things like registers. sigh.
const CompilerType &type(GetCompilerType());
- return (false == type.IsValid()) ||
- (0 != (type.GetTypeInfo() & eTypeHasValue));
+ return (!type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue));
}
bool ValueObject::IsChecksumEmpty() { return m_value_checksum.empty(); }
diff --git a/source/Core/ValueObjectCast.cpp b/source/Core/ValueObjectCast.cpp
index e0978f692bc5..fb0b55b6efdf 100644
--- a/source/Core/ValueObjectCast.cpp
+++ b/source/Core/ValueObjectCast.cpp
@@ -9,12 +9,12 @@
#include "lldb/Core/ValueObjectCast.h"
-#include "lldb/Core/Scalar.h" // for operator!=, Scalar
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Utility/Status.h" // for Status
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
namespace lldb_private {
class ConstString;
@@ -44,7 +44,9 @@ ValueObjectCast::~ValueObjectCast() {}
CompilerType ValueObjectCast::GetCompilerTypeImpl() { return m_cast_type; }
size_t ValueObjectCast::CalculateNumChildren(uint32_t max) {
- auto children_count = GetCompilerType().GetNumChildren(true);
+ ExecutionContext exe_ctx(GetExecutionContextRef());
+ auto children_count = GetCompilerType().GetNumChildren(
+ true, &exe_ctx);
return children_count <= max ? children_count : max;
}
diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp
index 019daa2fd3d2..0f7be8317dec 100644
--- a/source/Core/ValueObjectChild.cpp
+++ b/source/Core/ValueObjectChild.cpp
@@ -9,21 +9,21 @@
#include "lldb/Core/ValueObjectChild.h"
-#include "lldb/Core/Scalar.h" // for Scalar
-#include "lldb/Core/Value.h" // for Value, Value::ValueType::e...
+#include "lldb/Core/Value.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
-#include "lldb/Utility/Flags.h" // for Flags
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-forward.h" // for ProcessSP, ModuleSP
+#include "lldb/Utility/Flags.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-forward.h"
-#include <functional> // for _Func_impl<>::_Mybase
-#include <memory> // for shared_ptr
-#include <vector> // for vector
+#include <functional>
+#include <memory>
+#include <vector>
-#include <stdio.h> // for snprintf, size_t
-#include <string.h> // for strlen
+#include <stdio.h>
+#include <string.h>
using namespace lldb_private;
@@ -51,7 +51,8 @@ lldb::ValueType ValueObjectChild::GetValueType() const {
}
size_t ValueObjectChild::CalculateNumChildren(uint32_t max) {
- auto children_count = GetCompilerType().GetNumChildren(true);
+ ExecutionContext exe_ctx(GetExecutionContextRef());
+ auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
return children_count <= max ? children_count : max;
}
@@ -123,7 +124,7 @@ bool ValueObjectChild::UpdateValue() {
Flags parent_type_flags(parent_type.GetTypeInfo());
const bool is_instance_ptr_base =
- ((m_is_base_class == true) &&
+ ((m_is_base_class) &&
(parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer)));
if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) {
@@ -141,7 +142,7 @@ bool ValueObjectChild::UpdateValue() {
switch (addr_type) {
case eAddressTypeFile: {
lldb::ProcessSP process_sp(GetProcessSP());
- if (process_sp && process_sp->IsAlive() == true)
+ if (process_sp && process_sp->IsAlive())
m_value.SetValueType(Value::eValueTypeLoadAddress);
else
m_value.SetValueType(Value::eValueTypeFileAddress);
@@ -201,12 +202,9 @@ bool ValueObjectChild::UpdateValue() {
ExecutionContext exe_ctx(
GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped));
if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) {
- if (!is_instance_ptr_base)
- m_error =
- m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
- else
- m_error = m_parent->GetValue().GetValueAsData(&exe_ctx, m_data, 0,
- GetModule().get());
+ Value &value = is_instance_ptr_base ? m_parent->GetValue() : m_value;
+ m_error =
+ value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get());
} else {
m_error.Clear(); // No value so nothing to read...
}
diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp
index 1023696c35a7..f6e32c03b0eb 100644
--- a/source/Core/ValueObjectConstResult.cpp
+++ b/source/Core/ValueObjectConstResult.cpp
@@ -9,15 +9,15 @@
#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Core/Scalar.h" // for Scalar
#include "lldb/Core/ValueObjectDynamicValue.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ExecutionContextScope.h" // for ExecutionContextScope
+#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
-#include "lldb/Utility/DataBuffer.h" // for DataBuffer
-#include "lldb/Utility/DataBufferHeap.h" // for DataBufferHeap
+#include "lldb/Utility/DataBuffer.h"
+#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
namespace lldb_private {
class Module;
@@ -198,17 +198,19 @@ lldb::ValueType ValueObjectConstResult::GetValueType() const {
uint64_t ValueObjectConstResult::GetByteSize() {
ExecutionContext exe_ctx(GetExecutionContextRef());
-
- if (m_byte_size == 0)
- SetByteSize(
- GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()));
+ if (m_byte_size == 0) {
+ if (auto size =
+ GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()))
+ SetByteSize(*size);
+ }
return m_byte_size;
}
void ValueObjectConstResult::SetByteSize(size_t size) { m_byte_size = size; }
size_t ValueObjectConstResult::CalculateNumChildren(uint32_t max) {
- auto children_count = GetCompilerType().GetNumChildren(true);
+ ExecutionContext exe_ctx(GetExecutionContextRef());
+ auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
return children_count <= max ? children_count : max;
}
diff --git a/source/Core/ValueObjectConstResultChild.cpp b/source/Core/ValueObjectConstResultChild.cpp
index 3e9f87684162..441c16479f2c 100644
--- a/source/Core/ValueObjectConstResultChild.cpp
+++ b/source/Core/ValueObjectConstResultChild.cpp
@@ -9,7 +9,7 @@
#include "lldb/Core/ValueObjectConstResultChild.h"
-#include "lldb/lldb-private-enumerations.h" // for AddressType::eAddressType
+#include "lldb/lldb-private-enumerations.h"
namespace lldb_private {
class DataExtractor;
}
@@ -52,6 +52,11 @@ lldb::ValueObjectSP ValueObjectConstResultChild::AddressOf(Status &error) {
return m_impl.AddressOf(error);
}
+lldb::addr_t ValueObjectConstResultChild::GetAddressOf(
+ bool scalar_is_load_address, AddressType* address_type) {
+ return m_impl.GetAddressOf(scalar_is_load_address, address_type);
+}
+
ValueObject *ValueObjectConstResultChild::CreateChildAtIndex(
size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
return m_impl.CreateChildAtIndex(idx, synthetic_array_member,
diff --git a/source/Core/ValueObjectConstResultImpl.cpp b/source/Core/ValueObjectConstResultImpl.cpp
index 714634ed56e3..6bf8e62db067 100644
--- a/source/Core/ValueObjectConstResultImpl.cpp
+++ b/source/Core/ValueObjectConstResultImpl.cpp
@@ -9,19 +9,19 @@
#include "lldb/Core/ValueObjectConstResultImpl.h"
-#include "lldb/Core/Scalar.h" // for Scalar
-#include "lldb/Core/Value.h" // for Value, Value::Val...
-#include "lldb/Core/ValueObject.h" // for ValueObject
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectConstResultCast.h"
#include "lldb/Core/ValueObjectConstResultChild.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Utility/DataBufferHeap.h" // for DataBufferHeap
-#include "lldb/Utility/Endian.h" // for InlHostByteOrder
-#include "lldb/Utility/SharingPtr.h" // for SharingPtr
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/SharingPtr.h"
-#include <string> // for string
+#include <string>
namespace lldb_private {
class DataExtractor;
@@ -66,7 +66,7 @@ ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(
bool child_is_deref_of_parent = false;
uint64_t language_flags;
- const bool transparent_pointers = synthetic_array_member == false;
+ const bool transparent_pointers = !synthetic_array_member;
CompilerType compiler_type = m_impl_backend->GetCompilerType();
CompilerType child_compiler_type;
@@ -77,7 +77,13 @@ ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(
ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
child_is_deref_of_parent, m_impl_backend, language_flags);
- if (child_compiler_type && child_byte_size) {
+
+ // One might think we should check that the size of the children
+ // is always strictly positive, hence we could avoid creating a
+ // ValueObject if that's not the case, but it turns out there
+ // are languages out there which allow zero-size types with
+ // children (e.g. Swift).
+ if (child_compiler_type) {
if (synthetic_index)
child_byte_offset += child_byte_size * synthetic_index;
diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp
index e9b48310b0c6..161b6e49e0dd 100644
--- a/source/Core/ValueObjectDynamicValue.cpp
+++ b/source/Core/ValueObjectDynamicValue.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/ValueObjectDynamicValue.h"
-#include "lldb/Core/Scalar.h" // for Scalar, operator!=
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/CompilerType.h"
@@ -17,13 +16,14 @@
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataExtractor.h" // for DataExtractor
+#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-types.h" // for addr_t, offset_t
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-types.h"
-#include <string.h> // for strcmp, size_t
+#include <string.h>
namespace lldb_private {
class Declaration;
}
@@ -92,7 +92,8 @@ ConstString ValueObjectDynamicValue::GetDisplayTypeName() {
size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) {
const bool success = UpdateValueIfNeeded(false);
if (success && m_dynamic_type_info.HasType()) {
- auto children_count = GetCompilerType().GetNumChildren(true);
+ ExecutionContext exe_ctx(GetExecutionContextRef());
+ auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
return children_count <= max ? children_count : max;
} else
return m_parent->GetNumChildren(max);
diff --git a/source/Core/ValueObjectList.cpp b/source/Core/ValueObjectList.cpp
index 0dd07252888f..7a7e0d8417b7 100644
--- a/source/Core/ValueObjectList.cpp
+++ b/source/Core/ValueObjectList.cpp
@@ -9,11 +9,11 @@
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Core/ValueObject.h" // for ValueObject
-#include "lldb/Utility/ConstString.h" // for ConstString
-#include "lldb/Utility/SharingPtr.h" // for SharingPtr
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/SharingPtr.h"
-#include <utility> // for back_insert_iterator, back_ins...
+#include <utility>
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp
index 3e71fea6bb35..24103204ee47 100644
--- a/source/Core/ValueObjectMemory.cpp
+++ b/source/Core/ValueObjectMemory.cpp
@@ -8,19 +8,19 @@
//===----------------------------------------------------------------------===//
#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Core/Scalar.h" // for Scalar, operator!=
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataExtractor.h" // for DataExtractor
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-types.h" // for addr_t
-#include "llvm/Support/ErrorHandling.h" // for llvm_unreachable
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-types.h"
+#include "llvm/Support/ErrorHandling.h"
-#include <assert.h> // for assert
-#include <memory> // for shared_ptr
+#include <assert.h>
+#include <memory>
namespace lldb_private {
class ExecutionContextScope;
@@ -128,15 +128,19 @@ size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) {
return child_count <= max ? child_count : max;
}
+ ExecutionContext exe_ctx(GetExecutionContextRef());
const bool omit_empty_base_classes = true;
- auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes);
+ auto child_count =
+ m_compiler_type.GetNumChildren(omit_empty_base_classes, &exe_ctx);
return child_count <= max ? child_count : max;
}
uint64_t ValueObjectMemory::GetByteSize() {
if (m_type_sp)
return m_type_sp->GetByteSize();
- return m_compiler_type.GetByteSize(nullptr);
+ if (llvm::Optional<uint64_t> size = m_compiler_type.GetByteSize(nullptr))
+ return *size;
+ return 0;
}
lldb::ValueType ValueObjectMemory::GetValueType() const {
diff --git a/source/Core/ValueObjectRegister.cpp b/source/Core/ValueObjectRegister.cpp
index 05022d3ed10a..41d1c27f7361 100644
--- a/source/Core/ValueObjectRegister.cpp
+++ b/source/Core/ValueObjectRegister.cpp
@@ -10,23 +10,23 @@
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/Scalar.h" // for Scalar
-#include "lldb/Core/Value.h" // for Value, Value::ContextType:...
+#include "lldb/Core/Value.h"
#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/TypeSystem.h" // for TypeSystem
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/StackFrame.h" // for StackFrame
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataExtractor.h" // for DataExtractor
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/Stream.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
-#include <assert.h> // for assert
-#include <memory> // for shared_ptr
+#include <assert.h>
+#include <memory>
namespace lldb_private {
class ExecutionContextScope;
@@ -279,7 +279,8 @@ ConstString ValueObjectRegister::GetTypeName() {
}
size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) {
- auto children_count = GetCompilerType().GetNumChildren(true);
+ ExecutionContext exe_ctx(GetExecutionContextRef());
+ auto children_count = GetCompilerType().GetNumChildren(true, &exe_ctx);
return children_count <= max ? children_count : max;
}
diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp
index 044387a4ae12..d22b1dc1c57d 100644
--- a/source/Core/ValueObjectSyntheticFilter.cpp
+++ b/source/Core/ValueObjectSyntheticFilter.cpp
@@ -9,14 +9,14 @@
#include "lldb/Core/ValueObjectSyntheticFilter.h"
-#include "lldb/Core/Value.h" // for Value
+#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/Target/ExecutionContext.h" // for ExecutionContext
+#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet
-#include "lldb/Utility/SharingPtr.h" // for SharingPtr
-#include "lldb/Utility/Status.h" // for Status
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/SharingPtr.h"
+#include "lldb/Utility/Status.h"
#include "llvm/ADT/STLExtras.h"
@@ -119,7 +119,7 @@ bool ValueObjectSynthetic::MightHaveChildren() {
if (m_might_have_children == eLazyBoolCalculate)
m_might_have_children =
(m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
- return (m_might_have_children == eLazyBoolNo ? false : true);
+ return (m_might_have_children != eLazyBoolNo);
}
uint64_t ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); }
@@ -174,7 +174,7 @@ bool ValueObjectSynthetic::UpdateValue() {
}
// let our backend do its update
- if (m_synth_filter_ap->Update() == false) {
+ if (!m_synth_filter_ap->Update()) {
if (log)
log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic "
"filter said caches are stale - clearing",
@@ -235,7 +235,7 @@ lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx,
UpdateValueIfNeeded();
ValueObject *valobj;
- if (m_children_byindex.GetValueForKey(idx, valobj) == false) {
+ if (!m_children_byindex.GetValueForKey(idx, valobj)) {
if (can_create && m_synth_filter_ap.get() != nullptr) {
if (log)
log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at "
diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp
index bfe5c3de7fbf..4d401c56249c 100644
--- a/source/Core/ValueObjectVariable.cpp
+++ b/source/Core/ValueObjectVariable.cpp
@@ -9,14 +9,12 @@
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Core/Address.h" // for Address
-#include "lldb/Core/AddressRange.h" // for AddressRange
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h" // for Scalar, operator!=
#include "lldb/Core/Value.h"
-#include "lldb/Expression/DWARFExpression.h" // for DWARFExpression
-#include "lldb/Symbol/Declaration.h" // for Declaration
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -27,15 +25,17 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataExtractor.h" // for DataExtractor
-#include "lldb/Utility/Status.h" // for Status
-#include "lldb/lldb-private-enumerations.h" // for AddressType::eAddressTy...
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/lldb-private-enumerations.h"
+#include "lldb/lldb-types.h"
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/StringRef.h"
-#include <assert.h> // for assert
-#include <memory> // for shared_ptr
+#include <assert.h>
+#include <memory>
namespace lldb_private {
class ExecutionContextScope;
@@ -98,8 +98,9 @@ size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) {
if (!type.IsValid())
return 0;
+ ExecutionContext exe_ctx(GetExecutionContextRef());
const bool omit_empty_base_classes = true;
- auto child_count = type.GetNumChildren(omit_empty_base_classes);
+ auto child_count = type.GetNumChildren(omit_empty_base_classes, &exe_ctx);
return child_count <= max ? child_count : max;
}
@@ -111,7 +112,7 @@ uint64_t ValueObjectVariable::GetByteSize() {
if (!type.IsValid())
return 0;
- return type.GetByteSize(exe_ctx.GetBestExecutionContextScope());
+ return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()).getValueOr(0);
}
lldb::ValueType ValueObjectVariable::GetValueType() const {
diff --git a/source/DataFormatters/CXXFunctionPointer.cpp b/source/DataFormatters/CXXFunctionPointer.cpp
index fad67a9d5b7a..9059891e5e9b 100644
--- a/source/DataFormatters/CXXFunctionPointer.cpp
+++ b/source/DataFormatters/CXXFunctionPointer.cpp
@@ -38,7 +38,7 @@ bool lldb_private::formatters::CXXFunctionPointerSummaryProvider(
Address so_addr;
Target *target = exe_ctx.GetTargetPtr();
- if (target && target->GetSectionLoadList().IsEmpty() == false) {
+ if (target && !target->GetSectionLoadList().IsEmpty()) {
if (target->GetSectionLoadList().ResolveLoadAddress(func_ptr_address,
so_addr)) {
so_addr.Dump(&sstr, exe_ctx.GetBestExecutionContextScope(),
diff --git a/source/DataFormatters/DataVisualization.cpp b/source/DataFormatters/DataVisualization.cpp
index 2a2d4b8b553e..23b8b6e128c8 100644
--- a/source/DataFormatters/DataVisualization.cpp
+++ b/source/DataFormatters/DataVisualization.cpp
@@ -10,10 +10,6 @@
#include "lldb/DataFormatters/DataVisualization.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
@@ -149,7 +145,7 @@ void DataVisualization::Categories::Enable(lldb::LanguageType lang_type) {
}
void DataVisualization::Categories::Disable(const ConstString &category) {
- if (GetFormatManager().GetCategory(category)->IsEnabled() == true)
+ if (GetFormatManager().GetCategory(category)->IsEnabled())
GetFormatManager().DisableCategory(category);
}
@@ -170,7 +166,7 @@ void DataVisualization::Categories::Enable(
void DataVisualization::Categories::Disable(
const lldb::TypeCategoryImplSP &category) {
- if (category.get() && category->IsEnabled() == true)
+ if (category.get() && category->IsEnabled())
GetFormatManager().DisableCategory(category);
}
diff --git a/source/DataFormatters/DumpValueObjectOptions.cpp b/source/DataFormatters/DumpValueObjectOptions.cpp
index 7c9d5eb77a01..17f8d00ff493 100644
--- a/source/DataFormatters/DumpValueObjectOptions.cpp
+++ b/source/DataFormatters/DumpValueObjectOptions.cpp
@@ -10,10 +10,6 @@
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ValueObject.h"
using namespace lldb;
@@ -71,7 +67,7 @@ DumpValueObjectOptions &DumpValueObjectOptions::SetUseObjectiveC(bool use) {
}
DumpValueObjectOptions &DumpValueObjectOptions::SetShowSummary(bool show) {
- if (show == false)
+ if (!show)
SetOmitSummaryDepth(UINT32_MAX);
else
SetOmitSummaryDepth(0);
diff --git a/source/DataFormatters/FormatCache.cpp b/source/DataFormatters/FormatCache.cpp
index 0f1b29f1b476..bb5f379d3c73 100644
--- a/source/DataFormatters/FormatCache.cpp
+++ b/source/DataFormatters/FormatCache.cpp
@@ -8,13 +8,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormatCache.h"
using namespace lldb;
diff --git a/source/DataFormatters/FormatClasses.cpp b/source/DataFormatters/FormatClasses.cpp
index f657361d3d5d..1c595c3c04e5 100644
--- a/source/DataFormatters/FormatClasses.cpp
+++ b/source/DataFormatters/FormatClasses.cpp
@@ -12,13 +12,9 @@
#include "lldb/DataFormatters/FormatManager.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
diff --git a/source/DataFormatters/FormatManager.cpp b/source/DataFormatters/FormatManager.cpp
index bafee1799b80..da03c64b0f8c 100644
--- a/source/DataFormatters/FormatManager.cpp
+++ b/source/DataFormatters/FormatManager.cpp
@@ -11,10 +11,6 @@
#include "llvm/ADT/STLExtras.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
@@ -297,7 +293,7 @@ FormatManager::GetFormatForType(lldb::TypeNameSpecifierImplSP type_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)
+ if (!category_sp->IsEnabled())
continue;
lldb::TypeFormatImplSP format_current_sp =
category_sp->GetFormatForType(type_sp);
@@ -321,7 +317,7 @@ FormatManager::GetSummaryForType(lldb::TypeNameSpecifierImplSP type_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)
+ if (!category_sp->IsEnabled())
continue;
lldb::TypeSummaryImplSP summary_current_sp =
category_sp->GetSummaryForType(type_sp);
@@ -345,7 +341,7 @@ FormatManager::GetFilterForType(lldb::TypeNameSpecifierImplSP type_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)
+ if (!category_sp->IsEnabled())
continue;
lldb::TypeFilterImplSP filter_current_sp(
(TypeFilterImpl *)category_sp->GetFilterForType(type_sp).get());
@@ -370,7 +366,7 @@ FormatManager::GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_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)
+ if (!category_sp->IsEnabled())
continue;
lldb::ScriptedSyntheticChildrenSP synth_current_sp(
(ScriptedSyntheticChildren *)category_sp->GetSyntheticForType(type_sp)
@@ -410,7 +406,7 @@ FormatManager::GetValidatorForType(lldb::TypeNameSpecifierImplSP type_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)
+ if (!category_sp->IsEnabled())
continue;
lldb::TypeValidatorImplSP validator_current_sp(
category_sp->GetValidatorForType(type_sp).get());
@@ -483,7 +479,7 @@ lldb::Format 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)
+ !valobj.GetTargetSP()->GetDebugger().GetAutoOneLineSummaries())
return false; // then don't oneline
// if this object has a summary, then ask the summary
@@ -539,7 +535,7 @@ bool FormatManager::ShouldPrintAsOneLiner(ValueObject &valobj) {
if (!synth_sp)
return false;
// but if we only have them to provide a value, keep going
- if (synth_sp->MightHaveChildren() == false &&
+ if (!synth_sp->MightHaveChildren() &&
synth_sp->DoesProvideSyntheticValue())
is_synth_val = true;
else
diff --git a/source/DataFormatters/FormattersHelpers.cpp b/source/DataFormatters/FormattersHelpers.cpp
index 460a49690d3d..1a1321598966 100644
--- a/source/DataFormatters/FormattersHelpers.cpp
+++ b/source/DataFormatters/FormattersHelpers.cpp
@@ -8,13 +8,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Target/StackFrame.h"
diff --git a/source/DataFormatters/LanguageCategory.cpp b/source/DataFormatters/LanguageCategory.cpp
index 251f0c368e08..4a4b7c544f09 100644
--- a/source/DataFormatters/LanguageCategory.cpp
+++ b/source/DataFormatters/LanguageCategory.cpp
@@ -10,10 +10,6 @@
#include "lldb/DataFormatters/LanguageCategory.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/DataFormatters/TypeCategory.h"
#include "lldb/DataFormatters/TypeFormat.h"
diff --git a/source/DataFormatters/StringPrinter.cpp b/source/DataFormatters/StringPrinter.cpp
index 89d7a95069ca..6a000f0f6431 100644
--- a/source/DataFormatters/StringPrinter.cpp
+++ b/source/DataFormatters/StringPrinter.cpp
@@ -312,7 +312,7 @@ static bool DumpUTFBufferToStream(
utf8_data_end_ptr = utf8_data_ptr + utf8_data_buffer_sp->GetByteSize();
ConvertFunction(&data_ptr, data_end_ptr, &utf8_data_ptr,
utf8_data_end_ptr, llvm::lenientConversion);
- if (false == zero_is_terminator)
+ if (!zero_is_terminator)
utf8_data_end_ptr = utf8_data_ptr;
// needed because the ConvertFunction will change the value of the
// data_ptr.
diff --git a/source/DataFormatters/TypeCategory.cpp b/source/DataFormatters/TypeCategory.cpp
index 184a8c98de62..5740a095f8bd 100644
--- a/source/DataFormatters/TypeCategory.cpp
+++ b/source/DataFormatters/TypeCategory.cpp
@@ -10,10 +10,6 @@
#include "lldb/DataFormatters/TypeCategory.h"
#include "lldb/Target/Language.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
@@ -161,10 +157,7 @@ bool TypeCategoryImpl::Get(ValueObject &valobj,
else /*if (filter_sp.get() && synth.get())*/
{
- if (filter_sp->GetRevision() > synth->GetRevision())
- pick_synth = false;
- else
- pick_synth = true;
+ pick_synth = filter_sp->GetRevision() <= synth->GetRevision();
}
if (pick_synth) {
if (regex_synth && reason)
diff --git a/source/DataFormatters/TypeCategoryMap.cpp b/source/DataFormatters/TypeCategoryMap.cpp
index d2da672f13dc..3193f2703efa 100644
--- a/source/DataFormatters/TypeCategoryMap.cpp
+++ b/source/DataFormatters/TypeCategoryMap.cpp
@@ -13,10 +13,6 @@
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/Utility/Log.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
@@ -122,8 +118,7 @@ void TypeCategoryMap::EnableAllCategories() {
void TypeCategoryMap::DisableAllCategories() {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
- Position p = First;
- for (; false == m_active_categories.empty(); p++) {
+ for (Position p = First; !m_active_categories.empty(); p++) {
m_active_categories.front()->SetEnabledPosition(p);
Disable(m_active_categories.front());
}
diff --git a/source/DataFormatters/TypeFormat.cpp b/source/DataFormatters/TypeFormat.cpp
index 7902ccb47771..f00a679cecfd 100644
--- a/source/DataFormatters/TypeFormat.cpp
+++ b/source/DataFormatters/TypeFormat.cpp
@@ -9,13 +9,9 @@
#include "lldb/DataFormatters/TypeFormat.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
@@ -98,16 +94,18 @@ bool TypeFormatImpl_Format::FormatObject(ValueObject *valobj,
return false;
}
+ ExecutionContextScope *exe_scope =
+ exe_ctx.GetBestExecutionContextScope();
+ llvm::Optional<uint64_t> size = compiler_type.GetByteSize(exe_scope);
+ if (!size)
+ return false;
StreamString sstr;
- ExecutionContextScope *exe_scope(
- exe_ctx.GetBestExecutionContextScope());
compiler_type.DumpTypeValue(
- &sstr, // The stream to use for display
- GetFormat(), // Format to display this type with
- data, // Data to extract from
- 0, // Byte offset into "m_data"
- compiler_type.GetByteSize(
- exe_scope), // Byte size of item in "m_data"
+ &sstr, // The stream to use for display
+ GetFormat(), // Format to display this type with
+ data, // Data to extract from
+ 0, // Byte offset into "m_data"
+ *size, // Byte size of item in "m_data"
valobj->GetBitfieldBitSize(), // Bitfield bit size
valobj->GetBitfieldBitOffset(), // Bitfield bit offset
exe_scope);
@@ -163,11 +161,10 @@ bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj,
if (!target_sp)
return false;
const ModuleList &images(target_sp->GetImages());
- SymbolContext sc;
TypeList types;
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
- images.FindTypes(sc, m_enum_type, false, UINT32_MAX, searched_symbol_files,
- types);
+ images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX,
+ searched_symbol_files, types);
if (types.GetSize() == 0)
return false;
for (lldb::TypeSP type_sp : types.Types()) {
@@ -182,7 +179,7 @@ bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj,
}
} else
valobj_enum_type = iter->second;
- if (valobj_enum_type.IsValid() == false)
+ if (!valobj_enum_type.IsValid())
return false;
DataExtractor data;
Status error;
diff --git a/source/DataFormatters/TypeSummary.cpp b/source/DataFormatters/TypeSummary.cpp
index 09a7ff8d7d36..492d3efc7f4c 100644
--- a/source/DataFormatters/TypeSummary.cpp
+++ b/source/DataFormatters/TypeSummary.cpp
@@ -9,13 +9,9 @@
#include "lldb/DataFormatters/TypeSummary.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
@@ -139,7 +135,7 @@ bool CXXFunctionSummaryFormat::FormatObject(ValueObject *valobj,
const TypeSummaryOptions &options) {
dest.clear();
StreamString stream;
- if (!m_impl || m_impl(*valobj, stream, options) == false)
+ if (!m_impl || !m_impl(*valobj, stream, options))
return false;
dest = stream.GetString();
return true;
diff --git a/source/DataFormatters/TypeSynthetic.cpp b/source/DataFormatters/TypeSynthetic.cpp
index 28a51dae6b20..de46d505349b 100644
--- a/source/DataFormatters/TypeSynthetic.cpp
+++ b/source/DataFormatters/TypeSynthetic.cpp
@@ -8,13 +8,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-public.h"
diff --git a/source/DataFormatters/TypeValidator.cpp b/source/DataFormatters/TypeValidator.cpp
index 7a5b8d565292..6769a5a99856 100644
--- a/source/DataFormatters/TypeValidator.cpp
+++ b/source/DataFormatters/TypeValidator.cpp
@@ -7,13 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/TypeValidator.h"
#include "lldb/Utility/StreamString.h"
diff --git a/source/DataFormatters/ValueObjectPrinter.cpp b/source/DataFormatters/ValueObjectPrinter.cpp
index 43e91a2b6c92..082158822dff 100644
--- a/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/source/DataFormatters/ValueObjectPrinter.cpp
@@ -9,10 +9,6 @@
#include "lldb/DataFormatters/ValueObjectPrinter.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -133,13 +129,13 @@ bool ValueObjectPrinter::GetMostSpecializedValue() {
}
if (m_valobj->IsSynthetic()) {
- if (m_options.m_use_synthetic == false) {
+ if (!m_options.m_use_synthetic) {
ValueObject *non_synthetic = m_valobj->GetNonSyntheticValue().get();
if (non_synthetic)
m_valobj = non_synthetic;
}
} else {
- if (m_options.m_use_synthetic == true) {
+ if (m_options.m_use_synthetic) {
ValueObject *synthetic = m_valobj->GetSyntheticValue().get();
if (synthetic)
m_valobj = synthetic;
@@ -170,7 +166,7 @@ const char *ValueObjectPrinter::GetRootNameForDisplay(const char *if_fail) {
bool ValueObjectPrinter::ShouldPrintValueObject() {
if (m_should_print == eLazyBoolCalculate)
m_should_print =
- (m_options.m_flat_output == false || m_type_flags.Test(eTypeHasValue))
+ (!m_options.m_flat_output || m_type_flags.Test(eTypeHasValue))
? eLazyBoolYes
: eLazyBoolNo;
return m_should_print == eLazyBoolYes;
@@ -330,7 +326,7 @@ bool ValueObjectPrinter::CheckScopeIfNeeded() {
}
TypeSummaryImpl *ValueObjectPrinter::GetSummaryFormatter(bool null_if_omitted) {
- if (m_summary_formatter.second == false) {
+ if (!m_summary_formatter.second) {
TypeSummaryImpl *entry = m_options.m_summary_sp
? m_options.m_summary_sp.get()
: m_valobj->GetSummaryFormat().get();
@@ -462,7 +458,7 @@ bool ValueObjectPrinter::PrintObjectDescriptionIfNeeded(bool value_printed,
else
m_stream->Printf("%s\n", object_desc);
return true;
- } else if (value_printed == false && summary_printed == false)
+ } else if (!value_printed && !summary_printed)
return true;
else
return false;
@@ -629,7 +625,7 @@ bool ValueObjectPrinter::ShouldPrintEmptyBrackets(bool value_printed,
if (!IsAggregate())
return false;
- if (m_options.m_reveal_empty_aggregates == false) {
+ if (!m_options.m_reveal_empty_aggregates) {
if (value_printed || summary_printed)
return false;
}
diff --git a/source/DataFormatters/VectorType.cpp b/source/DataFormatters/VectorType.cpp
index d85a7e674177..b11fb1456afa 100644
--- a/source/DataFormatters/VectorType.cpp
+++ b/source/DataFormatters/VectorType.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Core/ValueObject.h"
@@ -175,13 +171,14 @@ static size_t CalculateNumChildren(
lldb_private::ExecutionContextScope *exe_scope =
nullptr // does not matter here because all we trade in are basic types
) {
- auto container_size = container_type.GetByteSize(exe_scope);
- auto element_size = element_type.GetByteSize(exe_scope);
+ llvm::Optional<uint64_t> container_size =
+ container_type.GetByteSize(exe_scope);
+ llvm::Optional<uint64_t> element_size = element_type.GetByteSize(exe_scope);
- if (element_size) {
- if (container_size % element_size)
+ if (container_size && element_size && *element_size) {
+ if (*container_size % *element_size)
return 0;
- return container_size / element_size;
+ return *container_size / *element_size;
}
return 0;
}
@@ -201,8 +198,11 @@ public:
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
if (idx >= CalculateNumChildren())
- return lldb::ValueObjectSP();
- auto offset = idx * m_child_type.GetByteSize(nullptr);
+ return {};
+ llvm::Optional<uint64_t> size = m_child_type.GetByteSize(nullptr);
+ if (!size)
+ return {};
+ auto offset = idx * *size;
StreamString idx_name;
idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
ValueObjectSP child_sp(m_backend.GetSyntheticChildAtOffset(
diff --git a/source/Expression/DWARFExpression.cpp b/source/Expression/DWARFExpression.cpp
index 55eb65f32b5a..a6249b3a2864 100644
--- a/source/Expression/DWARFExpression.cpp
+++ b/source/Expression/DWARFExpression.cpp
@@ -9,19 +9,17 @@
#include "lldb/Expression/DWARFExpression.h"
-// C Includes
#include <inttypes.h>
-// C++ Includes
#include <vector>
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/DataEncoder.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/VMRange.h"
@@ -1841,7 +1839,7 @@ bool DWARFExpression::Evaluate(
error_ptr->SetErrorString(
"Expression stack needs at least 1 item for DW_OP_abs.");
return false;
- } else if (stack.back().ResolveValue(exe_ctx).AbsoluteValue() == false) {
+ } else if (!stack.back().ResolveValue(exe_ctx).AbsoluteValue()) {
if (error_ptr)
error_ptr->SetErrorString(
"Failed to take the absolute value of the first stack item.");
@@ -1974,7 +1972,7 @@ bool DWARFExpression::Evaluate(
"Expression stack needs at least 1 item for DW_OP_neg.");
return false;
} else {
- if (stack.back().ResolveValue(exe_ctx).UnaryNegate() == false) {
+ if (!stack.back().ResolveValue(exe_ctx).UnaryNegate()) {
if (error_ptr)
error_ptr->SetErrorString("Unary negate failed.");
return false;
@@ -1995,7 +1993,7 @@ bool DWARFExpression::Evaluate(
"Expression stack needs at least 1 item for DW_OP_not.");
return false;
} else {
- if (stack.back().ResolveValue(exe_ctx).OnesComplement() == false) {
+ if (!stack.back().ResolveValue(exe_ctx).OnesComplement()) {
if (error_ptr)
error_ptr->SetErrorString("Logical NOT failed.");
return false;
@@ -2102,8 +2100,8 @@ bool DWARFExpression::Evaluate(
} else {
tmp = stack.back();
stack.pop_back();
- if (stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
- tmp.ResolveValue(exe_ctx)) == false) {
+ if (!stack.back().ResolveValue(exe_ctx).ShiftRightLogical(
+ tmp.ResolveValue(exe_ctx))) {
if (error_ptr)
error_ptr->SetErrorString("DW_OP_shr failed.");
return false;
@@ -2382,7 +2380,7 @@ bool DWARFExpression::Evaluate(
case DW_OP_lit29:
case DW_OP_lit30:
case DW_OP_lit31:
- stack.push_back(Scalar(op - DW_OP_lit0));
+ stack.push_back(Scalar((uint64_t)(op - DW_OP_lit0)));
break;
//----------------------------------------------------------------------
@@ -3029,7 +3027,9 @@ bool DWARFExpression::AddressRangeForLocationListEntry(
if (!debug_loc_data.ValidOffset(*offset_ptr))
return false;
- switch (dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat()) {
+ DWARFExpression::LocationListFormat format =
+ dwarf_cu->GetSymbolFileDWARF()->GetLocationListFormat();
+ switch (format) {
case NonLocationList:
return false;
case RegularLocationList:
@@ -3037,6 +3037,7 @@ bool DWARFExpression::AddressRangeForLocationListEntry(
high_pc = debug_loc_data.GetAddress(offset_ptr);
return true;
case SplitDwarfLocationList:
+ case LocLists:
switch (debug_loc_data.GetU8(offset_ptr)) {
case DW_LLE_end_of_list:
return false;
@@ -3050,12 +3051,25 @@ bool DWARFExpression::AddressRangeForLocationListEntry(
case DW_LLE_startx_length: {
uint64_t index = debug_loc_data.GetULEB128(offset_ptr);
low_pc = ReadAddressFromDebugAddrSection(dwarf_cu, index);
- uint32_t length = debug_loc_data.GetU32(offset_ptr);
+ uint64_t length = (format == LocLists)
+ ? debug_loc_data.GetULEB128(offset_ptr)
+ : debug_loc_data.GetU32(offset_ptr);
high_pc = low_pc + length;
return true;
}
+ case DW_LLE_start_length: {
+ low_pc = debug_loc_data.GetAddress(offset_ptr);
+ high_pc = low_pc + debug_loc_data.GetULEB128(offset_ptr);
+ return true;
+ }
+ case DW_LLE_start_end: {
+ low_pc = debug_loc_data.GetAddress(offset_ptr);
+ high_pc = debug_loc_data.GetAddress(offset_ptr);
+ return true;
+ }
default:
// Not supported entry type
+ lldbassert(false && "Not supported location list type");
return false;
}
}
diff --git a/source/Expression/ExpressionSourceCode.cpp b/source/Expression/ExpressionSourceCode.cpp
index abbb332fac48..03b2d26a256d 100644
--- a/source/Expression/ExpressionSourceCode.cpp
+++ b/source/Expression/ExpressionSourceCode.cpp
@@ -105,10 +105,7 @@ public:
if (m_file_stack.back() != m_current_file)
return true;
- if (line >= m_current_file_line)
- return false;
- else
- return true;
+ return line < m_current_file_line;
default:
return false;
}
@@ -378,7 +375,5 @@ bool ExpressionSourceCode::GetOriginalBodyBounds(
return false;
start_loc += strlen(start_marker);
end_loc = transformed_text.find(end_marker);
- if (end_loc == std::string::npos)
- return false;
- return true;
+ return end_loc != std::string::npos;
}
diff --git a/source/Expression/FunctionCaller.cpp b/source/Expression/FunctionCaller.cpp
index 9742ed0b270e..97f4f51e1ff6 100644
--- a/source/Expression/FunctionCaller.cpp
+++ b/source/Expression/FunctionCaller.cpp
@@ -7,14 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Expression/DiagnosticManager.h"
@@ -31,6 +26,7 @@
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb_private;
diff --git a/source/Expression/IRDynamicChecks.cpp b/source/Expression/IRDynamicChecks.cpp
index e0a7dca4113d..20431d5f93c5 100644
--- a/source/Expression/IRDynamicChecks.cpp
+++ b/source/Expression/IRDynamicChecks.cpp
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
@@ -18,7 +15,6 @@
#include "llvm/IR/Value.h"
#include "llvm/Support/raw_ostream.h"
-// Project includes
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Expression/UtilityFunction.h"
diff --git a/source/Expression/IRExecutionUnit.cpp b/source/Expression/IRExecutionUnit.cpp
index e34a4c7fac52..ec6ceeac1813 100644
--- a/source/Expression/IRExecutionUnit.cpp
+++ b/source/Expression/IRExecutionUnit.cpp
@@ -553,6 +553,8 @@ lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
sect_type = lldb::eSectionTypeDWARFDebugLine;
else if (dwarf_name.equals("loc"))
sect_type = lldb::eSectionTypeDWARFDebugLoc;
+ else if (dwarf_name.equals("loclists"))
+ sect_type = lldb::eSectionTypeDWARFDebugLocLists;
break;
case 'm':
@@ -707,9 +709,10 @@ FindBestAlternateMangledName(const ConstString &demangled,
struct IRExecutionUnit::SearchSpec {
ConstString name;
- uint32_t mask;
+ lldb::FunctionNameType mask;
- SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull)
+ SearchSpec(ConstString n,
+ lldb::FunctionNameType m = lldb::eFunctionNameTypeFull)
: name(n), mask(m) {}
};
@@ -1010,7 +1013,7 @@ IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) {
Name.c_str());
m_parent.ReportSymbolLookupError(name_cs);
- return 0xbad0bad0;
+ return 0;
} else {
if (log)
log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
@@ -1088,6 +1091,7 @@ bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp,
case lldb::eSectionTypeDWARFDebugInfo:
case lldb::eSectionTypeDWARFDebugLine:
case lldb::eSectionTypeDWARFDebugLoc:
+ case lldb::eSectionTypeDWARFDebugLocLists:
case lldb::eSectionTypeDWARFDebugMacInfo:
case lldb::eSectionTypeDWARFDebugPubNames:
case lldb::eSectionTypeDWARFDebugPubTypes:
@@ -1213,14 +1217,11 @@ void IRExecutionUnit::PopulateSectionList(
}
}
-bool IRExecutionUnit::GetArchitecture(lldb_private::ArchSpec &arch) {
+ArchSpec IRExecutionUnit::GetArchitecture() {
ExecutionContext exe_ctx(GetBestExecutionContextScope());
- Target *target = exe_ctx.GetTargetPtr();
- if (target)
- arch = target->GetArchitecture();
- else
- arch.Clear();
- return arch.IsValid();
+ if(Target *target = exe_ctx.GetTargetPtr())
+ return target->GetArchitecture();
+ return ArchSpec();
}
lldb::ModuleSP IRExecutionUnit::GetJITModule() {
diff --git a/source/Expression/IRInterpreter.cpp b/source/Expression/IRInterpreter.cpp
index abf86b739f07..457eaef46dd3 100644
--- a/source/Expression/IRInterpreter.cpp
+++ b/source/Expression/IRInterpreter.cpp
@@ -10,7 +10,6 @@
#include "lldb/Expression/IRInterpreter.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRExecutionUnit.h"
@@ -19,6 +18,7 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -152,17 +152,13 @@ public:
Type *type) {
size_t type_size = m_target_data.getTypeStoreSize(type);
- switch (type_size) {
- case 1:
- case 2:
- case 4:
- case 8:
- scalar = llvm::APInt(type_size*8, u64value);
- break;
- default:
+ if (type_size > 8)
return false;
- }
+ if (type_size != 1)
+ type_size = PowerOf2Ceil(type_size);
+
+ scalar = llvm::APInt(type_size*8, u64value);
return true;
}
@@ -192,8 +188,7 @@ public:
return false;
lldb::offset_t offset = 0;
- if (value_size == 1 || value_size == 2 || value_size == 4 ||
- value_size == 8) {
+ if (value_size <= 8) {
uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
return AssignToMatchType(scalar, u64value, value->getType());
}
@@ -618,6 +613,18 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, llvm::Function &function,
}
}
+ // The IR interpreter currently doesn't know about
+ // 128-bit integers. As they're not that frequent,
+ // we can just fall back to the JIT rather than
+ // choking.
+ if (operand_type->getPrimitiveSizeInBits() > 64) {
+ if (log)
+ log->Printf("Unsupported operand type: %s",
+ PrintType(operand_type).c_str());
+ error.SetErrorString(unsupported_operand_error);
+ return false;
+ }
+
if (Constant *constant = llvm::dyn_cast<Constant>(operand)) {
if (!CanResolveConstant(constant)) {
if (log)
@@ -1585,9 +1592,6 @@ bool IRInterpreter::Interpret(llvm::Module &module, llvm::Function &function,
// Check if this is a string literal or constant string pointer
if (arg_ty->isPointerTy()) {
- // Pointer to just one type
- assert(arg_ty->getNumContainedTypes() == 1);
-
lldb::addr_t addr = tmp_op.ULongLong();
size_t dataSize = 0;
diff --git a/source/Expression/IRMemoryMap.cpp b/source/Expression/IRMemoryMap.cpp
index 1953e80852ff..e4c85d6ce727 100644
--- a/source/Expression/IRMemoryMap.cpp
+++ b/source/Expression/IRMemoryMap.cpp
@@ -8,7 +8,6 @@
//===----------------------------------------------------------------------===//
#include "lldb/Expression/IRMemoryMap.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -16,6 +15,7 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
using namespace lldb_private;
@@ -272,21 +272,17 @@ IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
uint32_t permissions, uint8_t alignment,
AllocationPolicy policy)
: m_process_alloc(process_alloc), m_process_start(process_start),
- m_size(size), m_permissions(permissions), m_alignment(alignment),
- m_policy(policy), m_leak(false) {
+ m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
+ m_alignment(alignment) {
switch (policy) {
default:
assert(0 && "We cannot reach this!");
case eAllocationPolicyHostOnly:
+ case eAllocationPolicyMirror:
m_data.SetByteSize(size);
- memset(m_data.GetBytes(), 0, size);
break;
case eAllocationPolicyProcessOnly:
break;
- case eAllocationPolicyMirror:
- m_data.SetByteSize(size);
- memset(m_data.GetBytes(), 0, size);
- break;
}
}
@@ -393,9 +389,10 @@ lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
lldb::addr_t mask = alignment - 1;
aligned_address = (allocation_address + mask) & (~mask);
- m_allocations[aligned_address] =
- Allocation(allocation_address, aligned_address, allocation_size,
- permissions, alignment, policy);
+ m_allocations.emplace(
+ std::piecewise_construct, std::forward_as_tuple(aligned_address),
+ std::forward_as_tuple(allocation_address, aligned_address,
+ allocation_size, permissions, alignment, policy));
if (zero_memory) {
Status write_error;
diff --git a/source/Expression/LLVMUserExpression.cpp b/source/Expression/LLVMUserExpression.cpp
index fc32bfbd37a2..edf1e69c30d8 100644
--- a/source/Expression/LLVMUserExpression.cpp
+++ b/source/Expression/LLVMUserExpression.cpp
@@ -7,10 +7,7 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Project includes
#include "lldb/Expression/LLVMUserExpression.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
diff --git a/source/Expression/Materializer.cpp b/source/Expression/Materializer.cpp
index 74a965e015ce..4d4e5e21092c 100644
--- a/source/Expression/Materializer.cpp
+++ b/source/Expression/Materializer.cpp
@@ -7,13 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/Materializer.h"
#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ExpressionVariable.h"
@@ -27,6 +22,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
@@ -50,7 +46,8 @@ uint32_t Materializer::AddStructMember(Entity &entity) {
}
void Materializer::Entity::SetSizeAndAlignmentFromType(CompilerType &type) {
- m_size = type.GetByteSize(nullptr);
+ if (llvm::Optional<uint64_t> size = type.GetByteSize(nullptr))
+ m_size = *size;
uint32_t bit_alignment = type.GetTypeBitAlign();
@@ -532,7 +529,7 @@ public:
if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize()) {
if (data.GetByteSize() == 0 &&
- m_variable_sp->LocationExpression().IsValid() == false) {
+ !m_variable_sp->LocationExpression().IsValid()) {
err.SetErrorStringWithFormat("the variable '%s' has no location, "
"it may have been optimized out",
m_variable_sp->GetName().AsCString());
@@ -798,7 +795,11 @@ public:
ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope();
- size_t byte_size = m_type.GetByteSize(exe_scope);
+ llvm::Optional<uint64_t> byte_size = m_type.GetByteSize(exe_scope);
+ if (!byte_size) {
+ err.SetErrorString("can't get size of type");
+ return;
+ }
size_t bit_align = m_type.GetTypeBitAlign();
size_t byte_align = (bit_align + 7) / 8;
@@ -809,10 +810,10 @@ public:
const bool zero_memory = true;
m_temporary_allocation = map.Malloc(
- byte_size, byte_align,
+ *byte_size, byte_align,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
IRMemoryMap::eAllocationPolicyMirror, zero_memory, alloc_error);
- m_temporary_allocation_size = byte_size;
+ m_temporary_allocation_size = *byte_size;
if (!alloc_error.Success()) {
err.SetErrorStringWithFormat(
diff --git a/source/Expression/REPL.cpp b/source/Expression/REPL.cpp
index a441e381985c..943385bb3aac 100644
--- a/source/Expression/REPL.cpp
+++ b/source/Expression/REPL.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/REPL.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
@@ -66,7 +62,7 @@ std::string REPL::GetSourcePath() {
tmpdir_file_spec.GetFilename().SetCString(file_basename.AsCString());
m_repl_source_path = tmpdir_file_spec.GetPath();
} else {
- tmpdir_file_spec = FileSpec("/tmp", false);
+ tmpdir_file_spec = FileSpec("/tmp");
tmpdir_file_spec.AppendPathComponent(file_basename.AsCString());
}
@@ -416,11 +412,12 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
// Update our code on disk
if (!m_repl_source_path.empty()) {
- lldb_private::File file(m_repl_source_path.c_str(),
- File::eOpenOptionWrite |
- File::eOpenOptionTruncate |
- File::eOpenOptionCanCreate,
- lldb::eFilePermissionsFileDefault);
+ lldb_private::File file;
+ FileSystem::Instance().Open(file, FileSpec(m_repl_source_path),
+ File::eOpenOptionWrite |
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCanCreate,
+ lldb::eFilePermissionsFileDefault);
std::string code(m_code.CopyList());
code.append(1, '\n');
size_t bytes_written = code.size();
@@ -429,7 +426,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
// Now set the default file and line to the REPL source file
m_target.GetSourceManager().SetDefaultFileAndLine(
- FileSpec(m_repl_source_path, false), new_default_line);
+ FileSpec(m_repl_source_path), new_default_line);
}
static_cast<IOHandlerEditline &>(io_handler)
.SetBaseLineNumber(m_code.GetSize() + 1);
@@ -453,7 +450,7 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) {
int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line,
const char *cursor, const char *last_char,
int skip_first_n_matches, int max_matches,
- StringList &matches) {
+ StringList &matches, StringList &descriptions) {
matches.Clear();
llvm::StringRef line(current_line, cursor - current_line);
@@ -466,7 +463,7 @@ int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line,
const char *lldb_current_line = line.substr(1).data();
return debugger.GetCommandInterpreter().HandleCompletion(
lldb_current_line, cursor, last_char, skip_first_n_matches, max_matches,
- matches);
+ matches, descriptions);
}
// Strip spaces from the line and see if we had only spaces
diff --git a/source/Expression/UtilityFunction.cpp b/source/Expression/UtilityFunction.cpp
index 52f3bfc4d128..a0a1e4edfb0b 100644
--- a/source/Expression/UtilityFunction.cpp
+++ b/source/Expression/UtilityFunction.cpp
@@ -7,13 +7,11 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-// C++ Includes
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
diff --git a/source/Host/CMakeLists.txt b/source/Host/CMakeLists.txt
index 5a92447edf30..333f109a9a26 100644
--- a/source/Host/CMakeLists.txt
+++ b/source/Host/CMakeLists.txt
@@ -11,7 +11,9 @@ endmacro()
# Objective-C++ files in lldb (which slows down the build process).
macro(remove_module_flags)
string(REGEX REPLACE "-fmodules-cache-path=[^ ]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REGEX REPLACE "-fmodules-local-submodule-visibility" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REGEX REPLACE "-fmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ string(REGEX REPLACE "-gmodules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REGEX REPLACE "-fcxx-modules" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
endmacro()
@@ -28,8 +30,6 @@ add_host_subdirectory(common
common/LockFileBase.cpp
common/MainLoop.cpp
common/MonitoringProcessLauncher.cpp
- common/NativeBreakpoint.cpp
- common/NativeBreakpointList.cpp
common/NativeWatchpointList.cpp
common/NativeProcessProtocol.cpp
common/NativeRegisterContext.cpp
@@ -40,7 +40,6 @@ add_host_subdirectory(common
common/PseudoTerminal.cpp
common/Socket.cpp
common/SocketAddress.cpp
- common/SoftwareBreakpoint.cpp
common/StringConvert.cpp
common/Symbols.cpp
common/TaskPool.cpp
@@ -92,7 +91,7 @@ else()
include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR})
add_subdirectory(macosx/objcxx)
set(LLDBObjCLibs lldbHostMacOSXObjCXX)
- add_host_subdirectory(maqcosx
+ add_host_subdirectory(macosx
macosx/Symbols.cpp
macosx/cfcpp/CFCBundle.cpp
macosx/cfcpp/CFCData.cpp
@@ -156,7 +155,7 @@ if (HAVE_LIBDL)
list(APPEND EXTRA_LIBS ${CMAKE_DL_LIBS})
endif()
if (NOT LLDB_DISABLE_LIBEDIT)
- list(APPEND EXTRA_LIBS edit)
+ list(APPEND EXTRA_LIBS ${libedit_LIBRARIES})
endif()
add_lldb_library(lldbHost
@@ -174,3 +173,7 @@ add_lldb_library(lldbHost
Object
Support
)
+
+if (NOT LLDB_DISABLE_LIBEDIT)
+ target_include_directories(lldbHost PUBLIC ${libedit_INCLUDE_DIRS})
+endif()
diff --git a/source/Host/android/HostInfoAndroid.cpp b/source/Host/android/HostInfoAndroid.cpp
index a96033283212..3dea01f8240d 100644
--- a/source/Host/android/HostInfoAndroid.cpp
+++ b/source/Host/android/HostInfoAndroid.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/android/HostInfoAndroid.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/linux/HostInfoLinux.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -28,7 +29,7 @@ void HostInfoAndroid::ComputeHostArchitectureSupport(ArchSpec &arch_32,
}
FileSpec HostInfoAndroid::GetDefaultShell() {
- return FileSpec("/system/bin/sh", false);
+ return FileSpec("/system/bin/sh");
}
FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path,
@@ -39,8 +40,11 @@ FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path,
static const char *const default_lib64_path[] = {"/vendor/lib64",
"/system/lib64", nullptr};
- if (module_path.empty() || module_path[0] == '/')
- return FileSpec(module_path.c_str(), true);
+ if (module_path.empty() || module_path[0] == '/') {
+ FileSpec file_spec(module_path.c_str());
+ FileSystem::Instance().Resolve(file_spec);
+ return file_spec;
+ }
SmallVector<StringRef, 4> ld_paths;
@@ -65,10 +69,11 @@ FileSpec HostInfoAndroid::ResolveLibraryPath(const std::string &module_path,
ld_paths.push_back(StringRef(*it));
for (const StringRef &path : ld_paths) {
- FileSpec file_candidate(path.str().c_str(), true);
+ FileSpec file_candidate(path.str().c_str());
+ FileSystem::Instance().Resolve(file_candidate);
file_candidate.AppendPathComponent(module_path.c_str());
- if (file_candidate.Exists())
+ if (FileSystem::Instance().Exists(file_candidate))
return file_candidate;
}
@@ -83,8 +88,8 @@ bool HostInfoAndroid::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
// algorithm will deduce /tmp, which is plain wrong. In that case we have an
// invalid directory, we substitute the path with /data/local/tmp, which is
// correct at least in some cases (i.e., when running as shell user).
- if (!success || !file_spec.Exists())
- file_spec = FileSpec("/data/local/tmp", false);
+ if (!success || !FileSystem::Instance().Exists(file_spec))
+ file_spec = FileSpec("/data/local/tmp");
- return file_spec.Exists();
+ return FileSystem::Instance().Exists(file_spec);
}
diff --git a/source/Host/common/Editline.cpp b/source/Host/common/Editline.cpp
index 329c0c1f3b70..f7ba4b5822ff 100644
--- a/source/Host/common/Editline.cpp
+++ b/source/Host/common/Editline.cpp
@@ -13,6 +13,7 @@
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Editline.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -172,7 +173,8 @@ private:
const char *GetHistoryFilePath() {
if (m_path.empty() && m_history && !m_prefix.empty()) {
- FileSpec parent_path{"~/.lldb", true};
+ FileSpec parent_path("~/.lldb");
+ FileSystem::Instance().Resolve(parent_path);
char history_path[PATH_MAX];
if (!llvm::sys::fs::create_directory(parent_path.GetPath())) {
snprintf(history_path, sizeof(history_path), "~/.lldb/%s-history",
@@ -181,7 +183,9 @@ private:
snprintf(history_path, sizeof(history_path), "~/%s-widehistory",
m_prefix.c_str());
}
- m_path = FileSpec(history_path, true).GetPath();
+ auto file_spec = FileSpec(history_path);
+ FileSystem::Instance().Resolve(file_spec);
+ m_path = file_spec.GetPath();
}
if (m_path.empty())
return NULL;
@@ -426,7 +430,7 @@ unsigned char Editline::RecallHistory(bool earlier) {
// Treat moving from the "live" entry differently
if (!m_in_history) {
- if (earlier == false)
+ if (!earlier)
return CC_ERROR; // Can't go newer than the "live" entry
if (history_w(pHistory, &history_event, H_FIRST) == -1)
return CC_ERROR;
@@ -439,7 +443,7 @@ unsigned char Editline::RecallHistory(bool earlier) {
m_live_history_lines = m_input_lines;
m_in_history = true;
} else {
- if (history_w(pHistory, &history_event, earlier ? H_NEXT : H_PREV) == -1) {
+ if (history_w(pHistory, &history_event, earlier ? H_PREV : H_NEXT) == -1) {
// Can't move earlier than the earliest entry
if (earlier)
return CC_ERROR;
@@ -526,7 +530,7 @@ int Editline::GetCharacter(EditLineGetCharType *c) {
break;
case lldb::eConnectionStatusInterrupted:
- lldbassert(0 && "Interrupts should have been handled above.");
+ llvm_unreachable("Interrupts should have been handled above.");
case lldb::eConnectionStatusError: // Check GetError() for details
case lldb::eConnectionStatusTimedOut: // Request timed out
@@ -853,19 +857,45 @@ unsigned char Editline::BufferEndCommand(int ch) {
return CC_NEWLINE;
}
+//------------------------------------------------------------------------------
+/// Prints completions and their descriptions to the given file. Only the
+/// completions in the interval [start, end) are printed.
+//------------------------------------------------------------------------------
+static void PrintCompletion(FILE *output_file, size_t start, size_t end,
+ StringList &completions, StringList &descriptions) {
+ // This is an 'int' because of printf.
+ int max_len = 0;
+
+ for (size_t i = start; i < end; i++) {
+ const char *completion_str = completions.GetStringAtIndex(i);
+ max_len = std::max((int)strlen(completion_str), max_len);
+ }
+
+ for (size_t i = start; i < end; i++) {
+ const char *completion_str = completions.GetStringAtIndex(i);
+ const char *description_str = descriptions.GetStringAtIndex(i);
+
+ fprintf(output_file, "\n\t%-*s", max_len, completion_str);
+
+ // Print the description if we got one.
+ if (strlen(description_str))
+ fprintf(output_file, " -- %s", description_str);
+ }
+}
+
unsigned char Editline::TabCommand(int ch) {
if (m_completion_callback == nullptr)
return CC_ERROR;
const LineInfo *line_info = el_line(m_editline);
- StringList completions;
+ StringList completions, descriptions;
int page_size = 40;
const int num_completions = m_completion_callback(
line_info->buffer, line_info->cursor, line_info->lastchar,
0, // Don't skip any matches (start at match zero)
-1, // Get all the matches
- completions, m_completion_callback_baton);
+ completions, descriptions, m_completion_callback_baton);
if (num_completions == 0)
return CC_ERROR;
@@ -893,10 +923,8 @@ unsigned char Editline::TabCommand(int ch) {
int num_elements = num_completions + 1;
fprintf(m_output_file, "\n" ANSI_CLEAR_BELOW "Available completions:");
if (num_completions < page_size) {
- for (int i = 1; i < num_elements; i++) {
- completion_str = completions.GetStringAtIndex(i);
- fprintf(m_output_file, "\n\t%s", completion_str);
- }
+ PrintCompletion(m_output_file, 1, num_elements, completions,
+ descriptions);
fprintf(m_output_file, "\n");
} else {
int cur_pos = 1;
@@ -906,10 +934,10 @@ unsigned char Editline::TabCommand(int ch) {
int endpoint = cur_pos + page_size;
if (endpoint > num_elements)
endpoint = num_elements;
- for (; cur_pos < endpoint; cur_pos++) {
- completion_str = completions.GetStringAtIndex(cur_pos);
- fprintf(m_output_file, "\n\t%s", completion_str);
- }
+
+ PrintCompletion(m_output_file, cur_pos, endpoint, completions,
+ descriptions);
+ cur_pos = endpoint;
if (cur_pos >= num_elements) {
fprintf(m_output_file, "\n");
diff --git a/source/Host/common/File.cpp b/source/Host/common/File.cpp
index 3c3d55df2207..810c15588402 100644
--- a/source/Host/common/File.cpp
+++ b/source/Host/common/File.cpp
@@ -27,9 +27,10 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
+#include "llvm/Support/Process.h"
#include "lldb/Host/Config.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
@@ -71,26 +72,6 @@ static const char *GetStreamOpenModeFromOptions(uint32_t options) {
int File::kInvalidDescriptor = -1;
FILE *File::kInvalidStream = NULL;
-File::File(const char *path, uint32_t options, uint32_t permissions)
- : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
- m_stream(kInvalidStream), m_options(), m_own_stream(false),
- m_is_interactive(eLazyBoolCalculate),
- m_is_real_terminal(eLazyBoolCalculate) {
- Open(path, options, permissions);
-}
-
-File::File(const FileSpec &filespec, uint32_t options, uint32_t permissions)
- : IOObject(eFDTypeFile, false), m_descriptor(kInvalidDescriptor),
- m_stream(kInvalidStream), m_options(0), m_own_stream(false),
- m_is_interactive(eLazyBoolCalculate),
- m_is_real_terminal(eLazyBoolCalculate)
-
-{
- if (filespec) {
- Open(filespec.GetPath().c_str(), options, permissions);
- }
-}
-
File::~File() { Close(); }
int File::GetDescriptor() const {
@@ -159,108 +140,6 @@ void File::SetStream(FILE *fh, bool transfer_ownership) {
m_own_stream = transfer_ownership;
}
-static int DoOpen(const char *path, int flags, int mode) {
-#ifdef _MSC_VER
- std::wstring wpath;
- if (!llvm::ConvertUTF8toWide(path, wpath))
- return -1;
- int result;
- ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode);
- return result;
-#else
- return ::open(path, flags, mode);
-#endif
-}
-
-Status File::Open(const char *path, uint32_t options, uint32_t permissions) {
- Status error;
- if (IsValid())
- Close();
-
- int oflag = 0;
- const bool read = options & eOpenOptionRead;
- const bool write = options & eOpenOptionWrite;
- if (write) {
- if (read)
- oflag |= O_RDWR;
- else
- oflag |= O_WRONLY;
-
- if (options & eOpenOptionAppend)
- oflag |= O_APPEND;
-
- if (options & eOpenOptionTruncate)
- oflag |= O_TRUNC;
-
- if (options & eOpenOptionCanCreate)
- oflag |= O_CREAT;
-
- if (options & eOpenOptionCanCreateNewOnly)
- oflag |= O_CREAT | O_EXCL;
- } else if (read) {
- oflag |= O_RDONLY;
-
-#ifndef _WIN32
- if (options & eOpenOptionDontFollowSymlinks)
- oflag |= O_NOFOLLOW;
-#endif
- }
-
-#ifndef _WIN32
- if (options & eOpenOptionNonBlocking)
- oflag |= O_NONBLOCK;
- if (options & eOpenOptionCloseOnExec)
- oflag |= O_CLOEXEC;
-#else
- oflag |= O_BINARY;
-#endif
-
- mode_t mode = 0;
- if (oflag & O_CREAT) {
- if (permissions & lldb::eFilePermissionsUserRead)
- mode |= S_IRUSR;
- if (permissions & lldb::eFilePermissionsUserWrite)
- mode |= S_IWUSR;
- if (permissions & lldb::eFilePermissionsUserExecute)
- mode |= S_IXUSR;
- if (permissions & lldb::eFilePermissionsGroupRead)
- mode |= S_IRGRP;
- if (permissions & lldb::eFilePermissionsGroupWrite)
- mode |= S_IWGRP;
- if (permissions & lldb::eFilePermissionsGroupExecute)
- mode |= S_IXGRP;
- if (permissions & lldb::eFilePermissionsWorldRead)
- mode |= S_IROTH;
- if (permissions & lldb::eFilePermissionsWorldWrite)
- mode |= S_IWOTH;
- if (permissions & lldb::eFilePermissionsWorldExecute)
- mode |= S_IXOTH;
- }
-
- m_descriptor = llvm::sys::RetryAfterSignal(-1, DoOpen, path, oflag, mode);
- if (!DescriptorIsValid())
- error.SetErrorToErrno();
- else {
- m_should_close_fd = true;
- m_options = options;
- }
-
- return error;
-}
-
-uint32_t File::GetPermissions(const FileSpec &file_spec, Status &error) {
- if (file_spec) {
- error.Clear();
- auto Perms = llvm::sys::fs::getPermissions(file_spec.GetPath());
- if (Perms)
- return *Perms;
- error = Status(Perms.getError());
- return 0;
- } else
- error.SetErrorString("empty file spec");
- return 0;
-}
-
uint32_t File::GetPermissions(Status &error) const {
int fd = GetDescriptor();
if (fd != kInvalidDescriptor) {
@@ -315,7 +194,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const {
if (::fcntl(GetDescriptor(), F_GETPATH, path) == -1)
error.SetErrorToErrno();
else
- file_spec.SetFile(path, false, FileSpec::Style::native);
+ file_spec.SetFile(path, FileSpec::Style::native);
} else {
error.SetErrorString("invalid file handle");
}
@@ -330,7 +209,7 @@ Status File::GetFileSpec(FileSpec &file_spec) const {
error.SetErrorToErrno();
else {
path[len] = '\0';
- file_spec.SetFile(path, false, FileSpec::Style::native);
+ file_spec.SetFile(path, FileSpec::Style::native);
}
}
#else
@@ -806,6 +685,9 @@ void File::CalculateInteractiveAndTerminal() {
if (_isatty(fd)) {
m_is_interactive = eLazyBoolYes;
m_is_real_terminal = eLazyBoolYes;
+#if defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+ m_supports_colors = eLazyBoolYes;
+#endif
}
#else
if (isatty(fd)) {
diff --git a/source/Host/common/FileCache.cpp b/source/Host/common/FileCache.cpp
index b4629255c852..17833ef2cbb3 100644
--- a/source/Host/common/FileCache.cpp
+++ b/source/Host/common/FileCache.cpp
@@ -10,6 +10,7 @@
#include "lldb/Host/FileCache.h"
#include "lldb/Host/File.h"
+#include "lldb/Host/FileSystem.h"
using namespace lldb;
using namespace lldb_private;
@@ -25,14 +26,13 @@ FileCache &FileCache::GetInstance() {
lldb::user_id_t FileCache::OpenFile(const FileSpec &file_spec, uint32_t flags,
uint32_t mode, Status &error) {
- std::string path(file_spec.GetPath());
- if (path.empty()) {
+ if (!file_spec) {
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)
+ error = FileSystem::Instance().Open(*file_sp, file_spec, flags, mode);
+ if (!file_sp->IsValid())
return UINT64_MAX;
lldb::user_id_t fd = file_sp->GetDescriptor();
m_cache[fd] = file_sp;
diff --git a/source/Host/common/FileSystem.cpp b/source/Host/common/FileSystem.cpp
index 4472aece1daa..7191c9db9b2e 100644
--- a/source/Host/common/FileSystem.cpp
+++ b/source/Host/common/FileSystem.cpp
@@ -9,7 +9,29 @@
#include "lldb/Host/FileSystem.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/TildeExpressionResolver.h"
+
+#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Threading.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#include "lldb/Host/windows/windows.h"
+#else
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <unistd.h>
+#endif
#include <algorithm>
#include <fstream>
@@ -17,12 +39,366 @@
using namespace lldb;
using namespace lldb_private;
+using namespace llvm;
+
+FileSystem &FileSystem::Instance() { return *InstanceImpl(); }
+
+void FileSystem::Initialize() {
+ lldbassert(!InstanceImpl() && "Already initialized.");
+ InstanceImpl().emplace();
+}
+
+void FileSystem::Initialize(IntrusiveRefCntPtr<vfs::FileSystem> fs) {
+ lldbassert(!InstanceImpl() && "Already initialized.");
+ InstanceImpl().emplace(fs);
+}
+
+void FileSystem::Terminate() {
+ lldbassert(InstanceImpl() && "Already terminated.");
+ InstanceImpl().reset();
+}
+
+Optional<FileSystem> &FileSystem::InstanceImpl() {
+ static Optional<FileSystem> g_fs;
+ return g_fs;
+}
+
+vfs::directory_iterator FileSystem::DirBegin(const FileSpec &file_spec,
+ std::error_code &ec) {
+ return DirBegin(file_spec.GetPath(), ec);
+}
+
+vfs::directory_iterator FileSystem::DirBegin(const Twine &dir,
+ std::error_code &ec) {
+ return m_fs->dir_begin(dir, ec);
+}
+
+llvm::ErrorOr<vfs::Status>
+FileSystem::GetStatus(const FileSpec &file_spec) const {
+ return GetStatus(file_spec.GetPath());
+}
+
+llvm::ErrorOr<vfs::Status> FileSystem::GetStatus(const Twine &path) const {
+ return m_fs->status(path);
+}
+
+sys::TimePoint<>
+FileSystem::GetModificationTime(const FileSpec &file_spec) const {
+ return GetModificationTime(file_spec.GetPath());
+}
+
+sys::TimePoint<> FileSystem::GetModificationTime(const Twine &path) const {
+ ErrorOr<vfs::Status> status = m_fs->status(path);
+ if (!status)
+ return sys::TimePoint<>();
+ return status->getLastModificationTime();
+}
+
+uint64_t FileSystem::GetByteSize(const FileSpec &file_spec) const {
+ return GetByteSize(file_spec.GetPath());
+}
+
+uint64_t FileSystem::GetByteSize(const Twine &path) const {
+ ErrorOr<vfs::Status> status = m_fs->status(path);
+ if (!status)
+ return 0;
+ return status->getSize();
+}
+
+uint32_t FileSystem::GetPermissions(const FileSpec &file_spec) const {
+ return GetPermissions(file_spec.GetPath());
+}
+
+uint32_t FileSystem::GetPermissions(const FileSpec &file_spec,
+ std::error_code &ec) const {
+ return GetPermissions(file_spec.GetPath(), ec);
+}
+
+uint32_t FileSystem::GetPermissions(const Twine &path) const {
+ std::error_code ec;
+ return GetPermissions(path, ec);
+}
+
+uint32_t FileSystem::GetPermissions(const Twine &path,
+ std::error_code &ec) const {
+ ErrorOr<vfs::Status> status = m_fs->status(path);
+ if (!status) {
+ ec = status.getError();
+ return sys::fs::perms::perms_not_known;
+ }
+ return status->getPermissions();
+}
+
+bool FileSystem::Exists(const Twine &path) const { return m_fs->exists(path); }
+
+bool FileSystem::Exists(const FileSpec &file_spec) const {
+ return Exists(file_spec.GetPath());
+}
+
+bool FileSystem::Readable(const Twine &path) const {
+ return GetPermissions(path) & sys::fs::perms::all_read;
+}
+
+bool FileSystem::Readable(const FileSpec &file_spec) const {
+ return Readable(file_spec.GetPath());
+}
+
+bool FileSystem::IsDirectory(const Twine &path) const {
+ ErrorOr<vfs::Status> status = m_fs->status(path);
+ if (!status)
+ return false;
+ return status->isDirectory();
+}
+
+bool FileSystem::IsDirectory(const FileSpec &file_spec) const {
+ return IsDirectory(file_spec.GetPath());
+}
+
+bool FileSystem::IsLocal(const Twine &path) const {
+ bool b = false;
+ m_fs->isLocal(path, b);
+ return b;
+}
+
+bool FileSystem::IsLocal(const FileSpec &file_spec) const {
+ return IsLocal(file_spec.GetPath());
+}
+
+void FileSystem::EnumerateDirectory(Twine path, bool find_directories,
+ bool find_files, bool find_other,
+ EnumerateDirectoryCallbackType callback,
+ void *callback_baton) {
+ std::error_code EC;
+ vfs::recursive_directory_iterator Iter(*m_fs, path, EC);
+ vfs::recursive_directory_iterator End;
+ for (; Iter != End && !EC; Iter.increment(EC)) {
+ const auto &Item = *Iter;
+ ErrorOr<vfs::Status> Status = m_fs->status(Item.path());
+ if (!Status)
+ break;
+ if (!find_files && Status->isRegularFile())
+ continue;
+ if (!find_directories && Status->isDirectory())
+ continue;
+ if (!find_other && Status->isOther())
+ continue;
+
+ auto Result = callback(callback_baton, Status->getType(), Item.path());
+ if (Result == eEnumerateDirectoryResultQuit)
+ return;
+ if (Result == eEnumerateDirectoryResultNext) {
+ // Default behavior is to recurse. Opt out if the callback doesn't want
+ // this behavior.
+ Iter.no_push();
+ }
+ }
+}
+
+std::error_code FileSystem::MakeAbsolute(SmallVectorImpl<char> &path) const {
+ return m_fs->makeAbsolute(path);
+}
+
+std::error_code FileSystem::MakeAbsolute(FileSpec &file_spec) const {
+ SmallString<128> path;
+ file_spec.GetPath(path, false);
+
+ auto EC = MakeAbsolute(path);
+ if (EC)
+ return EC;
+
+ FileSpec new_file_spec(path, file_spec.GetPathStyle());
+ file_spec = new_file_spec;
+ return {};
+}
+
+std::error_code FileSystem::GetRealPath(const Twine &path,
+ SmallVectorImpl<char> &output) const {
+ return m_fs->getRealPath(path, output);
+}
+
+void FileSystem::Resolve(SmallVectorImpl<char> &path) {
+ if (path.empty())
+ return;
+
+ // Resolve tilde.
+ SmallString<128> original_path(path.begin(), path.end());
+ StandardTildeExpressionResolver Resolver;
+ Resolver.ResolveFullPath(original_path, path);
+
+ // Try making the path absolute if it exists.
+ SmallString<128> absolute_path(path.begin(), path.end());
+ MakeAbsolute(path);
+ if (!Exists(path)) {
+ path.clear();
+ path.append(original_path.begin(), original_path.end());
+ }
+}
+
+void FileSystem::Resolve(FileSpec &file_spec) {
+ // Extract path from the FileSpec.
+ SmallString<128> path;
+ file_spec.GetPath(path);
+
+ // Resolve the path.
+ Resolve(path);
+
+ // Update the FileSpec with the resolved path.
+ file_spec.SetPath(path);
+ file_spec.SetIsResolved(true);
+}
+
+std::shared_ptr<DataBufferLLVM>
+FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
+ uint64_t offset) {
+ const bool is_volatile = !IsLocal(path);
+
+ std::unique_ptr<llvm::WritableMemoryBuffer> buffer;
+ if (size == 0) {
+ auto buffer_or_error =
+ llvm::WritableMemoryBuffer::getFile(path, -1, is_volatile);
+ if (!buffer_or_error)
+ return nullptr;
+ buffer = std::move(*buffer_or_error);
+ } else {
+ auto buffer_or_error = llvm::WritableMemoryBuffer::getFileSlice(
+ path, size, offset, is_volatile);
+ if (!buffer_or_error)
+ return nullptr;
+ buffer = std::move(*buffer_or_error);
+ }
+ return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer)));
+}
+
+std::shared_ptr<DataBufferLLVM>
+FileSystem::CreateDataBuffer(const FileSpec &file_spec, uint64_t size,
+ uint64_t offset) {
+ return CreateDataBuffer(file_spec.GetPath(), size, offset);
+}
+
+bool FileSystem::ResolveExecutableLocation(FileSpec &file_spec) {
+ // If the directory is set there's nothing to do.
+ const ConstString &directory = file_spec.GetDirectory();
+ if (directory)
+ return false;
+
+ // We cannot look for a file if there's no file name.
+ const ConstString &filename = file_spec.GetFilename();
+ if (!filename)
+ return false;
+
+ // Search for the file on the host.
+ const std::string filename_str(filename.GetCString());
+ llvm::ErrorOr<std::string> error_or_path =
+ llvm::sys::findProgramByName(filename_str);
+ if (!error_or_path)
+ return false;
+
+ // findProgramByName returns "." if it can't find the file.
+ llvm::StringRef path = *error_or_path;
+ llvm::StringRef parent = llvm::sys::path::parent_path(path);
+ if (parent.empty() || parent == ".")
+ return false;
+
+ // Make sure that the result exists.
+ FileSpec result(*error_or_path);
+ if (!Exists(result))
+ return false;
+
+ file_spec = result;
+ return true;
+}
+
+static int OpenWithFS(const FileSystem &fs, const char *path, int flags,
+ int mode) {
+ return const_cast<FileSystem &>(fs).Open(path, flags, mode);
+}
+
+static int GetOpenFlags(uint32_t options) {
+ const bool read = options & File::eOpenOptionRead;
+ const bool write = options & File::eOpenOptionWrite;
+
+ int open_flags = 0;
+ if (write) {
+ if (read)
+ open_flags |= O_RDWR;
+ else
+ open_flags |= O_WRONLY;
+
+ if (options & File::eOpenOptionAppend)
+ open_flags |= O_APPEND;
+
+ if (options & File::eOpenOptionTruncate)
+ open_flags |= O_TRUNC;
+
+ if (options & File::eOpenOptionCanCreate)
+ open_flags |= O_CREAT;
+
+ if (options & File::eOpenOptionCanCreateNewOnly)
+ open_flags |= O_CREAT | O_EXCL;
+ } else if (read) {
+ open_flags |= O_RDONLY;
+
+#ifndef _WIN32
+ if (options & File::eOpenOptionDontFollowSymlinks)
+ open_flags |= O_NOFOLLOW;
+#endif
+ }
+
+#ifndef _WIN32
+ if (options & File::eOpenOptionNonBlocking)
+ open_flags |= O_NONBLOCK;
+ if (options & File::eOpenOptionCloseOnExec)
+ open_flags |= O_CLOEXEC;
+#else
+ open_flags |= O_BINARY;
+#endif
+
+ return open_flags;
+}
+
+static mode_t GetOpenMode(uint32_t permissions) {
+ mode_t mode = 0;
+ if (permissions & lldb::eFilePermissionsUserRead)
+ mode |= S_IRUSR;
+ if (permissions & lldb::eFilePermissionsUserWrite)
+ mode |= S_IWUSR;
+ if (permissions & lldb::eFilePermissionsUserExecute)
+ mode |= S_IXUSR;
+ if (permissions & lldb::eFilePermissionsGroupRead)
+ mode |= S_IRGRP;
+ if (permissions & lldb::eFilePermissionsGroupWrite)
+ mode |= S_IWGRP;
+ if (permissions & lldb::eFilePermissionsGroupExecute)
+ mode |= S_IXGRP;
+ if (permissions & lldb::eFilePermissionsWorldRead)
+ mode |= S_IROTH;
+ if (permissions & lldb::eFilePermissionsWorldWrite)
+ mode |= S_IWOTH;
+ if (permissions & lldb::eFilePermissionsWorldExecute)
+ mode |= S_IXOTH;
+ return mode;
+}
+
+Status FileSystem::Open(File &File, const FileSpec &file_spec, uint32_t options,
+ uint32_t permissions) {
+ if (File.IsValid())
+ File.Close();
+
+ const int open_flags = GetOpenFlags(options);
+ const mode_t open_mode =
+ (open_flags & O_CREAT) ? GetOpenMode(permissions) : 0;
+ const std::string path = file_spec.GetPath();
+
+ int descriptor = llvm::sys::RetryAfterSignal(
+ -1, OpenWithFS, *this, path.c_str(), open_flags, open_mode);
-llvm::sys::TimePoint<>
-FileSystem::GetModificationTime(const FileSpec &file_spec) {
- llvm::sys::fs::file_status status;
- std::error_code ec = llvm::sys::fs::status(file_spec.GetPath(), status);
- if (ec)
- return llvm::sys::TimePoint<>();
- return status.getLastModificationTime();
+ Status error;
+ if (!File::DescriptorIsValid(descriptor)) {
+ File.SetDescriptor(descriptor, false);
+ error.SetErrorToErrno();
+ } else {
+ File.SetDescriptor(descriptor, true);
+ File.SetOptions(options);
+ }
+ return error;
}
diff --git a/source/Host/common/Host.cpp b/source/Host/common/Host.cpp
index d2848254779e..62b936aadef1 100644
--- a/source/Host/common/Host.cpp
+++ b/source/Host/common/Host.cpp
@@ -45,14 +45,13 @@
#include <lwp.h>
#endif
-// C++ Includes
#include <csignal>
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/MonitoringProcessLauncher.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Host/ProcessLauncher.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
@@ -62,6 +61,7 @@
#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-forward.h"
#include "llvm/ADT/SmallString.h"
@@ -419,8 +419,10 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
#if !defined(__ANDROID__)
Dl_info info;
if (::dladdr(host_addr, &info)) {
- if (info.dli_fname)
- module_filespec.SetFile(info.dli_fname, true, FileSpec::Style::native);
+ if (info.dli_fname) {
+ module_filespec.SetFile(info.dli_fname, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_filespec);
+ }
}
#endif
return module_filespec;
@@ -494,7 +496,7 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
if (working_dir)
launch_info.SetWorkingDirectory(working_dir);
- llvm::SmallString<PATH_MAX> output_file_path;
+ llvm::SmallString<64> output_file_path;
if (command_output_ptr) {
// Create a temporary file to get the stdout/stderr and redirect the output
@@ -510,7 +512,7 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
}
}
- FileSpec output_file_spec{output_file_path.c_str(), false};
+ FileSpec output_file_spec(output_file_path.c_str());
launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false);
if (output_file_spec) {
@@ -554,14 +556,15 @@ Status Host::RunShellCommand(const Args &args, const FileSpec &working_dir,
if (command_output_ptr) {
command_output_ptr->clear();
- uint64_t file_size = output_file_spec.GetByteSize();
+ uint64_t file_size =
+ FileSystem::Instance().GetByteSize(output_file_spec);
if (file_size > 0) {
if (file_size > command_output_ptr->max_size()) {
error.SetErrorStringWithFormat(
"shell command output is too large to fit into a std::string");
} else {
auto Buffer =
- DataBufferLLVM::CreateFromPath(output_file_spec.GetPath());
+ FileSystem::Instance().CreateDataBuffer(output_file_spec);
if (error.Success())
command_output_ptr->assign(Buffer->GetChars(),
Buffer->GetByteSize());
diff --git a/source/Host/common/HostInfoBase.cpp b/source/Host/common/HostInfoBase.cpp
index 4de6953a91e3..34c362efc9e0 100644
--- a/source/Host/common/HostInfoBase.cpp
+++ b/source/Host/common/HostInfoBase.cpp
@@ -42,7 +42,7 @@ namespace {
struct HostInfoBaseFields {
~HostInfoBaseFields() {
- if (m_lldb_process_tmp_dir.Exists()) {
+ if (FileSystem::Instance().Exists(m_lldb_process_tmp_dir)) {
// Remove the LLDB temporary directory if we have one. Set "recurse" to
// true to all files that were created for the LLDB process can be
// cleaned up.
@@ -226,7 +226,7 @@ bool HostInfoBase::ComputeSharedLibraryDirectory(FileSpec &file_spec) {
// This is necessary because when running the testsuite the shlib might be a
// symbolic link inside the Python resource dir.
- FileSystem::ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
+ FileSystem::Instance().ResolveSymbolicLink(lldb_file_spec, lldb_file_spec);
// Remove the filename so that this FileSpec only represents the directory.
file_spec.GetDirectory() = lldb_file_spec.GetDirectory();
@@ -256,7 +256,8 @@ bool HostInfoBase::ComputeProcessTempFileDirectory(FileSpec &file_spec) {
bool HostInfoBase::ComputeTempFileBaseDirectory(FileSpec &file_spec) {
llvm::SmallVector<char, 16> tmpdir;
llvm::sys::path::system_temp_directory(/*ErasedOnReboot*/ true, tmpdir);
- file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()), true);
+ file_spec = FileSpec(std::string(tmpdir.data(), tmpdir.size()));
+ FileSystem::Instance().Resolve(file_spec);
return true;
}
diff --git a/source/Host/common/HostNativeThreadBase.cpp b/source/Host/common/HostNativeThreadBase.cpp
index 402d3caacfcb..25c8066bb1a3 100644
--- a/source/Host/common/HostNativeThreadBase.cpp
+++ b/source/Host/common/HostNativeThreadBase.cpp
@@ -41,6 +41,10 @@ void HostNativeThreadBase::Reset() {
m_result = 0;
}
+bool HostNativeThreadBase::EqualsThread(lldb::thread_t thread) const {
+ return m_thread == thread;
+}
+
lldb::thread_t HostNativeThreadBase::Release() {
lldb::thread_t result = m_thread;
m_thread = LLDB_INVALID_HOST_THREAD;
diff --git a/source/Host/common/HostThread.cpp b/source/Host/common/HostThread.cpp
index 02882c523908..2bf6f0a933d8 100644
--- a/source/Host/common/HostThread.cpp
+++ b/source/Host/common/HostThread.cpp
@@ -43,5 +43,5 @@ lldb::thread_result_t HostThread::GetResult() const {
}
bool HostThread::EqualsThread(lldb::thread_t thread) const {
- return m_native_thread->GetSystemHandle() == thread;
+ return m_native_thread->EqualsThread(thread);
}
diff --git a/source/Host/common/MainLoop.cpp b/source/Host/common/MainLoop.cpp
index 65158c942934..39c353e6717e 100644
--- a/source/Host/common/MainLoop.cpp
+++ b/source/Host/common/MainLoop.cpp
@@ -309,7 +309,7 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
g_signal_flags[signo] = 0;
// Even if using kqueue, the signal handler will still be invoked, so it's
- // important to replace it with our "bening" handler.
+ // important to replace it with our "benign" handler.
int ret = sigaction(signo, &new_action, &info.old_action);
assert(ret == 0 && "sigaction failed");
@@ -321,7 +321,7 @@ MainLoop::RegisterSignal(int signo, const Callback &callback, Status &error) {
#endif
// If we're using kqueue, the signal needs to be unblocked in order to
- // recieve it. If using pselect/ppoll, we need to block it, and later unblock
+ // receive it. If using pselect/ppoll, we need to block it, and later unblock
// it as a part of the system call.
ret = pthread_sigmask(HAVE_SYS_EVENT_H ? SIG_UNBLOCK : SIG_BLOCK,
&new_action.sa_mask, &old_set);
diff --git a/source/Host/common/MonitoringProcessLauncher.cpp b/source/Host/common/MonitoringProcessLauncher.cpp
index 76c11454f573..f6f772cb3679 100644
--- a/source/Host/common/MonitoringProcessLauncher.cpp
+++ b/source/Host/common/MonitoringProcessLauncher.cpp
@@ -8,10 +8,10 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/MonitoringProcessLauncher.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Status.h"
#include "llvm/Support/FileSystem.h"
@@ -29,20 +29,16 @@ MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info,
error.Clear();
+ FileSystem &fs = FileSystem::Instance();
FileSpec exe_spec(resolved_info.GetExecutableFile());
- llvm::sys::fs::file_status stats;
- status(exe_spec.GetPath(), stats);
- if (!exists(stats)) {
- exe_spec.ResolvePath();
- status(exe_spec.GetPath(), stats);
- }
- if (!exists(stats)) {
- exe_spec.ResolveExecutableLocation();
- status(exe_spec.GetPath(), stats);
- }
+ if (!fs.Exists(exe_spec))
+ FileSystem::Instance().Resolve(exe_spec);
+
+ if (!fs.Exists(exe_spec))
+ FileSystem::Instance().ResolveExecutableLocation(exe_spec);
- if (!exists(stats)) {
+ if (!fs.Exists(exe_spec)) {
error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'",
exe_spec);
return HostProcess();
diff --git a/source/Host/common/NativeBreakpoint.cpp b/source/Host/common/NativeBreakpoint.cpp
deleted file mode 100644
index 5eee3de482c1..000000000000
--- a/source/Host/common/NativeBreakpoint.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-//===-- NativeBreakpoint.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/common/NativeBreakpoint.h"
-
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Status.h"
-#include "lldb/lldb-defines.h"
-
-using namespace lldb_private;
-
-NativeBreakpoint::NativeBreakpoint(lldb::addr_t addr)
- : m_addr(addr), m_ref_count(1), m_enabled(true) {
- assert(addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address");
-}
-
-NativeBreakpoint::~NativeBreakpoint() {}
-
-void NativeBreakpoint::AddRef() {
- ++m_ref_count;
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64
- " bumped up, new ref count %" PRIu32,
- __FUNCTION__, m_addr, m_ref_count);
-}
-
-int32_t NativeBreakpoint::DecRef() {
- --m_ref_count;
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64
- " ref count decremented, new ref count %" PRIu32,
- __FUNCTION__, m_addr, m_ref_count);
-
- return m_ref_count;
-}
-
-Status NativeBreakpoint::Enable() {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- if (m_enabled) {
- // We're already enabled. Just log and exit.
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64
- " already enabled, ignoring.",
- __FUNCTION__, m_addr);
- return Status();
- }
-
- // Log and enable.
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...",
- __FUNCTION__, m_addr);
-
- Status error = DoEnable();
- if (error.Success()) {
- m_enabled = true;
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.",
- __FUNCTION__, m_addr);
- } else {
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s",
- __FUNCTION__, m_addr, error.AsCString());
- }
-
- return error;
-}
-
-Status NativeBreakpoint::Disable() {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- if (!m_enabled) {
- // We're already disabled. Just log and exit.
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64
- " already disabled, ignoring.",
- __FUNCTION__, m_addr);
- return Status();
- }
-
- // Log and disable.
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...",
- __FUNCTION__, m_addr);
-
- Status error = DoDisable();
- if (error.Success()) {
- m_enabled = false;
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.",
- __FUNCTION__, m_addr);
- } else {
- if (log)
- log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s",
- __FUNCTION__, m_addr, error.AsCString());
- }
-
- return error;
-}
diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp
deleted file mode 100644
index cfcbe0831064..000000000000
--- a/source/Host/common/NativeBreakpointList.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-//===-- NativeBreakpointList.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/common/NativeBreakpointList.h"
-
-#include "lldb/Utility/Log.h"
-
-#include "lldb/Host/common/NativeBreakpoint.h"
-#include "lldb/Host/common/SoftwareBreakpoint.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-NativeBreakpointList::NativeBreakpointList() : m_mutex() {}
-
-Status NativeBreakpointList::AddRef(lldb::addr_t addr, size_t size_hint,
- bool hardware,
- CreateBreakpointFunc create_func) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- ", size_hint = %zu, hardware = %s",
- __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
-
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- // Check if the breakpoint is already set.
- auto iter = m_breakpoints.find(addr);
- if (iter != m_breakpoints.end()) {
- // Yes - bump up ref count.
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- already enabled, upping ref count",
- __FUNCTION__, addr);
-
- iter->second->AddRef();
- return Status();
- }
-
- // Create a new breakpoint using the given create func.
- if (log)
- log->Printf(
- "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64
- ", size_hint = %zu, hardware = %s",
- __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
-
- NativeBreakpointSP breakpoint_sp;
- Status error = create_func(addr, size_hint, hardware, breakpoint_sp);
- if (error.Fail()) {
- if (log)
- log->Printf(
- "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64
- ", size_hint = %zu, hardware = %s -- FAILED: %s",
- __FUNCTION__, addr, size_hint, hardware ? "true" : "false",
- error.AsCString());
- return error;
- }
-
- // Remember the breakpoint.
- assert(breakpoint_sp && "NativeBreakpoint create function succeeded but "
- "returned NULL breakpoint");
- m_breakpoints.insert(BreakpointMap::value_type(addr, breakpoint_sp));
-
- return error;
-}
-
-Status NativeBreakpointList::DecRef(lldb::addr_t addr) {
- Status error;
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
-
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- // Check if the breakpoint is already set.
- auto iter = m_breakpoints.find(addr);
- if (iter == m_breakpoints.end()) {
- // Not found!
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
- __FUNCTION__, addr);
- error.SetErrorString("breakpoint not found");
- return error;
- }
-
- // Decrement ref count.
- const int32_t new_ref_count = iter->second->DecRef();
- assert(new_ref_count >= 0 && "NativeBreakpoint ref count went negative");
-
- if (new_ref_count > 0) {
- // Still references to this breakpoint. Leave it alone.
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- new breakpoint ref count %" PRIu32,
- __FUNCTION__, addr, new_ref_count);
- return error;
- }
-
- // Breakpoint has no more references. Disable it if it's not already
- // disabled.
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- removing due to no remaining references",
- __FUNCTION__, addr);
-
- // If it's enabled, we need to disable it.
- if (iter->second->IsEnabled()) {
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- currently enabled, now disabling",
- __FUNCTION__, addr);
- error = iter->second->Disable();
- if (error.Fail()) {
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- removal FAILED: %s",
- __FUNCTION__, addr, error.AsCString());
- // Continue since we still want to take it out of the breakpoint list.
- }
- } else {
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- already disabled, nothing to do",
- __FUNCTION__, addr);
- }
-
- // Take the breakpoint out of the list.
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64
- " -- removed from breakpoint map",
- __FUNCTION__, addr);
-
- m_breakpoints.erase(iter);
- return error;
-}
-
-Status NativeBreakpointList::EnableBreakpoint(lldb::addr_t addr) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
-
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- // Ensure we have said breakpoint.
- auto iter = m_breakpoints.find(addr);
- if (iter == m_breakpoints.end()) {
- // Not found!
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
- __FUNCTION__, addr);
- return Status("breakpoint not found");
- }
-
- // Enable it.
- return iter->second->Enable();
-}
-
-Status NativeBreakpointList::DisableBreakpoint(lldb::addr_t addr) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
-
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- // Ensure we have said breakpoint.
- auto iter = m_breakpoints.find(addr);
- if (iter == m_breakpoints.end()) {
- // Not found!
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND",
- __FUNCTION__, addr);
- return Status("breakpoint not found");
- }
-
- // Disable it.
- return iter->second->Disable();
-}
-
-Status NativeBreakpointList::GetBreakpoint(lldb::addr_t addr,
- NativeBreakpointSP &breakpoint_sp) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
-
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- // Ensure we have said breakpoint.
- auto iter = m_breakpoints.find(addr);
- if (iter == m_breakpoints.end()) {
- // Not found!
- breakpoint_sp.reset();
- return Status("breakpoint not found");
- }
-
- // Disable it.
- breakpoint_sp = iter->second;
- return Status();
-}
-
-Status NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf,
- size_t size) const {
- for (const auto &map : m_breakpoints) {
- lldb::addr_t bp_addr = map.first;
- // Breapoint not in range, ignore
- if (bp_addr < addr || addr + size <= bp_addr)
- continue;
- const auto &bp_sp = map.second;
- // Not software breakpoint, ignore
- if (!bp_sp->IsSoftwareBreakpoint())
- continue;
- auto software_bp_sp = std::static_pointer_cast<SoftwareBreakpoint>(bp_sp);
- auto opcode_addr = static_cast<char *>(buf) + bp_addr - addr;
- auto saved_opcodes = software_bp_sp->m_saved_opcodes;
- auto opcode_size = software_bp_sp->m_opcode_size;
- ::memcpy(opcode_addr, saved_opcodes, opcode_size);
- }
- return Status();
-}
diff --git a/source/Host/common/NativeProcessProtocol.cpp b/source/Host/common/NativeProcessProtocol.cpp
index 3e8648f81473..e3c81f6c147b 100644
--- a/source/Host/common/NativeProcessProtocol.cpp
+++ b/source/Host/common/NativeProcessProtocol.cpp
@@ -8,13 +8,13 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/common/NativeProcessProtocol.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/common/NativeBreakpointList.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
-#include "lldb/Host/common/SoftwareBreakpoint.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/lldb-enumerations.h"
using namespace lldb;
@@ -359,17 +359,271 @@ void NativeProcessProtocol::NotifyDidExec() {
Status NativeProcessProtocol::SetSoftwareBreakpoint(lldb::addr_t addr,
uint32_t size_hint) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__,
- addr);
+ LLDB_LOG(log, "addr = {0:x}, size_hint = {1}", addr, size_hint);
+
+ auto it = m_software_breakpoints.find(addr);
+ if (it != m_software_breakpoints.end()) {
+ ++it->second.ref_count;
+ return Status();
+ }
+ auto expected_bkpt = EnableSoftwareBreakpoint(addr, size_hint);
+ if (!expected_bkpt)
+ return Status(expected_bkpt.takeError());
+
+ m_software_breakpoints.emplace(addr, std::move(*expected_bkpt));
+ return Status();
+}
+
+Status NativeProcessProtocol::RemoveSoftwareBreakpoint(lldb::addr_t addr) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ LLDB_LOG(log, "addr = {0:x}", addr);
+ auto it = m_software_breakpoints.find(addr);
+ if (it == m_software_breakpoints.end())
+ return Status("Breakpoint not found.");
+ assert(it->second.ref_count > 0);
+ if (--it->second.ref_count > 0)
+ return Status();
+
+ // This is the last reference. Let's remove the breakpoint.
+ Status error;
+
+ // Clear a software breakpoint instruction
+ llvm::SmallVector<uint8_t, 4> curr_break_op(
+ it->second.breakpoint_opcodes.size(), 0);
+
+ // Read the breakpoint opcode
+ size_t bytes_read = 0;
+ error =
+ ReadMemory(addr, curr_break_op.data(), curr_break_op.size(), bytes_read);
+ if (error.Fail() || bytes_read < curr_break_op.size()) {
+ return Status("addr=0x%" PRIx64
+ ": tried to read %zu bytes but only read %zu",
+ addr, curr_break_op.size(), bytes_read);
+ }
+ const auto &saved = it->second.saved_opcodes;
+ // Make sure the breakpoint opcode exists at this address
+ if (makeArrayRef(curr_break_op) != it->second.breakpoint_opcodes) {
+ if (curr_break_op != it->second.saved_opcodes)
+ return Status("Original breakpoint trap is no longer in memory.");
+ LLDB_LOG(log,
+ "Saved opcodes ({0:@[x]}) have already been restored at {1:x}.",
+ llvm::make_range(saved.begin(), saved.end()), addr);
+ } else {
+ // We found a valid breakpoint opcode at this address, now restore the
+ // saved opcode.
+ size_t bytes_written = 0;
+ error = WriteMemory(addr, saved.data(), saved.size(), bytes_written);
+ if (error.Fail() || bytes_written < saved.size()) {
+ return Status("addr=0x%" PRIx64
+ ": tried to write %zu bytes but only wrote %zu",
+ addr, saved.size(), bytes_written);
+ }
+
+ // Verify that our original opcode made it back to the inferior
+ llvm::SmallVector<uint8_t, 4> verify_opcode(saved.size(), 0);
+ size_t verify_bytes_read = 0;
+ error = ReadMemory(addr, verify_opcode.data(), verify_opcode.size(),
+ verify_bytes_read);
+ if (error.Fail() || verify_bytes_read < verify_opcode.size()) {
+ return Status("addr=0x%" PRIx64
+ ": tried to read %zu verification bytes but only read %zu",
+ addr, verify_opcode.size(), verify_bytes_read);
+ }
+ if (verify_opcode != saved)
+ LLDB_LOG(log, "Restoring bytes at {0:x}: {1:@[x]}", addr,
+ llvm::make_range(saved.begin(), saved.end()));
+ }
+
+ m_software_breakpoints.erase(it);
+ return Status();
+}
+
+llvm::Expected<NativeProcessProtocol::SoftwareBreakpoint>
+NativeProcessProtocol::EnableSoftwareBreakpoint(lldb::addr_t addr,
+ uint32_t size_hint) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ auto expected_trap = GetSoftwareBreakpointTrapOpcode(size_hint);
+ if (!expected_trap)
+ return expected_trap.takeError();
+
+ llvm::SmallVector<uint8_t, 4> saved_opcode_bytes(expected_trap->size(), 0);
+ // Save the original opcodes by reading them so we can restore later.
+ size_t bytes_read = 0;
+ Status error = ReadMemory(addr, saved_opcode_bytes.data(),
+ saved_opcode_bytes.size(), bytes_read);
+ if (error.Fail())
+ return error.ToError();
+
+ // Ensure we read as many bytes as we expected.
+ if (bytes_read != saved_opcode_bytes.size()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Failed to read memory while attempting to set breakpoint: attempted "
+ "to read {0} bytes but only read {1}.",
+ saved_opcode_bytes.size(), bytes_read);
+ }
+
+ LLDB_LOG(
+ log, "Overwriting bytes at {0:x}: {1:@[x]}", addr,
+ llvm::make_range(saved_opcode_bytes.begin(), saved_opcode_bytes.end()));
+
+ // Write a software breakpoint in place of the original opcode.
+ size_t bytes_written = 0;
+ error = WriteMemory(addr, expected_trap->data(), expected_trap->size(),
+ bytes_written);
+ if (error.Fail())
+ return error.ToError();
+
+ // Ensure we wrote as many bytes as we expected.
+ if (bytes_written != expected_trap->size()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Failed write memory while attempting to set "
+ "breakpoint: attempted to write {0} bytes but only wrote {1}",
+ expected_trap->size(), bytes_written);
+ }
+
+ llvm::SmallVector<uint8_t, 4> verify_bp_opcode_bytes(expected_trap->size(),
+ 0);
+ size_t verify_bytes_read = 0;
+ error = ReadMemory(addr, verify_bp_opcode_bytes.data(),
+ verify_bp_opcode_bytes.size(), verify_bytes_read);
+ if (error.Fail())
+ return error.ToError();
+
+ // Ensure we read as many verification bytes as we expected.
+ if (verify_bytes_read != verify_bp_opcode_bytes.size()) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Failed to read memory while "
+ "attempting to verify breakpoint: attempted to read {0} bytes "
+ "but only read {1}",
+ verify_bp_opcode_bytes.size(), verify_bytes_read);
+ }
+
+ if (llvm::makeArrayRef(verify_bp_opcode_bytes.data(), verify_bytes_read) !=
+ *expected_trap) {
+ return llvm::createStringError(
+ llvm::inconvertibleErrorCode(),
+ "Verification of software breakpoint "
+ "writing failed - trap opcodes not successfully read back "
+ "after writing when setting breakpoint at {0:x}",
+ addr);
+ }
+
+ LLDB_LOG(log, "addr = {0:x}: SUCCESS", addr);
+ return SoftwareBreakpoint{1, saved_opcode_bytes, *expected_trap};
+}
+
+llvm::Expected<llvm::ArrayRef<uint8_t>>
+NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
+ static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};
+ static const uint8_t g_i386_opcode[] = {0xCC};
+ static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d};
+ static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00};
+ static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
+ static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
+
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::aarch64:
+ return llvm::makeArrayRef(g_aarch64_opcode);
+
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ return llvm::makeArrayRef(g_i386_opcode);
+
+ case llvm::Triple::mips:
+ case llvm::Triple::mips64:
+ return llvm::makeArrayRef(g_mips64_opcode);
+
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64el:
+ return llvm::makeArrayRef(g_mips64el_opcode);
+
+ case llvm::Triple::systemz:
+ return llvm::makeArrayRef(g_s390x_opcode);
+
+ case llvm::Triple::ppc64le:
+ return llvm::makeArrayRef(g_ppc64le_opcode);
- return m_breakpoint_list.AddRef(
- addr, size_hint, false,
- [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */,
- NativeBreakpointSP &breakpoint_sp) -> Status {
- return SoftwareBreakpoint::CreateSoftwareBreakpoint(
- *this, addr, size_hint, breakpoint_sp);
- });
+ default:
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "CPU type not supported!");
+ }
+}
+
+size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() {
+ switch (GetArchitecture().GetMachine()) {
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ case llvm::Triple::systemz:
+ // These architectures report increment the PC after breakpoint is hit.
+ return cantFail(GetSoftwareBreakpointTrapOpcode(0)).size();
+
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::ppc64le:
+ // On these architectures the PC doesn't get updated for breakpoint hits.
+ return 0;
+
+ default:
+ llvm_unreachable("CPU type not supported!");
+ }
+}
+
+void NativeProcessProtocol::FixupBreakpointPCAsNeeded(
+ NativeThreadProtocol &thread) {
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS);
+
+ Status error;
+
+ // Find out the size of a breakpoint (might depend on where we are in the
+ // code).
+ NativeRegisterContext &context = thread.GetRegisterContext();
+
+ uint32_t breakpoint_size = GetSoftwareBreakpointPCOffset();
+ LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
+ if (breakpoint_size == 0)
+ return;
+
+ // First try probing for a breakpoint at a software breakpoint location: PC -
+ // breakpoint size.
+ const lldb::addr_t initial_pc_addr = context.GetPCfromBreakpointLocation();
+ lldb::addr_t breakpoint_addr = initial_pc_addr;
+ // Do not allow breakpoint probe to wrap around.
+ if (breakpoint_addr >= breakpoint_size)
+ breakpoint_addr -= breakpoint_size;
+
+ if (m_software_breakpoints.count(breakpoint_addr) == 0) {
+ // We didn't find one at a software probe location. Nothing to do.
+ LLDB_LOG(log,
+ "pid {0} no lldb software breakpoint found at current pc with "
+ "adjustment: {1}",
+ GetID(), breakpoint_addr);
+ return;
+ }
+
+ //
+ // We have a software breakpoint and need to adjust the PC.
+ //
+
+ // Change the program counter.
+ LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(),
+ thread.GetID(), initial_pc_addr, breakpoint_addr);
+
+ error = context.SetPC(breakpoint_addr);
+ if (error.Fail()) {
+ // This can happen in case the process was killed between the time we read
+ // the PC and when we are updating it. There's nothing better to do than to
+ // swallow the error.
+ LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(),
+ thread.GetID(), error);
+ }
}
Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr,
@@ -377,15 +631,35 @@ Status NativeProcessProtocol::RemoveBreakpoint(lldb::addr_t addr,
if (hardware)
return RemoveHardwareBreakpoint(addr);
else
- return m_breakpoint_list.DecRef(addr);
-}
-
-Status NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) {
- return m_breakpoint_list.EnableBreakpoint(addr);
+ return RemoveSoftwareBreakpoint(addr);
}
-Status NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) {
- return m_breakpoint_list.DisableBreakpoint(addr);
+Status NativeProcessProtocol::ReadMemoryWithoutTrap(lldb::addr_t addr,
+ void *buf, size_t size,
+ size_t &bytes_read) {
+ Status error = ReadMemory(addr, buf, size, bytes_read);
+ if (error.Fail())
+ return error;
+
+ auto data =
+ llvm::makeMutableArrayRef(static_cast<uint8_t *>(buf), bytes_read);
+ for (const auto &pair : m_software_breakpoints) {
+ lldb::addr_t bp_addr = pair.first;
+ auto saved_opcodes = makeArrayRef(pair.second.saved_opcodes);
+
+ if (bp_addr + saved_opcodes.size() < addr || addr + bytes_read <= bp_addr)
+ continue; // Breapoint not in range, ignore
+
+ if (bp_addr < addr) {
+ saved_opcodes = saved_opcodes.drop_front(addr - bp_addr);
+ bp_addr = addr;
+ }
+ auto bp_data = data.drop_front(bp_addr - addr);
+ std::copy_n(saved_opcodes.begin(),
+ std::min(saved_opcodes.size(), bp_data.size()),
+ bp_data.begin());
+ }
+ return Status();
}
lldb::StateType NativeProcessProtocol::GetState() const {
diff --git a/source/Host/common/NativeRegisterContext.cpp b/source/Host/common/NativeRegisterContext.cpp
index 49b8284da970..6e6632aa710f 100644
--- a/source/Host/common/NativeRegisterContext.cpp
+++ b/source/Host/common/NativeRegisterContext.cpp
@@ -9,8 +9,8 @@
#include "lldb/Host/common/NativeRegisterContext.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
diff --git a/source/Host/common/NativeThreadProtocol.cpp b/source/Host/common/NativeThreadProtocol.cpp
index 0c648e40eb5c..af43683295b0 100644
--- a/source/Host/common/NativeThreadProtocol.cpp
+++ b/source/Host/common/NativeThreadProtocol.cpp
@@ -11,7 +11,6 @@
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeRegisterContext.h"
-#include "lldb/Host/common/SoftwareBreakpoint.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Host/common/ProcessRunLock.cpp b/source/Host/common/ProcessRunLock.cpp
index 48dcd62bb939..e0ba2ecfd3e9 100644
--- a/source/Host/common/ProcessRunLock.cpp
+++ b/source/Host/common/ProcessRunLock.cpp
@@ -30,7 +30,7 @@ ProcessRunLock::~ProcessRunLock() {
bool ProcessRunLock::ReadTryLock() {
::pthread_rwlock_rdlock(&m_rwlock);
- if (m_running == false) {
+ if (!m_running) {
return true;
}
::pthread_rwlock_unlock(&m_rwlock);
diff --git a/source/Host/common/PseudoTerminal.cpp b/source/Host/common/PseudoTerminal.cpp
index c9b290078e18..08d4fa218968 100644
--- a/source/Host/common/PseudoTerminal.cpp
+++ b/source/Host/common/PseudoTerminal.cpp
@@ -10,7 +10,8 @@
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/Config.h"
-#include <errno.h>
+#include "llvm/Support/Errno.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -27,6 +28,14 @@ int posix_openpt(int flags);
using namespace lldb_private;
//----------------------------------------------------------------------
+// Write string describing error number
+//----------------------------------------------------------------------
+static void ErrnoToStr(char *error_str, size_t error_len) {
+ std::string strerror = llvm::sys::StrError();
+ ::snprintf(error_str, error_len, "%s", strerror.c_str());
+}
+
+//----------------------------------------------------------------------
// PseudoTerminal constructor
//----------------------------------------------------------------------
PseudoTerminal::PseudoTerminal()
@@ -88,14 +97,14 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
m_master_fd = ::posix_openpt(oflag);
if (m_master_fd < 0) {
if (error_str)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
return false;
}
// Grant access to the slave pseudo terminal
if (::grantpt(m_master_fd) < 0) {
if (error_str)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
CloseMasterFileDescriptor();
return false;
}
@@ -103,7 +112,7 @@ bool PseudoTerminal::OpenFirstAvailableMaster(int oflag, char *error_str,
// Clear the lock flag on the slave pseudo terminal
if (::unlockpt(m_master_fd) < 0) {
if (error_str)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
CloseMasterFileDescriptor();
return false;
}
@@ -143,7 +152,7 @@ bool PseudoTerminal::OpenSlave(int oflag, char *error_str, size_t error_len) {
if (m_slave_fd < 0) {
if (error_str)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
return false;
}
@@ -175,7 +184,7 @@ const char *PseudoTerminal::GetSlaveName(char *error_str,
const char *slave_name = ::ptsname(m_master_fd);
if (error_str && slave_name == nullptr)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
return slave_name;
}
@@ -213,7 +222,7 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
if (pid < 0) {
// Fork failed
if (error_str)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
} else if (pid == 0) {
// Child Process
::setsid();
@@ -229,23 +238,23 @@ lldb::pid_t PseudoTerminal::Fork(char *error_str, size_t error_len) {
// Acquire the controlling terminal
if (::ioctl(m_slave_fd, TIOCSCTTY, (char *)0) < 0) {
if (error_str)
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
}
#endif
// Duplicate all stdio file descriptors to the slave pseudo terminal
if (::dup2(m_slave_fd, STDIN_FILENO) != STDIN_FILENO) {
if (error_str && !error_str[0])
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
}
if (::dup2(m_slave_fd, STDOUT_FILENO) != STDOUT_FILENO) {
if (error_str && !error_str[0])
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
}
if (::dup2(m_slave_fd, STDERR_FILENO) != STDERR_FILENO) {
if (error_str && !error_str[0])
- ::strerror_r(errno, error_str, error_len);
+ ErrnoToStr(error_str, error_len);
}
}
} else {
diff --git a/source/Host/common/SocketAddress.cpp b/source/Host/common/SocketAddress.cpp
index def3e0359f01..172cb06a5819 100644
--- a/source/Host/common/SocketAddress.cpp
+++ b/source/Host/common/SocketAddress.cpp
@@ -21,7 +21,6 @@
#include <stddef.h>
#include <stdio.h>
-// C Includes
#if !defined(_WIN32)
#include <arpa/inet.h>
#endif
@@ -29,9 +28,6 @@
#include <assert.h>
#include <string.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/PosixApi.h"
// WindowsXP needs an inet_ntop implementation
diff --git a/source/Host/common/SoftwareBreakpoint.cpp b/source/Host/common/SoftwareBreakpoint.cpp
deleted file mode 100644
index 353dadf6ce6d..000000000000
--- a/source/Host/common/SoftwareBreakpoint.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-//===-- SoftwareBreakpoint.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Host/common/SoftwareBreakpoint.h"
-
-#include "lldb/Host/Debug.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Status.h"
-
-#include "lldb/Host/common/NativeProcessProtocol.h"
-
-using namespace lldb_private;
-
-// ------------------------------------------------------------------- static
-// members -------------------------------------------------------------------
-
-Status SoftwareBreakpoint::CreateSoftwareBreakpoint(
- NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint,
- NativeBreakpointSP &breakpoint_sp) {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
-
- // Validate the address.
- if (addr == LLDB_INVALID_ADDRESS)
- return Status("SoftwareBreakpoint::%s invalid load address specified.",
- __FUNCTION__);
-
- // Ask the NativeProcessProtocol subclass to fill in the correct software
- // breakpoint trap for the breakpoint site.
- size_t bp_opcode_size = 0;
- const uint8_t *bp_opcode_bytes = NULL;
- Status error = process.GetSoftwareBreakpointTrapOpcode(
- size_hint, bp_opcode_size, bp_opcode_bytes);
-
- if (error.Fail()) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to retrieve software "
- "breakpoint trap opcode: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
-
- // Validate size of trap opcode.
- if (bp_opcode_size == 0) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to retrieve any trap opcodes",
- __FUNCTION__);
- return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() "
- "returned zero, unable to get breakpoint trap for address "
- "0x%" PRIx64,
- addr);
- }
-
- if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s cannot support %zu trapcode bytes, "
- "max size is %zu",
- __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
- return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() "
- "returned too many trap opcode bytes: requires %zu but we "
- "only support a max of %zu",
- bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
- }
-
- // Validate that we received opcodes.
- if (!bp_opcode_bytes) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes",
- __FUNCTION__);
- return Status("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() "
- "returned NULL trap opcode bytes, unable to get breakpoint "
- "trap for address 0x%" PRIx64,
- addr);
- }
-
- // Enable the breakpoint.
- uint8_t saved_opcode_bytes[MAX_TRAP_OPCODE_SIZE];
- error = EnableSoftwareBreakpoint(process, addr, bp_opcode_size,
- bp_opcode_bytes, saved_opcode_bytes);
- if (error.Fail()) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s: failed to enable new breakpoint at "
- "0x%" PRIx64 ": %s",
- __FUNCTION__, addr, error.AsCString());
- return error;
- }
-
- if (log)
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS",
- __FUNCTION__, addr);
-
- // Set the breakpoint and verified it was written properly. Now create a
- // breakpoint remover that understands how to undo this breakpoint.
- breakpoint_sp.reset(new SoftwareBreakpoint(process, addr, saved_opcode_bytes,
- bp_opcode_bytes, bp_opcode_size));
- return Status();
-}
-
-Status SoftwareBreakpoint::EnableSoftwareBreakpoint(
- NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size,
- const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes) {
- assert(bp_opcode_size <= MAX_TRAP_OPCODE_SIZE &&
- "bp_opcode_size out of valid range");
- assert(bp_opcode_bytes && "bp_opcode_bytes is NULL");
- assert(saved_opcode_bytes && "saved_opcode_bytes is NULL");
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
-
- // Save the original opcodes by reading them so we can restore later.
- size_t bytes_read = 0;
-
- Status error =
- process.ReadMemory(addr, saved_opcode_bytes, bp_opcode_size, bytes_read);
- if (error.Fail()) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to read memory while "
- "attempting to set breakpoint: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
-
- // Ensure we read as many bytes as we expected.
- if (bytes_read != bp_opcode_size) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to read memory while "
- "attempting to set breakpoint: attempted to read %zu bytes "
- "but only read %zu",
- __FUNCTION__, bp_opcode_size, bytes_read);
- return Status("SoftwareBreakpoint::%s failed to read memory while "
- "attempting to set breakpoint: attempted to read %zu bytes "
- "but only read %zu",
- __FUNCTION__, bp_opcode_size, bytes_read);
- }
-
- // Log what we read.
- if (log) {
- int i = 0;
- for (const uint8_t *read_byte = saved_opcode_bytes;
- read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) {
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64
- " ovewriting byte index %d (was 0x%hhx)",
- __FUNCTION__, addr, i++, *read_byte);
- }
- }
-
- // Write a software breakpoint in place of the original opcode.
- size_t bytes_written = 0;
- error =
- process.WriteMemory(addr, bp_opcode_bytes, bp_opcode_size, bytes_written);
- if (error.Fail()) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to write memory while "
- "attempting to set breakpoint: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
-
- // Ensure we wrote as many bytes as we expected.
- if (bytes_written != bp_opcode_size) {
- error.SetErrorStringWithFormat(
- "SoftwareBreakpoint::%s failed write memory while attempting to set "
- "breakpoint: attempted to write %zu bytes but only wrote %zu",
- __FUNCTION__, bp_opcode_size, bytes_written);
- if (log)
- log->PutCString(error.AsCString());
- return error;
- }
-
- uint8_t verify_bp_opcode_bytes[MAX_TRAP_OPCODE_SIZE];
- size_t verify_bytes_read = 0;
- error = process.ReadMemory(addr, verify_bp_opcode_bytes, bp_opcode_size,
- verify_bytes_read);
- if (error.Fail()) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to read memory while "
- "attempting to verify the breakpoint set: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
-
- // Ensure we read as many verification bytes as we expected.
- if (verify_bytes_read != bp_opcode_size) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s failed to read memory while "
- "attempting to verify breakpoint: attempted to read %zu "
- "bytes but only read %zu",
- __FUNCTION__, bp_opcode_size, verify_bytes_read);
- return Status(
- "SoftwareBreakpoint::%s failed to read memory while "
- "attempting to verify breakpoint: attempted to read %zu bytes "
- "but only read %zu",
- __FUNCTION__, bp_opcode_size, verify_bytes_read);
- }
-
- if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0) {
- if (log)
- log->Printf("SoftwareBreakpoint::%s: verification of software breakpoint "
- "writing failed - trap opcodes not successfully read back "
- "after writing when setting breakpoint at 0x%" PRIx64,
- __FUNCTION__, addr);
- return Status("SoftwareBreakpoint::%s: verification of software breakpoint "
- "writing failed - trap opcodes not successfully read back "
- "after writing when setting breakpoint at 0x%" PRIx64,
- __FUNCTION__, addr);
- }
-
- if (log)
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS",
- __FUNCTION__, addr);
-
- return Status();
-}
-
-// -------------------------------------------------------------------
-// instance-level members
-// -------------------------------------------------------------------
-
-SoftwareBreakpoint::SoftwareBreakpoint(NativeProcessProtocol &process,
- lldb::addr_t addr,
- const uint8_t *saved_opcodes,
- const uint8_t *trap_opcodes,
- size_t opcode_size)
- : NativeBreakpoint(addr), m_process(process), m_saved_opcodes(),
- m_trap_opcodes(), m_opcode_size(opcode_size) {
- assert(opcode_size > 0 && "setting software breakpoint with no trap opcodes");
- assert(opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large");
-
- ::memcpy(m_saved_opcodes, saved_opcodes, opcode_size);
- ::memcpy(m_trap_opcodes, trap_opcodes, opcode_size);
-}
-
-Status SoftwareBreakpoint::DoEnable() {
- return EnableSoftwareBreakpoint(m_process, m_addr, m_opcode_size,
- m_trap_opcodes, m_saved_opcodes);
-}
-
-Status SoftwareBreakpoint::DoDisable() {
- Status error;
- assert(m_addr && (m_addr != LLDB_INVALID_ADDRESS) &&
- "can't remove a software breakpoint for an invalid address");
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__,
- m_addr);
-
- assert((m_opcode_size > 0) &&
- "cannot restore opcodes when there are no opcodes");
-
- if (m_opcode_size > 0) {
- // Clear a software breakpoint instruction
- uint8_t curr_break_op[MAX_TRAP_OPCODE_SIZE];
- bool break_op_found = false;
- assert(m_opcode_size <= sizeof(curr_break_op));
-
- // Read the breakpoint opcode
- size_t bytes_read = 0;
- error =
- m_process.ReadMemory(m_addr, curr_break_op, m_opcode_size, bytes_read);
- if (error.Success() && bytes_read < m_opcode_size) {
- error.SetErrorStringWithFormat(
- "SoftwareBreakpointr::%s addr=0x%" PRIx64
- ": tried to read %zu bytes but only read %zu",
- __FUNCTION__, m_addr, m_opcode_size, bytes_read);
- }
- if (error.Success()) {
- bool verify = false;
- // Make sure the breakpoint opcode exists at this address
- if (::memcmp(curr_break_op, m_trap_opcodes, m_opcode_size) == 0) {
- break_op_found = true;
- // We found a valid breakpoint opcode at this address, now restore the
- // saved opcode.
- size_t bytes_written = 0;
- error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size,
- bytes_written);
- if (error.Success() && bytes_written < m_opcode_size) {
- error.SetErrorStringWithFormat(
- "SoftwareBreakpoint::%s addr=0x%" PRIx64
- ": tried to write %zu bytes but only wrote %zu",
- __FUNCTION__, m_addr, m_opcode_size, bytes_written);
- }
- if (error.Success()) {
- verify = true;
- }
- } else {
- error.SetErrorString(
- "Original breakpoint trap is no longer in memory.");
- // Set verify to true and so we can check if the original opcode has
- // already been restored
- verify = true;
- }
-
- if (verify) {
- uint8_t verify_opcode[MAX_TRAP_OPCODE_SIZE];
- assert(m_opcode_size <= sizeof(verify_opcode));
- // Verify that our original opcode made it back to the inferior
-
- size_t verify_bytes_read = 0;
- error = m_process.ReadMemory(m_addr, verify_opcode, m_opcode_size,
- verify_bytes_read);
- if (error.Success() && verify_bytes_read < m_opcode_size) {
- error.SetErrorStringWithFormat(
- "SoftwareBreakpoint::%s addr=0x%" PRIx64
- ": tried to read %zu verification bytes but only read %zu",
- __FUNCTION__, m_addr, m_opcode_size, verify_bytes_read);
- }
- if (error.Success()) {
- // compare the memory we just read with the original opcode
- if (::memcmp(m_saved_opcodes, verify_opcode, m_opcode_size) == 0) {
- // SUCCESS
- if (log) {
- int i = 0;
- for (const uint8_t *verify_byte = verify_opcode;
- verify_byte < verify_opcode + m_opcode_size; ++verify_byte) {
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64
- " replaced byte index %d with 0x%hhx",
- __FUNCTION__, m_addr, i++, *verify_byte);
- }
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64
- " -- SUCCESS",
- __FUNCTION__, m_addr);
- }
- return error;
- } else {
- if (break_op_found)
- error.SetErrorString("Failed to restore original opcode.");
- }
- } else
- error.SetErrorString("Failed to read memory to verify that "
- "breakpoint trap was restored.");
- }
- }
- }
-
- if (log && error.Fail())
- log->Printf("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s",
- __FUNCTION__, m_addr, error.AsCString());
- return error;
-}
-
-bool SoftwareBreakpoint::IsSoftwareBreakpoint() const { return true; }
diff --git a/source/Host/common/StringConvert.cpp b/source/Host/common/StringConvert.cpp
index b4171437b7e2..8f4e1956fc28 100644
--- a/source/Host/common/StringConvert.cpp
+++ b/source/Host/common/StringConvert.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdlib.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/StringConvert.h"
namespace lldb_private {
diff --git a/source/Host/common/Symbols.cpp b/source/Host/common/Symbols.cpp
index d7e0c13112aa..ed1677cbcb58 100644
--- a/source/Host/common/Symbols.cpp
+++ b/source/Host/common/Symbols.cpp
@@ -16,7 +16,6 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
@@ -29,7 +28,6 @@ typedef int cpu_subtype_t;
using namespace lldb;
using namespace lldb_private;
-using namespace llvm::MachO;
#if defined(__APPLE__)
@@ -67,96 +65,133 @@ static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec,
return false;
}
+// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid,
+// return true if there is a matching dSYM bundle next to the exec_fspec,
+// and return that value in dsym_fspec.
+// If there is a .dSYM.yaa compressed archive next to the exec_fspec,
+// call through Symbols::DownloadObjectAndSymbolFile to download the
+// expanded/uncompressed dSYM and return that filepath in dsym_fspec.
+
+static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec,
+ const FileSpec &exec_fspec,
+ FileSpec &dsym_fspec) {
+ ConstString filename = exec_fspec.GetFilename();
+ FileSpec dsym_directory = exec_fspec;
+ dsym_directory.RemoveLastPathComponent();
+
+ std::string dsym_filename = filename.AsCString();
+ dsym_filename += ".dSYM";
+ dsym_directory.AppendPathComponent(dsym_filename);
+ dsym_directory.AppendPathComponent("Contents");
+ dsym_directory.AppendPathComponent("Resources");
+ dsym_directory.AppendPathComponent("DWARF");
+
+ if (FileSystem::Instance().Exists(dsym_directory)) {
+
+ // See if the binary name exists in the dSYM DWARF
+ // subdir.
+ dsym_fspec = dsym_directory;
+ dsym_fspec.AppendPathComponent(filename.AsCString());
+ if (FileSystem::Instance().Exists(dsym_fspec) &&
+ FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(),
+ mod_spec.GetUUIDPtr())) {
+ return true;
+ }
+
+ // See if we have "../CF.framework" - so we'll look for
+ // CF.framework.dSYM/Contents/Resources/DWARF/CF
+ // We need to drop the last suffix after '.' to match
+ // 'CF' in the DWARF subdir.
+ std::string binary_name (filename.AsCString());
+ auto last_dot = binary_name.find_last_of('.');
+ if (last_dot != std::string::npos) {
+ binary_name.erase(last_dot);
+ dsym_fspec = dsym_directory;
+ dsym_fspec.AppendPathComponent(binary_name);
+ if (FileSystem::Instance().Exists(dsym_fspec) &&
+ FileAtPathContainsArchAndUUID(dsym_fspec,
+ mod_spec.GetArchitecturePtr(),
+ mod_spec.GetUUIDPtr())) {
+ return true;
+ }
+ }
+ }
+
+ // See if we have a .dSYM.yaa next to this executable path.
+ FileSpec dsym_yaa_fspec = exec_fspec;
+ dsym_yaa_fspec.RemoveLastPathComponent();
+ std::string dsym_yaa_filename = filename.AsCString();
+ dsym_yaa_filename += ".dSYM.yaa";
+ dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename);
+
+ if (FileSystem::Instance().Exists(dsym_yaa_fspec)) {
+ ModuleSpec mutable_mod_spec = mod_spec;
+ if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, true) &&
+ FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) {
+ dsym_fspec = mutable_mod_spec.GetSymbolFileSpec();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Given a ModuleSpec with a FileSpec and optionally uuid/architecture
+// filled in, look for a .dSYM bundle next to that binary. Returns true
+// if a .dSYM bundle is found, and that path is returned in the dsym_fspec
+// FileSpec.
+//
+// This routine looks a few directory layers above the given exec_path -
+// exec_path might be /System/Library/Frameworks/CF.framework/CF and the
+// dSYM might be /System/Library/Frameworks/CF.framework.dSYM.
+//
+// If there is a .dSYM.yaa compressed archive found next to the binary,
+// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM
+
static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
FileSpec &dsym_fspec) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
+ const FileSpec &exec_fspec = module_spec.GetFileSpec();
if (exec_fspec) {
- char path[PATH_MAX];
- if (exec_fspec->GetPath(path, sizeof(path))) {
- // Make sure the module isn't already just a dSYM file...
- if (strcasestr(path, ".dSYM/Contents/Resources/DWARF") == NULL) {
+ if (::LookForDsymNextToExecutablePath (module_spec, exec_fspec, dsym_fspec)) {
if (log) {
- if (module_spec.GetUUIDPtr() && module_spec.GetUUIDPtr()->IsValid()) {
- log->Printf(
- "Searching for dSYM bundle next to executable %s, UUID %s",
- path, module_spec.GetUUIDPtr()->GetAsString().c_str());
- } else {
- log->Printf("Searching for dSYM bundle next to executable %s",
- path);
- }
+ log->Printf("dSYM with matching UUID & arch found at %s", dsym_fspec.GetPath().c_str());
}
- ::strncat(path, ".dSYM/Contents/Resources/DWARF/",
- sizeof(path) - strlen(path) - 1);
- ::strncat(path, exec_fspec->GetFilename().AsCString(),
- sizeof(path) - strlen(path) - 1);
-
- dsym_fspec.SetFile(path, false, FileSpec::Style::native);
-
- ModuleSpecList module_specs;
- ModuleSpec matched_module_spec;
- if (dsym_fspec.Exists() &&
- FileAtPathContainsArchAndUUID(dsym_fspec,
- module_spec.GetArchitecturePtr(),
- module_spec.GetUUIDPtr())) {
- if (log) {
- log->Printf("dSYM with matching UUID & arch found at %s", path);
- }
- return true;
- } else {
- FileSpec parent_dirs = exec_fspec;
-
- // Remove the binary name from the FileSpec
- parent_dirs.RemoveLastPathComponent();
-
- // Add a ".dSYM" name to each directory component of the path,
- // stripping off components. e.g. we may have a binary like
- // /S/L/F/Foundation.framework/Versions/A/Foundation and
- // /S/L/F/Foundation.framework.dSYM
- //
- // so we'll need to start with
- // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the
- // "A", and if that doesn't exist, strip off the "A" and try it again
- // with "Versions", etc., until we find a dSYM bundle or we've
- // stripped off enough path components that there's no need to
- // continue.
-
- for (int i = 0; i < 4; i++) {
- // Does this part of the path have a "." character - could it be a
- // bundle's top level directory?
- const char *fn = parent_dirs.GetFilename().AsCString();
- if (fn == nullptr)
- break;
- if (::strchr(fn, '.') != nullptr) {
- dsym_fspec = parent_dirs;
- dsym_fspec.RemoveLastPathComponent();
-
- // If the current directory name is "Foundation.framework", see
- // if
- // "Foundation.framework.dSYM/Contents/Resources/DWARF/Foundation"
- // exists & has the right uuid.
- std::string dsym_fn = fn;
- dsym_fn += ".dSYM";
- dsym_fspec.AppendPathComponent(dsym_fn.c_str());
- dsym_fspec.AppendPathComponent("Contents");
- dsym_fspec.AppendPathComponent("Resources");
- dsym_fspec.AppendPathComponent("DWARF");
- dsym_fspec.AppendPathComponent(
- exec_fspec->GetFilename().AsCString());
- if (dsym_fspec.Exists() &&
- FileAtPathContainsArchAndUUID(
- dsym_fspec, module_spec.GetArchitecturePtr(),
- module_spec.GetUUIDPtr())) {
- if (log) {
- log->Printf("dSYM with matching UUID & arch found at %s",
- dsym_fspec.GetPath().c_str());
- }
- return true;
- }
+ return true;
+ } else {
+ FileSpec parent_dirs = exec_fspec;
+
+ // Remove the binary name from the FileSpec
+ parent_dirs.RemoveLastPathComponent();
+
+ // Add a ".dSYM" name to each directory component of the path,
+ // stripping off components. e.g. we may have a binary like
+ // /S/L/F/Foundation.framework/Versions/A/Foundation and
+ // /S/L/F/Foundation.framework.dSYM
+ //
+ // so we'll need to start with
+ // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the
+ // "A", and if that doesn't exist, strip off the "A" and try it again
+ // with "Versions", etc., until we find a dSYM bundle or we've
+ // stripped off enough path components that there's no need to
+ // continue.
+
+ for (int i = 0; i < 4; i++) {
+ // Does this part of the path have a "." character - could it be a
+ // bundle's top level directory?
+ const char *fn = parent_dirs.GetFilename().AsCString();
+ if (fn == nullptr)
+ break;
+ if (::strchr(fn, '.') != nullptr) {
+ if (::LookForDsymNextToExecutablePath (module_spec, parent_dirs, dsym_fspec)) {
+ if (log) {
+ log->Printf("dSYM with matching UUID & arch found at %s",
+ dsym_fspec.GetPath().c_str());
}
- parent_dirs.RemoveLastPathComponent();
+ return true;
}
}
+ parent_dirs.RemoveLastPathComponent();
}
}
}
@@ -164,7 +199,7 @@ static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
return false;
}
-FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
+static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
const FileSpec *exec_fspec = module_spec.GetFileSpecPtr();
const ArchSpec *arch = module_spec.GetArchitecturePtr();
const UUID *uuid = module_spec.GetUUIDPtr();
@@ -180,7 +215,7 @@ FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) {
ModuleSpec dsym_module_spec;
// First try and find the dSYM in the same directory as the executable or in
// an appropriate parent directory
- if (LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec) == false) {
+ if (!LocateDSYMInVincinityOfExecutable(module_spec, symbol_fspec)) {
// We failed to easily find the dSYM above, so use DebugSymbols
LocateMacOSXFilesUsingDebugSymbols(module_spec, dsym_module_spec);
} else {
@@ -212,9 +247,12 @@ ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
return result;
}
+// Keep "symbols.enable-external-lookup" description in sync with this function.
+
FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
FileSpec symbol_file_spec = module_spec.GetSymbolFileSpec();
- if (symbol_file_spec.IsAbsolute() && symbol_file_spec.Exists())
+ if (symbol_file_spec.IsAbsolute() &&
+ FileSystem::Instance().Exists(symbol_file_spec))
return symbol_file_spec;
const char *symbol_filename = symbol_file_spec.GetFilename().AsCString();
@@ -225,25 +263,42 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
// Add module directory.
FileSpec module_file_spec = module_spec.GetFileSpec();
// We keep the unresolved pathname if it fails.
- FileSystem::ResolveSymbolicLink(module_file_spec, module_file_spec);
+ FileSystem::Instance().ResolveSymbolicLink(module_file_spec, module_file_spec);
const ConstString &file_dir = module_file_spec.GetDirectory();
- debug_file_search_paths.AppendIfUnique(
- FileSpec(file_dir.AsCString("."), true));
+ {
+ FileSpec file_spec(file_dir.AsCString("."));
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
+
+ if (ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
- // Add current working directory.
- debug_file_search_paths.AppendIfUnique(FileSpec(".", true));
+ // Add current working directory.
+ {
+ FileSpec file_spec(".");
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
#ifndef _WIN32
#if defined(__NetBSD__)
- // Add /usr/libdata/debug directory.
- debug_file_search_paths.AppendIfUnique(
- FileSpec("/usr/libdata/debug", true));
+ // Add /usr/libdata/debug directory.
+ {
+ FileSpec file_spec("/usr/libdata/debug");
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
#else
- // Add /usr/lib/debug directory.
- debug_file_search_paths.AppendIfUnique(FileSpec("/usr/lib/debug", true));
+ // Add /usr/lib/debug directory.
+ {
+ FileSpec file_spec("/usr/lib/debug");
+ FileSystem::Instance().Resolve(file_spec);
+ debug_file_search_paths.AppendIfUnique(file_spec);
+ }
#endif
#endif // _WIN32
+ }
std::string uuid_str;
const UUID &module_uuid = module_spec.GetUUID();
@@ -260,8 +315,8 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
size_t num_directories = debug_file_search_paths.GetSize();
for (size_t idx = 0; idx < num_directories; ++idx) {
FileSpec dirspec = debug_file_search_paths.GetFileSpecAtIndex(idx);
- dirspec.ResolvePath();
- if (!llvm::sys::fs::is_directory(dirspec.GetPath()))
+ FileSystem::Instance().Resolve(dirspec);
+ if (!FileSystem::Instance().IsDirectory(dirspec))
continue;
std::vector<std::string> files;
@@ -279,13 +334,14 @@ FileSpec Symbols::LocateExecutableSymbolFile(const ModuleSpec &module_spec) {
const uint32_t num_files = files.size();
for (size_t idx_file = 0; idx_file < num_files; ++idx_file) {
const std::string &filename = files[idx_file];
- FileSpec file_spec(filename, true);
+ FileSpec file_spec(filename);
+ FileSystem::Instance().Resolve(file_spec);
if (llvm::sys::fs::equivalent(file_spec.GetPath(),
module_file_spec.GetPath()))
continue;
- if (file_spec.Exists()) {
+ if (FileSystem::Instance().Exists(file_spec)) {
lldb_private::ModuleSpecList specs;
const size_t num_specs =
ObjectFile::GetModuleSpecifications(file_spec, 0, 0, specs);
diff --git a/source/Host/common/TaskPool.cpp b/source/Host/common/TaskPool.cpp
index c54b9a8ae56b..ba1362a46f33 100644
--- a/source/Host/common/TaskPool.cpp
+++ b/source/Host/common/TaskPool.cpp
@@ -10,9 +10,9 @@
#include "lldb/Host/TaskPool.h"
#include "lldb/Host/ThreadLauncher.h"
-#include <cstdint> // for uint32_t
-#include <queue> // for queue
-#include <thread> // for thread
+#include <cstdint>
+#include <queue>
+#include <thread>
namespace lldb_private {
diff --git a/source/Host/common/XML.cpp b/source/Host/common/XML.cpp
index 7468a3d7ac65..967a294cbf72 100644
--- a/source/Host/common/XML.cpp
+++ b/source/Host/common/XML.cpp
@@ -201,8 +201,7 @@ void XMLNode::ForEachAttribute(AttributeCallback const &callback) const {
llvm::StringRef attr_value;
if (child->content)
attr_value = llvm::StringRef((const char *)child->content);
- if (callback(llvm::StringRef((const char *)attr->name), attr_value) ==
- false)
+ if (!callback(llvm::StringRef((const char *)attr->name), attr_value))
return;
}
}
@@ -217,7 +216,7 @@ void XMLNode::ForEachSiblingNode(NodeCallback const &callback) const {
if (IsValid()) {
// iterate through all siblings
for (xmlNodePtr node = m_node; node; node = node->next) {
- if (callback(XMLNode(node)) == false)
+ if (!callback(XMLNode(node)))
return;
}
}
@@ -234,7 +233,7 @@ void XMLNode::ForEachSiblingElement(NodeCallback const &callback) const {
if (node->type != XML_ELEMENT_NODE)
continue;
- if (callback(XMLNode(node)) == false)
+ if (!callback(XMLNode(node)))
return;
}
}
@@ -263,7 +262,7 @@ void XMLNode::ForEachSiblingElementWithName(
// ignore this one
}
- if (callback(XMLNode(node)) == false)
+ if (!callback(XMLNode(node)))
return;
}
}
@@ -439,7 +438,7 @@ XMLNode ApplePropertyList::GetValueNode(const char *key) const {
"key", [key, &value_node](const XMLNode &key_node) -> bool {
std::string key_name;
if (key_node.GetElementText(key_name)) {
- if (key_name.compare(key) == 0) {
+ if (key_name == key) {
value_node = key_node.GetSibling();
while (value_node && !value_node.IsElement())
value_node = value_node.GetSibling();
diff --git a/source/Host/freebsd/Host.cpp b/source/Host/freebsd/Host.cpp
index 87552bc2a27e..7bf959aee982 100644
--- a/source/Host/freebsd/Host.cpp
+++ b/source/Host/freebsd/Host.cpp
@@ -8,7 +8,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <sys/types.h>
#include <sys/exec.h>
@@ -23,9 +22,6 @@
#include <execinfo.h>
#include <stdio.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
@@ -75,11 +71,9 @@ GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
size_t pathname_len = sizeof(pathname);
mib[2] = KERN_PROC_PATHNAME;
if (::sysctl(mib, 4, pathname, &pathname_len, NULL, 0) == 0)
- process_info.GetExecutableFile().SetFile(pathname, false,
- FileSpec::Style::native);
+ process_info.GetExecutableFile().SetFile(pathname, FileSpec::Style::native);
else
- process_info.GetExecutableFile().SetFile(cstr, false,
- FileSpec::Style::native);
+ process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native);
if (!(match_info_ptr == NULL ||
NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
diff --git a/source/Host/freebsd/HostInfoFreeBSD.cpp b/source/Host/freebsd/HostInfoFreeBSD.cpp
index 18eae3eb7606..d123936b3668 100644
--- a/source/Host/freebsd/HostInfoFreeBSD.cpp
+++ b/source/Host/freebsd/HostInfoFreeBSD.cpp
@@ -69,7 +69,7 @@ FileSpec HostInfoFreeBSD::GetProgramFileSpec() {
if (sysctl(exe_path_mib, 4, NULL, &exe_path_size, NULL, 0) == 0) {
char *exe_path = new char[exe_path_size];
if (sysctl(exe_path_mib, 4, exe_path, &exe_path_size, NULL, 0) == 0)
- g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native);
+ g_program_filespec.SetFile(exe_path, FileSpec::Style::native);
delete[] exe_path;
}
}
diff --git a/source/Host/linux/Host.cpp b/source/Host/linux/Host.cpp
index 1a0eb767eb34..bd596f8cbfe0 100644
--- a/source/Host/linux/Host.cpp
+++ b/source/Host/linux/Host.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
@@ -18,20 +17,17 @@
#include <sys/utsname.h>
#include <unistd.h>
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/Object/ELF.h"
#include "llvm/Support/ScopedPrinter.h"
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/linux/Support.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/DataExtractor.h"
using namespace lldb;
@@ -125,7 +121,7 @@ static bool IsDirNumeric(const char *dname) {
static ArchSpec GetELFProcessCPUType(llvm::StringRef exe_path) {
Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
- auto buffer_sp = DataBufferLLVM::CreateSliceFromPath(exe_path, 0x20, 0);
+ auto buffer_sp = FileSystem::Instance().CreateDataBuffer(exe_path, 0x20, 0);
if (!buffer_sp)
return ArchSpec();
@@ -190,8 +186,7 @@ static bool GetProcessAndStatInfo(::pid_t pid,
return false;
process_info.SetProcessID(pid);
- process_info.GetExecutableFile().SetFile(PathRef, false,
- FileSpec::Style::native);
+ process_info.GetExecutableFile().SetFile(PathRef, FileSpec::Style::native);
llvm::StringRef Rest = Environ->getBuffer();
while (!Rest.empty()) {
diff --git a/source/Host/linux/HostInfoLinux.cpp b/source/Host/linux/HostInfoLinux.cpp
index 1d95010e2f73..f5a6b2c97a0d 100644
--- a/source/Host/linux/HostInfoLinux.cpp
+++ b/source/Host/linux/HostInfoLinux.cpp
@@ -7,8 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Host/Config.h"
#include "lldb/Host/linux/HostInfoLinux.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/Log.h"
#include "llvm/Support/Threading.h"
@@ -20,7 +21,7 @@
#include <unistd.h>
#include <algorithm>
-#include <mutex> // std::once
+#include <mutex>
using namespace lldb_private;
@@ -170,7 +171,7 @@ FileSpec HostInfoLinux::GetProgramFileSpec() {
ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path) - 1);
if (len > 0) {
exe_path[len] = 0;
- g_program_filespec.SetFile(exe_path, false, FileSpec::Style::native);
+ g_program_filespec.SetFile(exe_path, FileSpec::Style::native);
}
}
@@ -179,14 +180,15 @@ FileSpec HostInfoLinux::GetProgramFileSpec() {
bool HostInfoLinux::ComputeSupportExeDirectory(FileSpec &file_spec) {
if (HostInfoPosix::ComputeSupportExeDirectory(file_spec) &&
- file_spec.IsAbsolute() && file_spec.Exists())
+ file_spec.IsAbsolute() && FileSystem::Instance().Exists(file_spec))
return true;
file_spec.GetDirectory() = GetProgramFileSpec().GetDirectory();
return !file_spec.GetDirectory().IsEmpty();
}
bool HostInfoLinux::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
- FileSpec temp_file("/usr/lib" LLDB_LIBDIR_SUFFIX "/lldb/plugins", true);
+ FileSpec temp_file("/usr/lib" LLDB_LIBDIR_SUFFIX "/lldb/plugins");
+ FileSystem::Instance().Resolve(temp_file);
file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
return true;
}
diff --git a/source/Host/macosx/Symbols.cpp b/source/Host/macosx/Symbols.cpp
index b01c48e51d90..980bbc34449c 100644
--- a/source/Host/macosx/Symbols.cpp
+++ b/source/Host/macosx/Symbols.cpp
@@ -9,16 +9,11 @@
#include "lldb/Host/Symbols.h"
-// C Includes
-#include "lldb/Utility/SafeMachO.h"
#include <dirent.h>
#include <pwd.h>
-// C++ Includes
-// Other libraries and framework includes
#include <CoreFoundation/CoreFoundation.h>
-// Project includes
#include "Host/macosx/cfcpp/CFCBundle.h"
#include "Host/macosx/cfcpp/CFCData.h"
#include "Host/macosx/cfcpp/CFCReleaser.h"
@@ -42,7 +37,6 @@
using namespace lldb;
using namespace lldb_private;
-using namespace llvm::MachO;
#if !defined(__arm__) && !defined(__arm64__) && \
!defined(__aarch64__) // No DebugSymbols on the iOS devices
@@ -107,9 +101,11 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
"UUID %s -- looking for the dSYM",
path, uuid->GetAsString().c_str());
}
- FileSpec dsym_filespec(path, path[0] == '~');
+ FileSpec dsym_filespec(path);
+ if (path[0] == '~')
+ FileSystem::Instance().Resolve(dsym_filespec);
- if (llvm::sys::fs::is_directory(dsym_filespec.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(dsym_filespec)) {
dsym_filespec =
Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch);
++items_found;
@@ -148,8 +144,10 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
path, uuid->GetAsString().c_str());
}
++items_found;
- FileSpec exec_filespec(path, path[0] == '~');
- if (exec_filespec.Exists()) {
+ FileSpec exec_filespec(path);
+ if (path[0] == '~')
+ FileSystem::Instance().Resolve(exec_filespec);
+ if (FileSystem::Instance().Exists(exec_filespec)) {
success = true;
return_module_spec.GetFileSpec() = exec_filespec;
}
@@ -169,7 +167,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
"bundle with name with name %s",
path);
}
- FileSpec file_spec(path, true);
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
ModuleSpecList module_specs;
ModuleSpec matched_module_spec;
using namespace llvm::sys::fs;
@@ -184,7 +183,8 @@ int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
if (::CFURLGetFileSystemRepresentation(bundle_exe_url.get(),
true, (UInt8 *)path,
sizeof(path) - 1)) {
- FileSpec bundle_exe_file_spec(path, true);
+ FileSpec bundle_exe_file_spec(path);
+ FileSystem::Instance().Resolve(bundle_exe_file_spec);
if (ObjectFile::GetModuleSpecifications(
bundle_exe_file_spec, 0, 0, module_specs) &&
module_specs.FindMatchingModuleSpec(
@@ -309,8 +309,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
(CFDictionaryRef)uuid_dict, CFSTR("DBGSymbolRichExecutable"));
if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
if (CFCString::FileSystemRepresentation(cf_str, str)) {
- module_spec.GetFileSpec().SetFile(str.c_str(), true,
- FileSpec::Style::native);
+ module_spec.GetFileSpec().SetFile(str.c_str(), FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
if (log) {
log->Printf(
"From dsymForUUID plist: Symbol rich executable is at '%s'",
@@ -323,8 +323,9 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
CFSTR("DBGDSYMPath"));
if (cf_str && CFGetTypeID(cf_str) == CFStringGetTypeID()) {
if (CFCString::FileSystemRepresentation(cf_str, str)) {
- module_spec.GetSymbolFileSpec().SetFile(str.c_str(), true,
+ module_spec.GetSymbolFileSpec().SetFile(str.c_str(),
FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
success = true;
if (log) {
log->Printf("From dsymForUUID plist: dSYM is at '%s'", str.c_str());
@@ -398,12 +399,13 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
// DBGSourcePath values (the "values" half of key-value path pairs)
// were wrong. Ignore them and use the universal DBGSourcePath
// string from earlier.
- if (new_style_source_remapping_dictionary == true &&
+ if (new_style_source_remapping_dictionary &&
!original_DBGSourcePath_value.empty()) {
DBGSourcePath = original_DBGSourcePath_value;
}
if (DBGSourcePath[0] == '~') {
- FileSpec resolved_source_path(DBGSourcePath.c_str(), true);
+ FileSpec resolved_source_path(DBGSourcePath.c_str());
+ FileSystem::Instance().Resolve(resolved_source_path);
DBGSourcePath = resolved_source_path.GetPath();
}
// With version 2 of DBGSourcePathRemapping, we can chop off the
@@ -414,8 +416,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
ConstString(DBGBuildSourcePath.c_str()),
ConstString(DBGSourcePath.c_str()), true);
if (do_truncate_remapping_names) {
- FileSpec build_path(DBGBuildSourcePath.c_str(), false);
- FileSpec source_path(DBGSourcePath.c_str(), false);
+ FileSpec build_path(DBGBuildSourcePath.c_str());
+ FileSpec source_path(DBGSourcePath.c_str());
build_path.RemoveLastPathComponent();
build_path.RemoveLastPathComponent();
source_path.RemoveLastPathComponent();
@@ -451,7 +453,8 @@ static bool GetModuleSpecInfoFromUUIDDictionary(CFDictionaryRef uuid_dict,
if (!DBGBuildSourcePath.empty() && !DBGSourcePath.empty()) {
if (DBGSourcePath[0] == '~') {
- FileSpec resolved_source_path(DBGSourcePath.c_str(), true);
+ FileSpec resolved_source_path(DBGSourcePath.c_str());
+ FileSystem::Instance().Resolve(resolved_source_path);
DBGSourcePath = resolved_source_path.GetPath();
}
module_spec.GetSourceMappingList().Append(
@@ -472,7 +475,7 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
// it once per lldb run and cache the result.
static bool g_have_checked_for_dbgshell_command = false;
static const char *g_dbgshell_command = NULL;
- if (g_have_checked_for_dbgshell_command == false) {
+ if (!g_have_checked_for_dbgshell_command) {
g_have_checked_for_dbgshell_command = true;
CFTypeRef defaults_setting = CFPreferencesCopyAppValue(
CFSTR("DBGShellCommands"), CFSTR("com.apple.DebugSymbols"));
@@ -492,11 +495,12 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
// When g_dbgshell_command is NULL, the user has not enabled the use of an
// external program to find the symbols, don't run it for them.
- if (force_lookup == false && g_dbgshell_command == NULL) {
+ if (!force_lookup && g_dbgshell_command == NULL) {
return false;
}
- if (uuid_ptr || (file_spec_ptr && file_spec_ptr->Exists())) {
+ if (uuid_ptr ||
+ (file_spec_ptr && FileSystem::Instance().Exists(*file_spec_ptr))) {
static bool g_located_dsym_for_uuid_exe = false;
static bool g_dsym_for_uuid_exe_exists = false;
static char g_dsym_for_uuid_exe_path[PATH_MAX];
@@ -506,15 +510,18 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
getenv("LLDB_APPLE_DSYMFORUUID_EXECUTABLE");
FileSpec dsym_for_uuid_exe_spec;
if (dsym_for_uuid_exe_path_cstr) {
- dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr, true,
+ dsym_for_uuid_exe_spec.SetFile(dsym_for_uuid_exe_path_cstr,
FileSpec::Style::native);
- g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec);
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
}
if (!g_dsym_for_uuid_exe_exists) {
- dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID", false,
+ dsym_for_uuid_exe_spec.SetFile("/usr/local/bin/dsymForUUID",
FileSpec::Style::native);
- g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
if (!g_dsym_for_uuid_exe_exists) {
long bufsize;
if ((bufsize = sysconf(_SC_GETPW_R_SIZE_MAX)) != -1) {
@@ -527,17 +534,20 @@ bool Symbols::DownloadObjectAndSymbolFile(ModuleSpec &module_spec,
tilde_rc && tilde_rc->pw_dir) {
std::string dsymforuuid_path(tilde_rc->pw_dir);
dsymforuuid_path += "/bin/dsymForUUID";
- dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(), false,
+ dsym_for_uuid_exe_spec.SetFile(dsymforuuid_path.c_str(),
FileSpec::Style::native);
- g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
}
}
}
}
if (!g_dsym_for_uuid_exe_exists && g_dbgshell_command != NULL) {
- dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command, true,
+ dsym_for_uuid_exe_spec.SetFile(g_dbgshell_command,
FileSpec::Style::native);
- g_dsym_for_uuid_exe_exists = dsym_for_uuid_exe_spec.Exists();
+ FileSystem::Instance().Resolve(dsym_for_uuid_exe_spec);
+ g_dsym_for_uuid_exe_exists =
+ FileSystem::Instance().Exists(dsym_for_uuid_exe_spec);
}
if (g_dsym_for_uuid_exe_exists)
diff --git a/source/Host/macosx/cfcpp/CFCMutableArray.cpp b/source/Host/macosx/cfcpp/CFCMutableArray.cpp
index 0b6258315eb0..f426e9c13a59 100644
--- a/source/Host/macosx/cfcpp/CFCMutableArray.cpp
+++ b/source/Host/macosx/cfcpp/CFCMutableArray.cpp
@@ -88,7 +88,7 @@ bool CFCMutableArray::SetValueAtIndex(CFIndex idx, const void *value) {
bool CFCMutableArray::AppendValue(const void *value, bool can_create) {
CFMutableArrayRef array = get();
if (array == NULL) {
- if (can_create == false)
+ if (!can_create)
return false;
array =
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
@@ -106,7 +106,7 @@ bool CFCMutableArray::AppendCStringAsCFString(const char *s,
bool can_create) {
CFMutableArrayRef array = get();
if (array == NULL) {
- if (can_create == false)
+ if (!can_create)
return false;
array =
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
@@ -124,7 +124,7 @@ bool CFCMutableArray::AppendFileSystemRepresentationAsCFString(
const char *s, bool can_create) {
CFMutableArrayRef array = get();
if (array == NULL) {
- if (can_create == false)
+ if (!can_create)
return false;
array =
::CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
diff --git a/source/Host/macosx/cfcpp/CFCMutableSet.cpp b/source/Host/macosx/cfcpp/CFCMutableSet.cpp
index c339e950674b..b8bf81e1b52e 100644
--- a/source/Host/macosx/cfcpp/CFCMutableSet.cpp
+++ b/source/Host/macosx/cfcpp/CFCMutableSet.cpp
@@ -9,10 +9,6 @@
#include "CFCMutableSet.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
//----------------------------------------------------------------------
// CFCString constructor
@@ -64,7 +60,7 @@ const void *CFCMutableSet::GetValue(const void *value) const {
const void *CFCMutableSet::AddValue(const void *value, bool can_create) {
CFMutableSetRef set = get();
if (set == NULL) {
- if (can_create == false)
+ if (!can_create)
return NULL;
set = ::CFSetCreateMutable(kCFAllocatorDefault, 0, &kCFTypeSetCallBacks);
reset(set);
diff --git a/source/Host/macosx/objcxx/Host.mm b/source/Host/macosx/objcxx/Host.mm
index a70bf0421ec4..3cf44c4cb65f 100644
--- a/source/Host/macosx/objcxx/Host.mm
+++ b/source/Host/macosx/objcxx/Host.mm
@@ -55,10 +55,11 @@
#include <unistd.h>
#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -100,12 +101,12 @@ using namespace lldb_private;
bool Host::GetBundleDirectory(const FileSpec &file,
FileSpec &bundle_directory) {
#if defined(__APPLE__)
- if (llvm::sys::fs::is_directory(file.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(file)) {
char path[PATH_MAX];
if (file.GetPath(path, sizeof(path))) {
CFCBundle bundle(path);
if (bundle.GetPath(path, sizeof(path))) {
- bundle_directory.SetFile(path, false, FileSpec::Style::native);
+ bundle_directory.SetFile(path, FileSpec::Style::native);
return true;
}
}
@@ -117,7 +118,7 @@ bool Host::GetBundleDirectory(const FileSpec &file,
bool Host::ResolveExecutableInBundle(FileSpec &file) {
#if defined(__APPLE__)
- if (llvm::sys::fs::is_directory(file.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(file)) {
char path[PATH_MAX];
if (file.GetPath(path, sizeof(path))) {
CFCBundle bundle(path);
@@ -125,7 +126,7 @@ bool Host::ResolveExecutableInBundle(FileSpec &file) {
if (url.get()) {
if (::CFURLGetFileSystemRepresentation(url.get(), YES, (UInt8 *)path,
sizeof(path))) {
- file.SetFile(path, false, FileSpec::Style::native);
+ file.SetFile(path, FileSpec::Style::native);
return true;
}
}
@@ -225,7 +226,7 @@ LaunchInNewTerminalWithAppleScript(const char *exe_path,
darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
- if (!darwin_debug_file_spec.Exists()) {
+ if (!FileSystem::Instance().Exists(darwin_debug_file_spec)) {
error.SetErrorStringWithFormat(
"the 'darwin-debug' executable doesn't exists at '%s'",
darwin_debug_file_spec.GetPath().c_str());
@@ -485,11 +486,9 @@ static bool GetMacOSXProcessCPUType(ProcessInstanceInfo &process_info) {
bool host_cpu_is_64bit;
uint32_t is64bit_capable;
size_t is64bit_capable_len = sizeof(is64bit_capable);
- if (sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
- &is64bit_capable_len, NULL, 0) == 0)
- host_cpu_is_64bit = true;
- else
- host_cpu_is_64bit = false;
+ host_cpu_is_64bit =
+ sysctlbyname("hw.cpu64bit_capable", &is64bit_capable,
+ &is64bit_capable_len, NULL, 0) == 0;
// if the host is an armv8 device, its cpusubtype will be in
// CPU_SUBTYPE_ARM64 numbering
@@ -541,8 +540,7 @@ static bool GetMacOSXProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
triple_arch == llvm::Triple::x86_64);
const char *cstr = data.GetCStr(&offset);
if (cstr) {
- process_info.GetExecutableFile().SetFile(cstr, false,
- FileSpec::Style::native);
+ process_info.GetExecutableFile().SetFile(cstr, FileSpec::Style::native);
if (match_info_ptr == NULL ||
NameMatches(
@@ -629,7 +627,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
size_t pid_data_size = 0;
- if (::sysctl(mib, 4, NULL, &pid_data_size, NULL, 0) != 0)
+ if (::sysctl(mib, 3, nullptr, &pid_data_size, nullptr, 0) != 0)
return 0;
// Add a few extra in case a few more show up
@@ -639,7 +637,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
kinfos.resize(estimated_pid_count);
pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);
- if (::sysctl(mib, 4, &kinfos[0], &pid_data_size, NULL, 0) != 0)
+ if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, nullptr, 0) != 0)
return 0;
const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
@@ -660,7 +658,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
if (our_uid == 0)
kinfo_user_matches = true;
- if (kinfo_user_matches == false || // Make sure the user is acceptable
+ if (!kinfo_user_matches || // Make sure the user is acceptable
static_cast<lldb::pid_t>(kinfo.kp_proc.p_pid) ==
our_pid || // Skip this process
kinfo.kp_proc.p_pid == 0 || // Skip kernel (kernel pid is zero)
@@ -1273,21 +1271,19 @@ static bool ShouldLaunchUsingXPC(ProcessLaunchInfo &launch_info) {
Status Host::LaunchProcess(ProcessLaunchInfo &launch_info) {
Status error;
+
+ FileSystem &fs = FileSystem::Instance();
FileSpec exe_spec(launch_info.GetExecutableFile());
- llvm::sys::fs::file_status stats;
- status(exe_spec.GetPath(), stats);
- if (!exists(stats)) {
- exe_spec.ResolvePath();
- status(exe_spec.GetPath(), stats);
- }
- if (!exists(stats)) {
- exe_spec.ResolveExecutableLocation();
- status(exe_spec.GetPath(), stats);
- }
- if (!exists(stats)) {
+ if (!fs.Exists(exe_spec))
+ FileSystem::Instance().Resolve(exe_spec);
+
+ if (!fs.Exists(exe_spec))
+ FileSystem::Instance().ResolveExecutableLocation(exe_spec);
+
+ if (!fs.Exists(exe_spec)) {
error.SetErrorStringWithFormatv("executable doesn't exist: '{0}'",
- launch_info.GetExecutableFile());
+ exe_spec);
return error;
}
@@ -1337,7 +1333,7 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
return error;
}
expand_tool_spec.AppendPathComponent("lldb-argdumper");
- if (!expand_tool_spec.Exists()) {
+ if (!FileSystem::Instance().Exists(expand_tool_spec)) {
error.SetErrorStringWithFormat(
"could not find the lldb-argdumper tool: %s",
expand_tool_spec.GetPath().c_str());
@@ -1354,14 +1350,14 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
int status;
std::string output;
FileSpec cwd(launch_info.GetWorkingDirectory());
- if (!cwd.Exists()) {
+ if (!FileSystem::Instance().Exists(cwd)) {
char *wd = getcwd(nullptr, 0);
if (wd == nullptr) {
error.SetErrorStringWithFormat(
"cwd does not exist; cannot launch with shell argument expansion");
return error;
} else {
- FileSpec working_dir(wd, false);
+ FileSpec working_dir(wd);
free(wd);
launch_info.SetWorkingDirectory(working_dir);
}
diff --git a/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index a39d26aa31ae..165e87e8bed4 100644
--- a/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -7,11 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Host/HostInfo.h"
#include "lldb/Host/macosx/HostInfoMacOSX.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/SafeMachO.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
@@ -97,14 +97,13 @@ FileSpec HostInfoMacOSX::GetProgramFileSpec() {
uint32_t len = sizeof(program_fullpath);
int err = _NSGetExecutablePath(program_fullpath, &len);
if (err == 0)
- g_program_filespec.SetFile(program_fullpath, false,
- FileSpec::Style::native);
+ g_program_filespec.SetFile(program_fullpath, FileSpec::Style::native);
else if (err == -1) {
char *large_program_fullpath = (char *)::malloc(len + 1);
err = _NSGetExecutablePath(large_program_fullpath, &len);
if (err == 0)
- g_program_filespec.SetFile(large_program_fullpath, false,
+ g_program_filespec.SetFile(large_program_fullpath,
FileSpec::Style::native);
::free(large_program_fullpath);
@@ -140,8 +139,9 @@ bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) {
// as in the case of a python script, the executable is python, not
// the lldb driver.
raw_path.append("/../bin");
- FileSpec support_dir_spec(raw_path, true);
- if (!llvm::sys::fs::is_directory(support_dir_spec.GetPath())) {
+ FileSpec support_dir_spec(raw_path);
+ FileSystem::Instance().Resolve(support_dir_spec);
+ if (!FileSystem::Instance().IsDirectory(support_dir_spec)) {
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (log)
log->Printf("HostInfoMacOSX::%s(): failed to find support directory",
@@ -204,7 +204,8 @@ bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
}
bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
- FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true);
+ FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns");
+ FileSystem::Instance().Resolve(temp_file);
file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
return true;
}
@@ -254,6 +255,9 @@ void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32,
#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
arch_32.GetTriple().setOS(llvm::Triple::TvOS);
arch_64.GetTriple().setOS(llvm::Triple::TvOS);
+#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
+ arch_32.GetTriple().setOS(llvm::Triple::BridgeOS);
+ arch_64.GetTriple().setOS(llvm::Triple::BridgeOS);
#else
arch_32.GetTriple().setOS(llvm::Triple::IOS);
arch_64.GetTriple().setOS(llvm::Triple::IOS);
diff --git a/source/Host/netbsd/Host.cpp b/source/Host/netbsd/Host.cpp
index bfd5a74ffcc2..4d50363c72e0 100644
--- a/source/Host/netbsd/Host.cpp
+++ b/source/Host/netbsd/Host.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <dlfcn.h>
#include <execinfo.h>
#include <stdio.h>
@@ -22,9 +21,6 @@
#include <sys/exec.h>
#include <sys/ptrace.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
@@ -70,7 +66,7 @@ static bool GetNetBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
if (!cstr)
return false;
- process_info.GetExecutableFile().SetFile(cstr, false,
+ process_info.GetExecutableFile().SetFile(cstr,
FileSpec::Style::native);
if (!(match_info_ptr == NULL ||
diff --git a/source/Host/netbsd/HostInfoNetBSD.cpp b/source/Host/netbsd/HostInfoNetBSD.cpp
index dfbce310509d..a54483fcc55b 100644
--- a/source/Host/netbsd/HostInfoNetBSD.cpp
+++ b/source/Host/netbsd/HostInfoNetBSD.cpp
@@ -85,7 +85,7 @@ FileSpec HostInfoNetBSD::GetProgramFileSpec() {
len = sizeof(path);
if (sysctl(name, __arraycount(name), path, &len, NULL, 0) != -1) {
- g_program_filespec.SetFile(path, false, FileSpec::Style::native);
+ g_program_filespec.SetFile(path, FileSpec::Style::native);
}
}
return g_program_filespec;
diff --git a/source/Host/openbsd/Host.cpp b/source/Host/openbsd/Host.cpp
index 49e9c290a027..cba1f4ee6b7c 100644
--- a/source/Host/openbsd/Host.cpp
+++ b/source/Host/openbsd/Host.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <sys/types.h>
#include <sys/signal.h>
@@ -19,9 +18,6 @@
#include <stdio.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
diff --git a/source/Host/posix/ConnectionFileDescriptorPosix.cpp b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
index c21bb786a896..deac3844d4a2 100644
--- a/source/Host/posix/ConnectionFileDescriptorPosix.cpp
+++ b/source/Host/posix/ConnectionFileDescriptorPosix.cpp
@@ -21,7 +21,6 @@
#include "lldb/Utility/SelectHelper.h"
#include "lldb/Utility/Timeout.h"
-// C Includes
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -33,16 +32,13 @@
#include <unistd.h>
#endif
-// C++ Includes
#include <sstream>
-// Other libraries and framework includes
#include "llvm/Support/Errno.h"
#include "llvm/Support/ErrorHandling.h"
#if defined(__APPLE__)
#include "llvm/ADT/SmallVector.h"
#endif
-// Project includes
#include "lldb/Host/Host.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/common/TCPSocket.h"
diff --git a/source/Host/posix/FileSystem.cpp b/source/Host/posix/FileSystem.cpp
index 60be642df608..d7045ff99919 100644
--- a/source/Host/posix/FileSystem.cpp
+++ b/source/Host/posix/FileSystem.cpp
@@ -11,6 +11,7 @@
// C includes
#include <dirent.h>
+#include <fcntl.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/stat.h>
@@ -47,7 +48,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
error.SetErrorToErrno();
else {
buf[count] = '\0'; // Success
- dst.SetFile(buf, false, FileSpec::Style::native);
+ dst.SetFile(buf, FileSpec::Style::native);
}
return error;
}
@@ -65,7 +66,7 @@ Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {
return err;
}
- dst = FileSpec(real_path, false);
+ dst = FileSpec(real_path);
return Status();
}
@@ -73,3 +74,7 @@ Status FileSystem::ResolveSymbolicLink(const FileSpec &src, FileSpec &dst) {
FILE *FileSystem::Fopen(const char *path, const char *mode) {
return ::fopen(path, mode);
}
+
+int FileSystem::Open(const char *path, int flags, int mode) {
+ return ::open(path, flags, mode);
+}
diff --git a/source/Host/posix/HostInfoPosix.cpp b/source/Host/posix/HostInfoPosix.cpp
index 62c70fa3edc1..4763ebc9b9d4 100644
--- a/source/Host/posix/HostInfoPosix.cpp
+++ b/source/Host/posix/HostInfoPosix.cpp
@@ -119,7 +119,7 @@ uint32_t HostInfoPosix::GetEffectiveUserID() { return geteuid(); }
uint32_t HostInfoPosix::GetEffectiveGroupID() { return getegid(); }
-FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh", false); }
+FileSpec HostInfoPosix::GetDefaultShell() { return FileSpec("/bin/sh"); }
bool HostInfoPosix::ComputePathRelativeToLibrary(FileSpec &file_spec,
llvm::StringRef dir) {
@@ -163,7 +163,7 @@ bool HostInfoPosix::ComputeSupportExeDirectory(FileSpec &file_spec) {
}
bool HostInfoPosix::ComputeHeaderDirectory(FileSpec &file_spec) {
- FileSpec temp_file("/opt/local/include/lldb", false);
+ FileSpec temp_file("/opt/local/include/lldb");
file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
return true;
}
diff --git a/source/Host/posix/HostProcessPosix.cpp b/source/Host/posix/HostProcessPosix.cpp
index 3c5273f4bd3f..f431e0c72de1 100644
--- a/source/Host/posix/HostProcessPosix.cpp
+++ b/source/Host/posix/HostProcessPosix.cpp
@@ -62,7 +62,7 @@ Status HostProcessPosix::GetMainModule(FileSpec &file_spec) const {
return error;
}
- error = FileSystem::Readlink(FileSpec{link_path, false}, file_spec);
+ error = FileSystem::Instance().Readlink(FileSpec(link_path), file_spec);
if (!error.Success())
return error;
diff --git a/source/Host/posix/PipePosix.cpp b/source/Host/posix/PipePosix.cpp
index b321cad64275..866a9897ee43 100644
--- a/source/Host/posix/PipePosix.cpp
+++ b/source/Host/posix/PipePosix.cpp
@@ -61,12 +61,13 @@ bool SetCloexecFlag(int fd) {
std::chrono::time_point<std::chrono::steady_clock> Now() {
return std::chrono::steady_clock::now();
}
-}
+} // namespace
PipePosix::PipePosix()
: m_fds{PipePosix::kInvalidDescriptor, PipePosix::kInvalidDescriptor} {}
-PipePosix::PipePosix(int read_fd, int write_fd) : m_fds{read_fd, write_fd} {}
+PipePosix::PipePosix(lldb::pipe_t read, lldb::pipe_t write)
+ : m_fds{read, write} {}
PipePosix::PipePosix(PipePosix &&pipe_posix)
: PipeBase{std::move(pipe_posix)},
@@ -125,8 +126,8 @@ Status PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) {
Status PipePosix::CreateWithUniqueName(llvm::StringRef prefix,
bool child_process_inherit,
llvm::SmallVectorImpl<char> &name) {
- llvm::SmallString<PATH_MAX> named_pipe_path;
- llvm::SmallString<PATH_MAX> pipe_spec((prefix + ".%%%%%%").str());
+ llvm::SmallString<128> named_pipe_path;
+ llvm::SmallString<128> pipe_spec((prefix + ".%%%%%%").str());
FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir();
if (!tmpdir_file_spec)
tmpdir_file_spec.AppendPathComponent("/tmp");
diff --git a/source/Host/posix/ProcessLauncherPosixFork.cpp b/source/Host/posix/ProcessLauncherPosixFork.cpp
index 46ce3e3d224f..6bf78463d060 100644
--- a/source/Host/posix/ProcessLauncherPosixFork.cpp
+++ b/source/Host/posix/ProcessLauncherPosixFork.cpp
@@ -157,7 +157,7 @@ static void LLVM_ATTRIBUTE_NORETURN ChildFunc(int error_fd,
#if defined(__linux__)
if (errno == ETXTBSY) {
- // On android M and earlier we can get this error because the adb deamon
+ // On android M and earlier we can get this error because the adb daemon
// can hold a write handle on the executable even after it has finished
// uploading it. This state lasts only a short time and happens only when
// there are many concurrent adb commands being issued, such as when
diff --git a/source/Host/windows/FileSystem.cpp b/source/Host/windows/FileSystem.cpp
index 9309b89f2baf..3217cdc8480a 100644
--- a/source/Host/windows/FileSystem.cpp
+++ b/source/Host/windows/FileSystem.cpp
@@ -75,7 +75,7 @@ Status FileSystem::Readlink(const FileSpec &src, FileSpec &dst) {
else if (!llvm::convertWideToUTF8(buf.data(), path))
error.SetErrorString(PATH_CONVERSION_ERROR);
else
- dst.SetFile(path, false, FileSpec::Style::native);
+ dst.SetFile(path, FileSpec::Style::native);
::CloseHandle(h);
return error;
@@ -96,3 +96,12 @@ FILE *FileSystem::Fopen(const char *path, const char *mode) {
return nullptr;
return file;
}
+
+int FileSystem::Open(const char *path, int flags, int mode) {
+ std::wstring wpath;
+ if (!llvm::ConvertUTF8toWide(path, wpath))
+ return -1;
+ int result;
+ ::_wsopen_s(&result, wpath.c_str(), flags, _SH_DENYNO, mode);
+ return result;
+}
diff --git a/source/Host/windows/Host.cpp b/source/Host/windows/Host.cpp
index cc6c454d36b1..3ac16a42286a 100644
--- a/source/Host/windows/Host.cpp
+++ b/source/Host/windows/Host.cpp
@@ -7,14 +7,11 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include "lldb/Host/windows/AutoHandle.h"
#include "lldb/Host/windows/windows.h"
#include <stdio.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
@@ -36,8 +33,9 @@ namespace {
bool GetTripleForProcess(const FileSpec &executable, llvm::Triple &triple) {
// Open the PE File as a binary file, and parse just enough information to
// determine the machine type.
- File imageBinary(executable.GetPath().c_str(), File::eOpenOptionRead,
- lldb::eFilePermissionsUserRead);
+ File imageBinary;
+ FileSystem::Instance().Open(imageBinary, executable, File::eOpenOptionRead,
+ lldb::eFilePermissionsUserRead);
imageBinary.SeekFromStart(0x3c);
int32_t peOffset = 0;
uint32_t peHead = 0;
@@ -83,7 +81,7 @@ void GetProcessExecutableAndTriple(const AutoHandle &handle,
triple.setOS(llvm::Triple::Win32);
triple.setArch(llvm::Triple::UnknownArch);
if (GetExecutableForProcess(handle, executable)) {
- FileSpec executableFile(executable.c_str(), false);
+ FileSpec executableFile(executable.c_str());
process.SetExecutableFile(executableFile, true);
GetTripleForProcess(executableFile, triple);
}
@@ -122,7 +120,7 @@ FileSpec Host::GetModuleFileSpecForHostAddress(const void *host_addr) {
std::string path;
if (!llvm::convertWideToUTF8(buffer.data(), path))
return module_filespec;
- module_filespec.SetFile(path, false, FileSpec::Style::native);
+ module_filespec.SetFile(path, FileSpec::Style::native);
return module_filespec;
}
@@ -145,7 +143,7 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfo process;
std::string exeFile;
llvm::convertWideToUTF8(pe.szExeFile, exeFile);
- process.SetExecutableFile(FileSpec(exeFile, false), true);
+ process.SetExecutableFile(FileSpec(exeFile), true);
process.SetProcessID(pe.th32ProcessID);
process.SetParentProcessID(pe.th32ParentProcessID);
GetProcessExecutableAndTriple(handle, process);
@@ -189,7 +187,7 @@ Status Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
return error;
}
expand_tool_spec.AppendPathComponent("lldb-argdumper.exe");
- if (!expand_tool_spec.Exists()) {
+ if (!FileSystem::Instance().Exists(expand_tool_spec)) {
error.SetErrorString("could not find the lldb-argdumper tool");
return error;
}
diff --git a/source/Host/windows/HostInfoWindows.cpp b/source/Host/windows/HostInfoWindows.cpp
index bd3f74f2e2f3..81392d9a85b3 100644
--- a/source/Host/windows/HostInfoWindows.cpp
+++ b/source/Host/windows/HostInfoWindows.cpp
@@ -11,7 +11,7 @@
#include <objbase.h>
-#include <mutex> // std::once
+#include <mutex>
#include "lldb/Host/windows/HostInfoWindows.h"
#include "lldb/Host/windows/PosixApi.h"
@@ -92,7 +92,7 @@ FileSpec HostInfoWindows::GetProgramFileSpec() {
::GetModuleFileNameW(NULL, buffer.data(), buffer.size());
std::string path;
llvm::convertWideToUTF8(buffer.data(), path);
- m_program_filespec.SetFile(path, false, FileSpec::Style::native);
+ m_program_filespec.SetFile(path, FileSpec::Style::native);
});
return m_program_filespec;
}
@@ -103,9 +103,9 @@ FileSpec HostInfoWindows::GetDefaultShell() {
std::string shell;
if (GetEnvironmentVar("ComSpec", shell))
- return FileSpec(shell, false);
+ return FileSpec(shell);
- return FileSpec("C:\\Windows\\system32\\cmd.exe", false);
+ return FileSpec("C:\\Windows\\system32\\cmd.exe");
}
bool HostInfoWindows::GetEnvironmentVar(const std::string &var_name,
diff --git a/source/Host/windows/HostProcessWindows.cpp b/source/Host/windows/HostProcessWindows.cpp
index ce75c14cdcf4..701167ff6fea 100644
--- a/source/Host/windows/HostProcessWindows.cpp
+++ b/source/Host/windows/HostProcessWindows.cpp
@@ -57,7 +57,7 @@ Status HostProcessWindows::GetMainModule(FileSpec &file_spec) const {
if (::GetProcessImageFileNameW(m_process, wpath.data(), wpath.size())) {
std::string path;
if (llvm::convertWideToUTF8(wpath.data(), path))
- file_spec.SetFile(path, false, FileSpec::Style::native);
+ file_spec.SetFile(path, FileSpec::Style::native);
else
error.SetErrorString("Error converting path to UTF-8");
} else
diff --git a/source/Host/windows/HostThreadWindows.cpp b/source/Host/windows/HostThreadWindows.cpp
index 3d603ff61663..b516230e7fa4 100644
--- a/source/Host/windows/HostThreadWindows.cpp
+++ b/source/Host/windows/HostThreadWindows.cpp
@@ -69,3 +69,7 @@ void HostThreadWindows::Reset() {
HostNativeThreadBase::Reset();
}
+
+bool HostThreadWindows::EqualsThread(lldb::thread_t thread) const {
+ return GetThreadId() == ::GetThreadId(thread);
+}
diff --git a/source/Host/windows/PipeWindows.cpp b/source/Host/windows/PipeWindows.cpp
index 1951c9ca193a..57221a72899c 100644
--- a/source/Host/windows/PipeWindows.cpp
+++ b/source/Host/windows/PipeWindows.cpp
@@ -25,14 +25,41 @@ using namespace lldb_private;
namespace {
std::atomic<uint32_t> g_pipe_serial(0);
+constexpr llvm::StringLiteral g_pipe_name_prefix = "\\\\.\\Pipe\\";
+} // namespace
+
+PipeWindows::PipeWindows()
+ : m_read(INVALID_HANDLE_VALUE), m_write(INVALID_HANDLE_VALUE),
+ m_read_fd(PipeWindows::kInvalidDescriptor),
+ m_write_fd(PipeWindows::kInvalidDescriptor) {
+ ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+ ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
}
-PipeWindows::PipeWindows() {
- m_read = INVALID_HANDLE_VALUE;
- m_write = INVALID_HANDLE_VALUE;
+PipeWindows::PipeWindows(pipe_t read, pipe_t write)
+ : m_read((HANDLE)read), m_write((HANDLE)write),
+ m_read_fd(PipeWindows::kInvalidDescriptor),
+ m_write_fd(PipeWindows::kInvalidDescriptor) {
+ assert(read != LLDB_INVALID_PIPE || write != LLDB_INVALID_PIPE);
+
+ // Don't risk in passing file descriptors and getting handles from them by
+ // _get_osfhandle since the retrieved handles are highly likely unrecognized
+ // in the current process and usually crashes the program. Pass handles
+ // instead since the handle can be inherited.
+
+ if (read != LLDB_INVALID_PIPE) {
+ m_read_fd = _open_osfhandle((intptr_t)read, _O_RDONLY);
+ // Make sure the fd and native handle are consistent.
+ if (m_read_fd < 0)
+ m_read = INVALID_HANDLE_VALUE;
+ }
+
+ if (write != LLDB_INVALID_PIPE) {
+ m_write_fd = _open_osfhandle((intptr_t)write, _O_WRONLY);
+ if (m_write_fd < 0)
+ m_write = INVALID_HANDLE_VALUE;
+ }
- m_read_fd = -1;
- m_write_fd = -1;
ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
}
@@ -40,6 +67,24 @@ PipeWindows::PipeWindows() {
PipeWindows::~PipeWindows() { Close(); }
Status PipeWindows::CreateNew(bool child_process_inherit) {
+ // Create an anonymous pipe with the specified inheritance.
+ SECURITY_ATTRIBUTES sa{sizeof(SECURITY_ATTRIBUTES), 0,
+ child_process_inherit ? TRUE : FALSE};
+ BOOL result = ::CreatePipe(&m_read, &m_write, &sa, 1024);
+ if (result == FALSE)
+ return Status(::GetLastError(), eErrorTypeWin32);
+
+ m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
+ ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
+ m_read_overlapped.hEvent = ::CreateEventA(nullptr, TRUE, FALSE, nullptr);
+
+ m_write_fd = _open_osfhandle((intptr_t)m_write, _O_WRONLY);
+ ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
+
+ return Status();
+}
+
+Status PipeWindows::CreateNewNamed(bool child_process_inherit) {
// Even for anonymous pipes, we open a named pipe. This is because you
// cannot get overlapped i/o on Windows without using a named pipe. So we
// synthesize a unique name.
@@ -60,7 +105,7 @@ Status PipeWindows::CreateNew(llvm::StringRef name,
if (CanRead() || CanWrite())
return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
- std::string pipe_path = "\\\\.\\Pipe\\";
+ std::string pipe_path = g_pipe_name_prefix;
pipe_path.append(name);
// Always open for overlapped i/o. We implement blocking manually in Read
@@ -75,7 +120,8 @@ Status PipeWindows::CreateNew(llvm::StringRef name,
ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
m_read_overlapped.hEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
- // Open the write end of the pipe.
+ // Open the write end of the pipe. Note that closing either the read or
+ // write end of the pipe could directly close the pipe itself.
Status result = OpenNamedPipe(name, child_process_inherit, false);
if (!result.Success()) {
CloseReadFileDescriptor();
@@ -111,7 +157,7 @@ Status PipeWindows::CreateWithUniqueName(llvm::StringRef prefix,
Status PipeWindows::OpenAsReader(llvm::StringRef name,
bool child_process_inherit) {
- if (CanRead() || CanWrite())
+ if (CanRead())
return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
return OpenNamedPipe(name, child_process_inherit, true);
@@ -121,7 +167,7 @@ Status
PipeWindows::OpenAsWriterWithTimeout(llvm::StringRef name,
bool child_process_inherit,
const std::chrono::microseconds &timeout) {
- if (CanRead() || CanWrite())
+ if (CanWrite())
return Status(ERROR_ALREADY_EXISTS, eErrorTypeWin32);
return OpenNamedPipe(name, child_process_inherit, false);
@@ -137,7 +183,7 @@ Status PipeWindows::OpenNamedPipe(llvm::StringRef name,
SECURITY_ATTRIBUTES attributes = {};
attributes.bInheritHandle = child_process_inherit;
- std::string pipe_path = "\\\\.\\Pipe\\";
+ std::string pipe_path = g_pipe_name_prefix;
pipe_path.append(name);
if (is_read) {
@@ -170,9 +216,9 @@ int PipeWindows::GetWriteFileDescriptor() const { return m_write_fd; }
int PipeWindows::ReleaseReadFileDescriptor() {
if (!CanRead())
- return -1;
+ return PipeWindows::kInvalidDescriptor;
int result = m_read_fd;
- m_read_fd = -1;
+ m_read_fd = PipeWindows::kInvalidDescriptor;
if (m_read_overlapped.hEvent)
::CloseHandle(m_read_overlapped.hEvent);
m_read = INVALID_HANDLE_VALUE;
@@ -182,9 +228,9 @@ int PipeWindows::ReleaseReadFileDescriptor() {
int PipeWindows::ReleaseWriteFileDescriptor() {
if (!CanWrite())
- return -1;
+ return PipeWindows::kInvalidDescriptor;
int result = m_write_fd;
- m_write_fd = -1;
+ m_write_fd = PipeWindows::kInvalidDescriptor;
m_write = INVALID_HANDLE_VALUE;
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
return result;
@@ -196,9 +242,10 @@ void PipeWindows::CloseReadFileDescriptor() {
if (m_read_overlapped.hEvent)
::CloseHandle(m_read_overlapped.hEvent);
+
_close(m_read_fd);
m_read = INVALID_HANDLE_VALUE;
- m_read_fd = -1;
+ m_read_fd = PipeWindows::kInvalidDescriptor;
ZeroMemory(&m_read_overlapped, sizeof(m_read_overlapped));
}
@@ -208,7 +255,7 @@ void PipeWindows::CloseWriteFileDescriptor() {
_close(m_write_fd);
m_write = INVALID_HANDLE_VALUE;
- m_write_fd = -1;
+ m_write_fd = PipeWindows::kInvalidDescriptor;
ZeroMemory(&m_write_overlapped, sizeof(m_write_overlapped));
}
diff --git a/source/Host/windows/ProcessLauncherWindows.cpp b/source/Host/windows/ProcessLauncherWindows.cpp
index 553dd9d286da..a186c7177fdf 100644
--- a/source/Host/windows/ProcessLauncherWindows.cpp
+++ b/source/Host/windows/ProcessLauncherWindows.cpp
@@ -76,6 +76,9 @@ ProcessLauncherWindows::LaunchProcess(const ProcessLaunchInfo &launch_info,
if (launch_info.GetFlags().Test(eLaunchFlagDebug))
flags |= DEBUG_ONLY_THIS_PROCESS;
+ if (launch_info.GetFlags().Test(eLaunchFlagDisableSTDIO))
+ flags &= ~CREATE_NEW_CONSOLE;
+
LPVOID env_block = nullptr;
::CreateEnvironmentBuffer(launch_info.GetEnvironment(), environment);
if (!environment.empty())
diff --git a/source/Initialization/SystemInitializerCommon.cpp b/source/Initialization/SystemInitializerCommon.cpp
index 006ab23595c7..d1d55fcfde74 100644
--- a/source/Initialization/SystemInitializerCommon.cpp
+++ b/source/Initialization/SystemInitializerCommon.cpp
@@ -15,9 +15,11 @@
#include "Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h"
#include "Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h"
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Reproducer.h"
#include "lldb/Utility/Timer.h"
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
@@ -34,12 +36,14 @@
#include <string>
using namespace lldb_private;
+using namespace lldb_private::repro;
SystemInitializerCommon::SystemInitializerCommon() {}
SystemInitializerCommon::~SystemInitializerCommon() {}
-void SystemInitializerCommon::Initialize() {
+llvm::Error
+SystemInitializerCommon::Initialize(const InitializerOptions &options) {
#if defined(_MSC_VER)
const char *disable_crash_dialog_var = getenv("LLDB_DISABLE_CRASH_DIALOG");
if (disable_crash_dialog_var &&
@@ -62,6 +66,16 @@ void SystemInitializerCommon::Initialize() {
}
#endif
+ ReproducerMode mode = ReproducerMode::Off;
+ if (options.reproducer_capture)
+ mode = ReproducerMode::Capture;
+ if (options.reproducer_replay)
+ mode = ReproducerMode::Replay;
+
+ if (auto e = Reproducer::Initialize(mode, FileSpec(options.reproducer_path)))
+ return e;
+
+ FileSystem::Initialize();
Log::Initialize();
HostInfo::Initialize();
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
@@ -87,6 +101,8 @@ void SystemInitializerCommon::Initialize() {
#if defined(_MSC_VER)
ProcessWindowsLog::Initialize();
#endif
+
+ return llvm::Error::success();
}
void SystemInitializerCommon::Terminate() {
@@ -106,4 +122,6 @@ void SystemInitializerCommon::Terminate() {
HostInfo::Terminate();
Log::DisableAllLogChannels();
+ FileSystem::Terminate();
+ Reproducer::Terminate();
}
diff --git a/source/Initialization/SystemLifetimeManager.cpp b/source/Initialization/SystemLifetimeManager.cpp
index 4d271787833d..65431bf6017d 100644
--- a/source/Initialization/SystemLifetimeManager.cpp
+++ b/source/Initialization/SystemLifetimeManager.cpp
@@ -24,9 +24,9 @@ SystemLifetimeManager::~SystemLifetimeManager() {
"SystemLifetimeManager destroyed without calling Terminate!");
}
-void SystemLifetimeManager::Initialize(
+llvm::Error SystemLifetimeManager::Initialize(
std::unique_ptr<SystemInitializer> initializer,
- LoadPluginCallbackType plugin_callback) {
+ const InitializerOptions &options, LoadPluginCallbackType plugin_callback) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (!m_initialized) {
assert(!m_initializer && "Attempting to call "
@@ -35,9 +35,13 @@ void SystemLifetimeManager::Initialize(
m_initialized = true;
m_initializer = std::move(initializer);
- m_initializer->Initialize();
+ if (auto e = m_initializer->Initialize(options))
+ return e;
+
Debugger::Initialize(plugin_callback);
}
+
+ return llvm::Error::success();
}
void SystemLifetimeManager::Terminate() {
diff --git a/source/Interpreter/CMakeLists.txt b/source/Interpreter/CMakeLists.txt
index aaa335af39f9..f8fed8b4ac14 100644
--- a/source/Interpreter/CMakeLists.txt
+++ b/source/Interpreter/CMakeLists.txt
@@ -55,3 +55,7 @@ add_lldb_library(lldbInterpreter
LINK_COMPONENTS
Support
)
+
+if (NOT LLDB_DISABLE_LIBEDIT)
+ target_include_directories(lldbInterpreter PRIVATE ${libedit_INCLUDE_DIRS})
+endif() \ No newline at end of file
diff --git a/source/Interpreter/CommandAlias.cpp b/source/Interpreter/CommandAlias.cpp
index a4b0a0c55c0e..078eb73a7a87 100644
--- a/source/Interpreter/CommandAlias.cpp
+++ b/source/Interpreter/CommandAlias.cpp
@@ -158,8 +158,7 @@ void CommandAlias::GetAliasExpansion(StreamString &help_string) const {
help_string.Printf(" %s", value.c_str());
} else {
help_string.Printf(" %s", opt.c_str());
- if ((value.compare("<no-argument>") != 0) &&
- (value.compare("<need-argument") != 0)) {
+ if ((value != "<no-argument>") && (value != "<need-argument")) {
help_string.Printf(" %s", value.c_str());
}
}
diff --git a/source/Interpreter/CommandInterpreter.cpp b/source/Interpreter/CommandInterpreter.cpp
index 64d2c3222fb6..6d75ec57c83b 100644
--- a/source/Interpreter/CommandInterpreter.cpp
+++ b/source/Interpreter/CommandInterpreter.cpp
@@ -31,6 +31,7 @@
#include "Commands/CommandObjectProcess.h"
#include "Commands/CommandObjectQuit.h"
#include "Commands/CommandObjectRegister.h"
+#include "Commands/CommandObjectReproducer.h"
#include "Commands/CommandObjectSettings.h"
#include "Commands/CommandObjectSource.h"
#include "Commands/CommandObjectStats.h"
@@ -42,9 +43,9 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
@@ -76,28 +77,43 @@ using namespace lldb_private;
static const char *k_white_space = " \t\v";
-static PropertyDefinition g_properties[] = {
- {"expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, regular expression alias commands will show the "
- "expanded command that will be executed. This can be used to "
- "debug new regular expression alias commands."},
- {"prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
+static constexpr bool NoGlobalSetting = true;
+static constexpr uintptr_t DefaultValueTrue = true;
+static constexpr uintptr_t DefaultValueFalse = false;
+static constexpr const char *NoCStrDefault = nullptr;
+
+static constexpr PropertyDefinition g_properties[] = {
+ {"expand-regex-aliases", OptionValue::eTypeBoolean, NoGlobalSetting,
+ DefaultValueFalse, NoCStrDefault, {},
+ "If true, regular expression alias commands will show the "
+ "expanded command that will be executed. This can be used to "
+ "debug new regular expression alias commands."},
+ {"prompt-on-quit", OptionValue::eTypeBoolean, NoGlobalSetting,
+ DefaultValueTrue, NoCStrDefault, {},
"If true, LLDB will prompt you before quitting if there are any live "
"processes being debugged. If false, LLDB will quit without asking in any "
"case."},
- {"stop-command-source-on-error", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr, "If true, LLDB will stop running a 'command source' "
- "script upon encountering an error."},
- {"space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr,
+ {"stop-command-source-on-error", OptionValue::eTypeBoolean, NoGlobalSetting,
+ DefaultValueTrue, NoCStrDefault, {},
+ "If true, LLDB will stop running a 'command source' "
+ "script upon encountering an error."},
+ {"space-repl-prompts", OptionValue::eTypeBoolean, NoGlobalSetting,
+ DefaultValueFalse, NoCStrDefault, {},
"If true, blank lines will be printed between between REPL submissions."},
- {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
+ {"echo-commands", OptionValue::eTypeBoolean, NoGlobalSetting,
+ DefaultValueTrue, NoCStrDefault, {},
+ "If true, commands will be echoed before they are evaluated."},
+ {"echo-comment-commands", OptionValue::eTypeBoolean, NoGlobalSetting,
+ DefaultValueTrue, NoCStrDefault, {},
+ "If true, commands will be echoed even if they are pure comment lines."}};
enum {
ePropertyExpandRegexAliases = 0,
ePropertyPromptOnQuit = 1,
ePropertyStopCmdSourceOnError = 2,
- eSpaceReplPrompts = 3
+ eSpaceReplPrompts = 3,
+ eEchoCommands = 4,
+ eEchoCommentCommands = 5
};
ConstString &CommandInterpreter::GetStaticBroadcasterClass() {
@@ -144,6 +160,28 @@ void CommandInterpreter::SetPromptOnQuit(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
+bool CommandInterpreter::GetEchoCommands() const {
+ const uint32_t idx = eEchoCommands;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void CommandInterpreter::SetEchoCommands(bool b) {
+ const uint32_t idx = eEchoCommands;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
+bool CommandInterpreter::GetEchoCommentCommands() const {
+ const uint32_t idx = eEchoCommentCommands;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void CommandInterpreter::SetEchoCommentCommands(bool b) {
+ const uint32_t idx = eEchoCommentCommands;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
void CommandInterpreter::AllowExitCodeOnQuit(bool allow) {
m_allow_exit_code = allow;
if (!allow)
@@ -386,6 +424,13 @@ void CommandInterpreter::Initialize() {
if (cmd_obj_sp) {
AddAlias("rbreak", cmd_obj_sp, "--func-regex %1");
}
+
+ cmd_obj_sp = GetCommandSPExact("frame variable", false);
+ if (cmd_obj_sp) {
+ AddAlias("v", cmd_obj_sp);
+ AddAlias("var", cmd_obj_sp);
+ AddAlias("vo", cmd_obj_sp, "--object-description");
+ }
}
void CommandInterpreter::Clear() {
@@ -439,6 +484,8 @@ void CommandInterpreter::LoadCommandDictionary() {
m_command_dict["quit"] = CommandObjectSP(new CommandObjectQuit(*this));
m_command_dict["register"] =
CommandObjectSP(new CommandObjectRegister(*this));
+ m_command_dict["reproducer"] =
+ CommandObjectSP(new CommandObjectReproducer(*this));
m_command_dict["script"] =
CommandObjectSP(new CommandObjectScript(*this, script_language));
m_command_dict["settings"] =
@@ -794,20 +841,23 @@ void CommandInterpreter::LoadCommandDictionary() {
}
int CommandInterpreter::GetCommandNamesMatchingPartialString(
- const char *cmd_str, bool include_aliases, StringList &matches) {
- AddNamesMatchingPartialString(m_command_dict, cmd_str, matches);
+ const char *cmd_str, bool include_aliases, StringList &matches,
+ StringList &descriptions) {
+ AddNamesMatchingPartialString(m_command_dict, cmd_str, matches,
+ &descriptions);
if (include_aliases) {
- AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches);
+ AddNamesMatchingPartialString(m_alias_dict, cmd_str, matches,
+ &descriptions);
}
return matches.GetSize();
}
-CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str,
- bool include_aliases,
- bool exact,
- StringList *matches) const {
+CommandObjectSP
+CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str, bool include_aliases,
+ bool exact, StringList *matches,
+ StringList *descriptions) const {
CommandObjectSP command_sp;
std::string cmd = cmd_str;
@@ -848,8 +898,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str,
// empty CommandObjectSP and the list of matches.
if (HasCommands()) {
- num_cmd_matches =
- AddNamesMatchingPartialString(m_command_dict, cmd_str, *matches);
+ num_cmd_matches = AddNamesMatchingPartialString(m_command_dict, cmd_str,
+ *matches, descriptions);
}
if (num_cmd_matches == 1) {
@@ -860,8 +910,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str,
}
if (include_aliases && HasAliases()) {
- num_alias_matches =
- AddNamesMatchingPartialString(m_alias_dict, cmd_str, *matches);
+ num_alias_matches = AddNamesMatchingPartialString(m_alias_dict, cmd_str,
+ *matches, descriptions);
}
if (num_alias_matches == 1) {
@@ -872,8 +922,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str,
}
if (HasUserCommands()) {
- num_user_matches =
- AddNamesMatchingPartialString(m_user_dict, cmd_str, *matches);
+ num_user_matches = AddNamesMatchingPartialString(m_user_dict, cmd_str,
+ *matches, descriptions);
}
if (num_user_matches == 1) {
@@ -898,6 +948,8 @@ CommandObjectSP CommandInterpreter::GetCommandSP(llvm::StringRef cmd_str,
}
} else if (matches && command_sp) {
matches->AppendString(cmd_str);
+ if (descriptions)
+ descriptions->AppendString(command_sp->GetHelp());
}
return command_sp;
@@ -935,16 +987,16 @@ bool CommandInterpreter::AddUserCommand(llvm::StringRef name,
if (!name.empty()) {
// do not allow replacement of internal commands
if (CommandExists(name)) {
- if (can_replace == false)
+ if (!can_replace)
return false;
- if (m_command_dict[name]->IsRemovable() == false)
+ if (!m_command_dict[name]->IsRemovable())
return false;
}
if (UserCommandExists(name)) {
- if (can_replace == false)
+ if (!can_replace)
return false;
- if (m_user_dict[name]->IsRemovable() == false)
+ if (!m_user_dict[name]->IsRemovable())
return false;
}
@@ -997,10 +1049,12 @@ CommandObjectSP CommandInterpreter::GetCommandSPExact(llvm::StringRef cmd_str,
return ret_val;
}
-CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
- StringList *matches) const {
+CommandObject *
+CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
+ StringList *matches,
+ StringList *descriptions) const {
CommandObject *command_obj =
- GetCommandSP(cmd_str, false, true, matches).get();
+ GetCommandSP(cmd_str, false, true, matches, descriptions).get();
// If we didn't find an exact match to the command string in the commands,
// look in the aliases.
@@ -1008,7 +1062,7 @@ CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
if (command_obj)
return command_obj;
- command_obj = GetCommandSP(cmd_str, true, true, matches).get();
+ command_obj = GetCommandSP(cmd_str, true, true, matches, descriptions).get();
if (command_obj)
return command_obj;
@@ -1023,10 +1077,12 @@ CommandObject *CommandInterpreter::GetCommandObject(llvm::StringRef cmd_str,
if (command_obj) {
if (matches)
matches->AppendString(command_obj->GetCommandName());
+ if (descriptions)
+ descriptions->AppendString(command_obj->GetHelp());
return command_obj;
}
- return GetCommandSP(cmd_str, true, false, matches).get();
+ return GetCommandSP(cmd_str, true, false, matches, descriptions).get();
}
bool CommandInterpreter::CommandExists(llvm::StringRef cmd) const {
@@ -1337,7 +1393,7 @@ CommandObject *CommandInterpreter::BuildAliasResult(
alias_cmd_obj = desugared.first.get();
std::string alias_name_str = alias_name;
if ((cmd_args.GetArgumentCount() == 0) ||
- (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0))
+ (alias_name_str != cmd_args.GetArgumentAtIndex(0)))
cmd_args.Unshift(alias_name_str);
result_str.Printf("%s", alias_cmd_obj->GetCommandName().str().c_str());
@@ -1399,130 +1455,140 @@ Status CommandInterpreter::PreprocessCommand(std::string &command) {
size_t start_backtick;
size_t pos = 0;
while ((start_backtick = command.find('`', pos)) != std::string::npos) {
+ // Stop if an error was encountered during the previous iteration.
+ if (error.Fail())
+ break;
+
if (start_backtick > 0 && command[start_backtick - 1] == '\\') {
// The backtick was preceded by a '\' character, remove the slash and
- // don't treat the backtick as the start of an expression
+ // don't treat the backtick as the start of an expression.
command.erase(start_backtick - 1, 1);
- // No need to add one to start_backtick since we just deleted a char
+ // No need to add one to start_backtick since we just deleted a char.
pos = start_backtick;
- } else {
- const size_t expr_content_start = start_backtick + 1;
- const size_t end_backtick = command.find('`', expr_content_start);
- if (end_backtick == std::string::npos)
- return error;
- else if (end_backtick == expr_content_start) {
- // Empty expression (two backticks in a row)
- command.erase(start_backtick, 2);
- } else {
- std::string expr_str(command, expr_content_start,
- end_backtick - expr_content_start);
-
- ExecutionContext exe_ctx(GetExecutionContext());
- Target *target = exe_ctx.GetTargetPtr();
- // Get a dummy target to allow for calculator mode while processing
- // backticks. This also helps break the infinite loop caused when
- // target is null.
- if (!target)
- target = m_debugger.GetDummyTarget();
- if (target) {
- ValueObjectSP expr_result_valobj_sp;
-
- EvaluateExpressionOptions options;
- options.SetCoerceToId(false);
- options.SetUnwindOnError(true);
- options.SetIgnoreBreakpoints(true);
- options.SetKeepInMemory(false);
- options.SetTryAllThreads(true);
- options.SetTimeout(llvm::None);
-
- ExpressionResults expr_result = target->EvaluateExpression(
- expr_str.c_str(), exe_ctx.GetFramePtr(), expr_result_valobj_sp,
- options);
-
- if (expr_result == eExpressionCompleted) {
- Scalar scalar;
- if (expr_result_valobj_sp)
- expr_result_valobj_sp =
- expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
- expr_result_valobj_sp->GetDynamicValueType(), true);
- if (expr_result_valobj_sp->ResolveValue(scalar)) {
- command.erase(start_backtick, end_backtick - start_backtick + 1);
- StreamString value_strm;
- const bool show_type = false;
- scalar.GetValue(&value_strm, show_type);
- size_t value_string_size = value_strm.GetSize();
- if (value_string_size) {
- command.insert(start_backtick, value_strm.GetString());
- pos = start_backtick + value_string_size;
- continue;
- } else {
- error.SetErrorStringWithFormat("expression value didn't result "
- "in a scalar value for the "
- "expression '%s'",
- expr_str.c_str());
- }
- } else {
- error.SetErrorStringWithFormat("expression value didn't result "
- "in a scalar value for the "
- "expression '%s'",
- expr_str.c_str());
- }
- } else {
- if (expr_result_valobj_sp)
- error = expr_result_valobj_sp->GetError();
- if (error.Success()) {
-
- switch (expr_result) {
- case eExpressionSetupError:
- error.SetErrorStringWithFormat(
- "expression setup error for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionParseError:
- error.SetErrorStringWithFormat(
- "expression parse error for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionResultUnavailable:
- error.SetErrorStringWithFormat(
- "expression error fetching result for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionCompleted:
- break;
- case eExpressionDiscarded:
- error.SetErrorStringWithFormat(
- "expression discarded for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionInterrupted:
- error.SetErrorStringWithFormat(
- "expression interrupted for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionHitBreakpoint:
- error.SetErrorStringWithFormat(
- "expression hit breakpoint for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionTimedOut:
- error.SetErrorStringWithFormat(
- "expression timed out for the expression '%s'",
- expr_str.c_str());
- break;
- case eExpressionStoppedForDebug:
- error.SetErrorStringWithFormat("expression stop at entry point "
- "for debugging for the "
- "expression '%s'",
- expr_str.c_str());
- break;
- }
- }
- }
+ continue;
+ }
+
+ const size_t expr_content_start = start_backtick + 1;
+ const size_t end_backtick = command.find('`', expr_content_start);
+
+ if (end_backtick == std::string::npos) {
+ // Stop if there's no end backtick.
+ break;
+ }
+
+ if (end_backtick == expr_content_start) {
+ // Skip over empty expression. (two backticks in a row)
+ command.erase(start_backtick, 2);
+ continue;
+ }
+
+ std::string expr_str(command, expr_content_start,
+ end_backtick - expr_content_start);
+
+ ExecutionContext exe_ctx(GetExecutionContext());
+ Target *target = exe_ctx.GetTargetPtr();
+
+ // Get a dummy target to allow for calculator mode while processing
+ // backticks. This also helps break the infinite loop caused when target is
+ // null.
+ if (!target)
+ target = m_debugger.GetDummyTarget();
+
+ if (!target)
+ continue;
+
+ ValueObjectSP expr_result_valobj_sp;
+
+ EvaluateExpressionOptions options;
+ options.SetCoerceToId(false);
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetKeepInMemory(false);
+ options.SetTryAllThreads(true);
+ options.SetTimeout(llvm::None);
+
+ ExpressionResults expr_result =
+ target->EvaluateExpression(expr_str.c_str(), exe_ctx.GetFramePtr(),
+ expr_result_valobj_sp, options);
+
+ if (expr_result == eExpressionCompleted) {
+ Scalar scalar;
+ if (expr_result_valobj_sp)
+ expr_result_valobj_sp =
+ expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(
+ expr_result_valobj_sp->GetDynamicValueType(), true);
+ if (expr_result_valobj_sp->ResolveValue(scalar)) {
+ command.erase(start_backtick, end_backtick - start_backtick + 1);
+ StreamString value_strm;
+ const bool show_type = false;
+ scalar.GetValue(&value_strm, show_type);
+ size_t value_string_size = value_strm.GetSize();
+ if (value_string_size) {
+ command.insert(start_backtick, value_strm.GetString());
+ pos = start_backtick + value_string_size;
+ continue;
+ } else {
+ error.SetErrorStringWithFormat("expression value didn't result "
+ "in a scalar value for the "
+ "expression '%s'",
+ expr_str.c_str());
+ break;
}
+ } else {
+ error.SetErrorStringWithFormat("expression value didn't result "
+ "in a scalar value for the "
+ "expression '%s'",
+ expr_str.c_str());
+ break;
}
- if (error.Fail())
+
+ continue;
+ }
+
+ if (expr_result_valobj_sp)
+ error = expr_result_valobj_sp->GetError();
+
+ if (error.Success()) {
+ switch (expr_result) {
+ case eExpressionSetupError:
+ error.SetErrorStringWithFormat(
+ "expression setup error for the expression '%s'", expr_str.c_str());
+ break;
+ case eExpressionParseError:
+ error.SetErrorStringWithFormat(
+ "expression parse error for the expression '%s'", expr_str.c_str());
+ break;
+ case eExpressionResultUnavailable:
+ error.SetErrorStringWithFormat(
+ "expression error fetching result for the expression '%s'",
+ expr_str.c_str());
+ break;
+ case eExpressionCompleted:
+ break;
+ case eExpressionDiscarded:
+ error.SetErrorStringWithFormat(
+ "expression discarded for the expression '%s'", expr_str.c_str());
+ break;
+ case eExpressionInterrupted:
+ error.SetErrorStringWithFormat(
+ "expression interrupted for the expression '%s'", expr_str.c_str());
+ break;
+ case eExpressionHitBreakpoint:
+ error.SetErrorStringWithFormat(
+ "expression hit breakpoint for the expression '%s'",
+ expr_str.c_str());
break;
+ case eExpressionTimedOut:
+ error.SetErrorStringWithFormat(
+ "expression timed out for the expression '%s'", expr_str.c_str());
+ break;
+ case eExpressionStoppedForDebug:
+ error.SetErrorStringWithFormat("expression stop at entry point "
+ "for debugging for the "
+ "expression '%s'",
+ expr_str.c_str());
+ break;
+ }
}
}
return error;
@@ -1712,16 +1778,17 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
if (request.GetCursorIndex() == -1) {
// We got nothing on the command line, so return the list of commands
bool include_aliases = true;
- StringList new_matches;
- num_command_matches =
- GetCommandNamesMatchingPartialString("", include_aliases, new_matches);
- request.AddCompletions(new_matches);
+ StringList new_matches, descriptions;
+ num_command_matches = GetCommandNamesMatchingPartialString(
+ "", include_aliases, new_matches, descriptions);
+ request.AddCompletions(new_matches, descriptions);
} else if (request.GetCursorIndex() == 0) {
// The cursor is in the first argument, so just do a lookup in the
// dictionary.
- StringList new_matches;
- CommandObject *cmd_obj = GetCommandObject(
- request.GetParsedLine().GetArgumentAtIndex(0), &new_matches);
+ StringList new_matches, new_descriptions;
+ CommandObject *cmd_obj =
+ GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0),
+ &new_matches, &new_descriptions);
if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() &&
new_matches.GetStringAtIndex(0) != nullptr &&
@@ -1733,12 +1800,13 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
look_for_subcommand = true;
num_command_matches = 0;
new_matches.DeleteStringAtIndex(0);
+ new_descriptions.DeleteStringAtIndex(0);
request.GetParsedLine().AppendArgument(llvm::StringRef());
request.SetCursorIndex(request.GetCursorIndex() + 1);
request.SetCursorCharPosition(0);
}
}
- request.AddCompletions(new_matches);
+ request.AddCompletions(new_matches, new_descriptions);
num_command_matches = request.GetNumberOfMatches();
}
@@ -1762,12 +1830,13 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
int CommandInterpreter::HandleCompletion(
const char *current_line, const char *cursor, const char *last_char,
- int match_start_point, int max_return_elements, StringList &matches) {
+ int match_start_point, int max_return_elements, StringList &matches,
+ StringList &descriptions) {
llvm::StringRef command_line(current_line, last_char - current_line);
+ CompletionResult result;
CompletionRequest request(command_line, cursor - current_line,
- match_start_point, max_return_elements, matches);
-
+ match_start_point, max_return_elements, result);
// Don't complete comments, and if the line we are completing is just the
// history repeat character, substitute the appropriate history line.
const char *first_arg = request.GetParsedLine().GetArgumentAtIndex(0);
@@ -1777,6 +1846,7 @@ int CommandInterpreter::HandleCompletion(
else if (first_arg[0] == CommandHistory::g_repeat_char) {
if (auto hist_str = m_command_history.FindString(first_arg)) {
matches.InsertStringAtIndex(0, *hist_str);
+ descriptions.InsertStringAtIndex(0, "Previous command history event");
return -2;
} else
return 0;
@@ -1787,6 +1857,8 @@ int CommandInterpreter::HandleCompletion(
lldbassert(max_return_elements == -1);
int num_command_matches = HandleCompletionMatches(request);
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
if (num_command_matches <= 0)
return num_command_matches;
@@ -1794,6 +1866,7 @@ int CommandInterpreter::HandleCompletion(
if (request.GetParsedLine().GetArgumentCount() == 0) {
// If we got an empty string, insert nothing.
matches.InsertStringAtIndex(0, "");
+ descriptions.InsertStringAtIndex(0, "");
} else {
// Now figure out if there is a common substring, and if so put that in
// element 0, otherwise put an empty string in element 0.
@@ -1815,6 +1888,7 @@ int CommandInterpreter::HandleCompletion(
common_prefix.push_back(' ');
}
matches.InsertStringAtIndex(0, common_prefix.c_str());
+ descriptions.InsertStringAtIndex(0, "");
}
return num_command_matches;
}
@@ -1873,7 +1947,7 @@ void CommandInterpreter::BuildAliasCommandArgs(CommandObject *alias_cmd_obj,
// Make sure that the alias name is the 0th element in cmd_args
std::string alias_name_str = alias_name;
- if (alias_name_str.compare(cmd_args.GetArgumentAtIndex(0)) != 0)
+ if (alias_name_str != cmd_args.GetArgumentAtIndex(0))
cmd_args.Unshift(alias_name_str);
Args new_args(alias_cmd_obj->GetCommandName());
@@ -2025,13 +2099,14 @@ void CommandInterpreter::SourceInitFile(bool in_cwd,
LoadCWDlldbinitFile should_load =
target->TargetProperties::GetLoadCWDlldbinitFile();
if (should_load == eLoadCWDlldbinitWarn) {
- FileSpec dot_lldb(".lldbinit", true);
+ FileSpec dot_lldb(".lldbinit");
+ FileSystem::Instance().Resolve(dot_lldb);
llvm::SmallString<64> home_dir_path;
llvm::sys::path::home_directory(home_dir_path);
- FileSpec homedir_dot_lldb(home_dir_path.c_str(), false);
+ FileSpec homedir_dot_lldb(home_dir_path.c_str());
homedir_dot_lldb.AppendPathComponent(".lldbinit");
- homedir_dot_lldb.ResolvePath();
- if (dot_lldb.Exists() &&
+ FileSystem::Instance().Resolve(homedir_dot_lldb);
+ if (FileSystem::Instance().Exists(dot_lldb) &&
dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory()) {
result.AppendErrorWithFormat(
"There is a .lldbinit file in the current directory which is not "
@@ -2049,7 +2124,8 @@ void CommandInterpreter::SourceInitFile(bool in_cwd,
return;
}
} else if (should_load == eLoadCWDlldbinitTrue) {
- init_file.SetFile("./.lldbinit", true, FileSpec::Style::native);
+ init_file.SetFile("./.lldbinit", FileSpec::Style::native);
+ FileSystem::Instance().Resolve(init_file);
}
}
} else {
@@ -2061,11 +2137,11 @@ void CommandInterpreter::SourceInitFile(bool in_cwd,
// init files.
llvm::SmallString<64> home_dir_path;
llvm::sys::path::home_directory(home_dir_path);
- FileSpec profilePath(home_dir_path.c_str(), false);
+ FileSpec profilePath(home_dir_path.c_str());
profilePath.AppendPathComponent(".lldbinit");
std::string init_file_path = profilePath.GetPath();
- if (m_skip_app_init_files == false) {
+ if (!m_skip_app_init_files) {
FileSpec program_file_spec(HostInfo::GetProgramFileSpec());
const char *program_name = program_file_spec.GetFilename().AsCString();
@@ -2073,22 +2149,22 @@ void CommandInterpreter::SourceInitFile(bool in_cwd,
char program_init_file_name[PATH_MAX];
::snprintf(program_init_file_name, sizeof(program_init_file_name),
"%s-%s", init_file_path.c_str(), program_name);
- init_file.SetFile(program_init_file_name, true,
- FileSpec::Style::native);
- if (!init_file.Exists())
+ init_file.SetFile(program_init_file_name, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(init_file);
+ if (!FileSystem::Instance().Exists(init_file))
init_file.Clear();
}
}
if (!init_file && !m_skip_lldbinit_files)
- init_file.SetFile(init_file_path, false, FileSpec::Style::native);
+ init_file.SetFile(init_file_path, FileSpec::Style::native);
}
// If the file exists, tell HandleCommand to 'source' it; this will do the
// actual broadcasting of the commands back to any appropriate listener (see
// CommandObjectSource::Execute for more details).
- if (init_file.Exists()) {
+ if (FileSystem::Instance().Exists(init_file)) {
const bool saved_batch = SetBatchCommandMode(true);
CommandInterpreterRunOptions options;
options.SetSilent(true);
@@ -2281,20 +2357,20 @@ enum {
eHandleCommandFlagStopOnContinue = (1u << 0),
eHandleCommandFlagStopOnError = (1u << 1),
eHandleCommandFlagEchoCommand = (1u << 2),
- eHandleCommandFlagPrintResult = (1u << 3),
- eHandleCommandFlagStopOnCrash = (1u << 4)
+ eHandleCommandFlagEchoCommentCommand = (1u << 3),
+ eHandleCommandFlagPrintResult = (1u << 4),
+ eHandleCommandFlagStopOnCrash = (1u << 5)
};
void CommandInterpreter::HandleCommandsFromFile(
FileSpec &cmd_file, ExecutionContext *context,
CommandInterpreterRunOptions &options, CommandReturnObject &result) {
- if (cmd_file.Exists()) {
+ if (FileSystem::Instance().Exists(cmd_file)) {
StreamFileSP input_file_sp(new StreamFile());
std::string cmd_file_path = cmd_file.GetPath();
- Status error = input_file_sp->GetFile().Open(cmd_file_path.c_str(),
- File::eOpenOptionRead);
-
+ Status error = FileSystem::Instance().Open(input_file_sp->GetFile(),
+ cmd_file, File::eOpenOptionRead);
if (error.Success()) {
Debugger &debugger = GetDebugger();
@@ -2324,9 +2400,10 @@ void CommandInterpreter::HandleCommandsFromFile(
flags |= eHandleCommandFlagStopOnError;
}
+ // stop-on-crash can only be set, if it is present in all levels of
+ // pushed flag sets.
if (options.GetStopOnCrash()) {
if (m_command_source_flags.empty()) {
- // Echo command by default
flags |= eHandleCommandFlagStopOnCrash;
} else if (m_command_source_flags.back() &
eHandleCommandFlagStopOnCrash) {
@@ -2346,6 +2423,19 @@ void CommandInterpreter::HandleCommandsFromFile(
flags |= eHandleCommandFlagEchoCommand;
}
+ // We will only ever ask for this flag, if we echo commands in general.
+ if (options.m_echo_comment_commands == eLazyBoolCalculate) {
+ if (m_command_source_flags.empty()) {
+ // Echo comments by default
+ flags |= eHandleCommandFlagEchoCommentCommand;
+ } else if (m_command_source_flags.back() &
+ eHandleCommandFlagEchoCommentCommand) {
+ flags |= eHandleCommandFlagEchoCommentCommand;
+ }
+ } else if (options.m_echo_comment_commands == eLazyBoolYes) {
+ flags |= eHandleCommandFlagEchoCommentCommand;
+ }
+
if (options.m_print_results == eLazyBoolCalculate) {
if (m_command_source_flags.empty()) {
// Print output by default
@@ -2667,6 +2757,21 @@ void CommandInterpreter::PrintCommandOutput(Stream &stream,
}
}
+bool CommandInterpreter::EchoCommandNonInteractive(
+ llvm::StringRef line, const Flags &io_handler_flags) const {
+ if (!io_handler_flags.Test(eHandleCommandFlagEchoCommand))
+ return false;
+
+ llvm::StringRef command = line.trim();
+ if (command.empty())
+ return true;
+
+ if (command.front() == m_comment_char)
+ return io_handler_flags.Test(eHandleCommandFlagEchoCommentCommand);
+
+ return true;
+}
+
void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
std::string &line) {
// If we were interrupted, bail out...
@@ -2674,7 +2779,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
return;
const bool is_interactive = io_handler.GetIsInteractive();
- if (is_interactive == false) {
+ if (!is_interactive) {
// When we are not interactive, don't execute blank lines. This will happen
// sourcing a commands file. We don't want blank lines to repeat the
// previous command and cause any errors to occur (like redefining an
@@ -2685,7 +2790,7 @@ void CommandInterpreter::IOHandlerInputComplete(IOHandler &io_handler,
// When using a non-interactive file handle (like when sourcing commands
// from a file) we need to echo the command out so we don't just see the
// command output and no command...
- if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand))
+ if (EchoCommandNonInteractive(line, io_handler.GetFlags()))
io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(),
line.c_str());
}
@@ -2859,6 +2964,8 @@ CommandInterpreter::GetIOHandler(bool force_create,
flags |= eHandleCommandFlagStopOnCrash;
if (options->m_echo_commands != eLazyBoolNo)
flags |= eHandleCommandFlagEchoCommand;
+ if (options->m_echo_comment_commands != eLazyBoolNo)
+ flags |= eHandleCommandFlagEchoCommentCommand;
if (options->m_print_results != eLazyBoolNo)
flags |= eHandleCommandFlagPrintResult;
} else {
@@ -2921,8 +3028,7 @@ CommandInterpreter::ResolveCommandImpl(std::string &command_line,
bool is_alias = GetAliasFullName(next_word, full_name);
cmd_obj = GetCommandObject(next_word, &matches);
bool is_real_command =
- (is_alias == false) ||
- (cmd_obj != nullptr && cmd_obj->IsAlias() == false);
+ (!is_alias) || (cmd_obj != nullptr && !cmd_obj->IsAlias());
if (!is_real_command) {
matches.Clear();
std::string alias_result;
diff --git a/source/Interpreter/CommandObject.cpp b/source/Interpreter/CommandObject.cpp
index 324b0b511220..05c540b37c62 100644
--- a/source/Interpreter/CommandObject.cpp
+++ b/source/Interpreter/CommandObject.cpp
@@ -409,15 +409,12 @@ const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) {
}
bool CommandObject::IsPairType(ArgumentRepetitionType arg_repeat_type) {
- if ((arg_repeat_type == eArgRepeatPairPlain) ||
- (arg_repeat_type == eArgRepeatPairOptional) ||
- (arg_repeat_type == eArgRepeatPairPlus) ||
- (arg_repeat_type == eArgRepeatPairStar) ||
- (arg_repeat_type == eArgRepeatPairRange) ||
- (arg_repeat_type == eArgRepeatPairRangeOptional))
- return true;
-
- return false;
+ return (arg_repeat_type == eArgRepeatPairPlain) ||
+ (arg_repeat_type == eArgRepeatPairOptional) ||
+ (arg_repeat_type == eArgRepeatPairPlus) ||
+ (arg_repeat_type == eArgRepeatPairStar) ||
+ (arg_repeat_type == eArgRepeatPairRange) ||
+ (arg_repeat_type == eArgRepeatPairRangeOptional);
}
static CommandObject::CommandArgumentEntry
diff --git a/source/Interpreter/CommandObjectRegexCommand.cpp b/source/Interpreter/CommandObjectRegexCommand.cpp
index ec89ad8fb162..2944177b0dc3 100644
--- a/source/Interpreter/CommandObjectRegexCommand.cpp
+++ b/source/Interpreter/CommandObjectRegexCommand.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/CommandObjectRegexCommand.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
diff --git a/source/Interpreter/CommandObjectScript.cpp b/source/Interpreter/CommandObjectScript.cpp
index fa1516df60c9..ed434031ae4e 100644
--- a/source/Interpreter/CommandObjectScript.cpp
+++ b/source/Interpreter/CommandObjectScript.cpp
@@ -9,10 +9,6 @@
#include "CommandObjectScript.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
diff --git a/source/Interpreter/CommandObjectScript.h b/source/Interpreter/CommandObjectScript.h
index 7a61b06e5b04..ca453a875494 100644
--- a/source/Interpreter/CommandObjectScript.h
+++ b/source/Interpreter/CommandObjectScript.h
@@ -10,10 +10,6 @@
#ifndef liblldb_CommandObjectScript_h_
#define liblldb_CommandObjectScript_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/CommandObject.h"
namespace lldb_private {
diff --git a/source/Interpreter/CommandReturnObject.cpp b/source/Interpreter/CommandReturnObject.cpp
index 7c06e22c3909..cf397a47a3bf 100644
--- a/source/Interpreter/CommandReturnObject.cpp
+++ b/source/Interpreter/CommandReturnObject.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/CommandReturnObject.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
diff --git a/source/Interpreter/OptionArgParser.cpp b/source/Interpreter/OptionArgParser.cpp
index 3bd3af8fc50e..b0565b706c5b 100644
--- a/source/Interpreter/OptionArgParser.cpp
+++ b/source/Interpreter/OptionArgParser.cpp
@@ -46,10 +46,10 @@ char OptionArgParser::ToChar(llvm::StringRef s, char fail_value,
}
int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s,
- OptionEnumValueElement *enum_values,
+ const OptionEnumValues &enum_values,
int32_t fail_value, Status &error) {
error.Clear();
- if (!enum_values) {
+ if (enum_values.empty()) {
error.SetErrorString("invalid enumeration argument");
return fail_value;
}
@@ -59,16 +59,18 @@ int64_t OptionArgParser::ToOptionEnum(llvm::StringRef s,
return fail_value;
}
- for (int i = 0; enum_values[i].string_value != nullptr; i++) {
- llvm::StringRef this_enum(enum_values[i].string_value);
+ for (const auto &enum_value : enum_values) {
+ llvm::StringRef this_enum(enum_value.string_value);
if (this_enum.startswith(s))
- return enum_values[i].value;
+ return enum_value.value;
}
StreamString strm;
strm.PutCString("invalid enumeration value, valid values are: ");
- for (int i = 0; enum_values[i].string_value != nullptr; i++) {
- strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
+ bool is_first = true;
+ for (const auto &enum_value : enum_values) {
+ strm.Printf("%s\"%s\"",
+ is_first ? is_first = false,"" : ", ", enum_value.string_value);
}
error.SetErrorString(strm.GetString());
return fail_value;
diff --git a/source/Interpreter/OptionGroupArchitecture.cpp b/source/Interpreter/OptionGroupArchitecture.cpp
index bbd69b8f13fc..42eafc9872db 100644
--- a/source/Interpreter/OptionGroupArchitecture.cpp
+++ b/source/Interpreter/OptionGroupArchitecture.cpp
@@ -18,9 +18,9 @@ OptionGroupArchitecture::OptionGroupArchitecture() : m_arch_str() {}
OptionGroupArchitecture::~OptionGroupArchitecture() {}
-static OptionDefinition g_option_table[] = {
+static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "arch", 'a', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeArchitecture,
+ nullptr, {}, 0, eArgTypeArchitecture,
"Specify the architecture for the target."},
};
diff --git a/source/Interpreter/OptionGroupBoolean.cpp b/source/Interpreter/OptionGroupBoolean.cpp
index e3759f2e60a1..ca694ef5f488 100644
--- a/source/Interpreter/OptionGroupBoolean.cpp
+++ b/source/Interpreter/OptionGroupBoolean.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupBoolean.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
using namespace lldb;
@@ -32,7 +28,7 @@ OptionGroupBoolean::OptionGroupBoolean(uint32_t usage_mask, bool required,
m_option_definition.option_has_arg = no_argument_toggle_default
? OptionParser::eNoArgument
: OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
+ m_option_definition.enum_values = {};
m_option_definition.completion_type = 0;
m_option_definition.argument_type = eArgTypeBoolean;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupFile.cpp b/source/Interpreter/OptionGroupFile.cpp
index d45f00a66616..241bad022ba7 100644
--- a/source/Interpreter/OptionGroupFile.cpp
+++ b/source/Interpreter/OptionGroupFile.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupFile.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
using namespace lldb;
@@ -30,7 +26,7 @@ OptionGroupFile::OptionGroupFile(uint32_t usage_mask, bool required,
m_option_definition.short_option = short_option;
m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
+ m_option_definition.enum_values = {};
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
@@ -61,7 +57,7 @@ OptionGroupFileList::OptionGroupFileList(
m_option_definition.short_option = short_option;
m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
+ m_option_definition.enum_values = {};
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupFormat.cpp b/source/Interpreter/OptionGroupFormat.cpp
index b64c19324810..6345a633635c 100644
--- a/source/Interpreter/OptionGroupFormat.cpp
+++ b/source/Interpreter/OptionGroupFormat.cpp
@@ -27,18 +27,18 @@ OptionGroupFormat::OptionGroupFormat(lldb::Format default_format,
OptionGroupFormat::~OptionGroupFormat() {}
-static OptionDefinition g_option_table[] = {
+static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFormat,
+ nullptr, {}, 0, eArgTypeFormat,
"Specify a format to be used for display."},
{LLDB_OPT_SET_2, false, "gdb-format", 'G', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeGDBFormat,
+ nullptr, {}, 0, eArgTypeGDBFormat,
"Specify a format using a GDB format specifier string."},
{LLDB_OPT_SET_3, false, "size", 's', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeByteSize,
+ nullptr, {}, 0, eArgTypeByteSize,
"The size in bytes to use when displaying with the selected format."},
{LLDB_OPT_SET_4, false, "count", 'c', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeCount,
+ nullptr, {}, 0, eArgTypeCount,
"The number of total items to display."},
};
diff --git a/source/Interpreter/OptionGroupOutputFile.cpp b/source/Interpreter/OptionGroupOutputFile.cpp
index fd406494ea97..aebbf05131a0 100644
--- a/source/Interpreter/OptionGroupOutputFile.cpp
+++ b/source/Interpreter/OptionGroupOutputFile.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupOutputFile.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
using namespace lldb;
@@ -25,12 +21,12 @@ OptionGroupOutputFile::~OptionGroupOutputFile() {}
static const uint32_t SHORT_OPTION_APND = 0x61706e64; // 'apnd'
-static OptionDefinition g_option_table[] = {
+static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "outfile", 'o', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Specify a path for capturing command output."},
{LLDB_OPT_SET_1, false, "append-outfile", SHORT_OPTION_APND,
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Append to the file specified with '--outfile <path>'."},
};
diff --git a/source/Interpreter/OptionGroupPlatform.cpp b/source/Interpreter/OptionGroupPlatform.cpp
index 47974276c8c0..5858fcc4aa48 100644
--- a/source/Interpreter/OptionGroupPlatform.cpp
+++ b/source/Interpreter/OptionGroupPlatform.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupPlatform.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Target/Platform.h"
@@ -65,21 +61,21 @@ void OptionGroupPlatform::OptionParsingStarting(
m_os_version = llvm::VersionTuple();
}
-static OptionDefinition g_option_table[] = {
+static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_ALL, false, "platform", 'p', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypePlatform, "Specify name of the platform to "
- "use for this target, creating the "
- "platform if necessary."},
+ nullptr, {}, 0, eArgTypePlatform, "Specify name of the platform to "
+ "use for this target, creating the "
+ "platform if necessary."},
{LLDB_OPT_SET_ALL, false, "version", 'v', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Specify the initial SDK version to use prior to connecting."},
{LLDB_OPT_SET_ALL, false, "build", 'b', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Specify the initial SDK build number."},
{LLDB_OPT_SET_ALL, false, "sysroot", 'S', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename, "Specify the SDK root directory "
- "that contains a root of all "
- "remote system files."}};
+ nullptr, {}, 0, eArgTypeFilename, "Specify the SDK root directory "
+ "that contains a root of all "
+ "remote system files."}};
llvm::ArrayRef<OptionDefinition> OptionGroupPlatform::GetDefinitions() {
llvm::ArrayRef<OptionDefinition> result(g_option_table);
diff --git a/source/Interpreter/OptionGroupString.cpp b/source/Interpreter/OptionGroupString.cpp
index 1a161945a17f..1b1fbdf4f6ed 100644
--- a/source/Interpreter/OptionGroupString.cpp
+++ b/source/Interpreter/OptionGroupString.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupString.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
using namespace lldb;
@@ -31,7 +27,7 @@ OptionGroupString::OptionGroupString(uint32_t usage_mask, bool required,
m_option_definition.short_option = short_option;
m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
+ m_option_definition.enum_values = {};
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupUInt64.cpp b/source/Interpreter/OptionGroupUInt64.cpp
index ae4828c3e926..bb2dcbbd23f9 100644
--- a/source/Interpreter/OptionGroupUInt64.cpp
+++ b/source/Interpreter/OptionGroupUInt64.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupUInt64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
using namespace lldb;
@@ -31,7 +27,7 @@ OptionGroupUInt64::OptionGroupUInt64(uint32_t usage_mask, bool required,
m_option_definition.short_option = short_option;
m_option_definition.validator = nullptr;
m_option_definition.option_has_arg = OptionParser::eRequiredArgument;
- m_option_definition.enum_values = nullptr;
+ m_option_definition.enum_values = {};
m_option_definition.completion_type = completion_type;
m_option_definition.argument_type = argument_type;
m_option_definition.usage_text = usage_text;
diff --git a/source/Interpreter/OptionGroupUUID.cpp b/source/Interpreter/OptionGroupUUID.cpp
index bf02d1b660cf..0859877774cc 100644
--- a/source/Interpreter/OptionGroupUUID.cpp
+++ b/source/Interpreter/OptionGroupUUID.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupUUID.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
using namespace lldb;
@@ -22,9 +18,9 @@ OptionGroupUUID::OptionGroupUUID() : m_uuid() {}
OptionGroupUUID::~OptionGroupUUID() {}
-static OptionDefinition g_option_table[] = {
+static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeNone, "A module UUID value."},
+ nullptr, {}, 0, eArgTypeNone, "A module UUID value."},
};
llvm::ArrayRef<OptionDefinition> OptionGroupUUID::GetDefinitions() {
diff --git a/source/Interpreter/OptionGroupValueObjectDisplay.cpp b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
index 54b45c29c70d..40f219c8ab86 100644
--- a/source/Interpreter/OptionGroupValueObjectDisplay.cpp
+++ b/source/Interpreter/OptionGroupValueObjectDisplay.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -28,46 +24,44 @@ OptionGroupValueObjectDisplay::OptionGroupValueObjectDisplay() {}
OptionGroupValueObjectDisplay::~OptionGroupValueObjectDisplay() {}
-static OptionDefinition g_option_table[] = {
+static const OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "dynamic-type", 'd',
- OptionParser::eRequiredArgument, nullptr, g_dynamic_value_types, 0,
+ OptionParser::eRequiredArgument, nullptr, GetDynamicValueTypes(), 0,
eArgTypeNone, "Show the object as its full dynamic type, not its static "
"type, if available."},
{LLDB_OPT_SET_1, false, "synthetic-type", 'S',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Show the object obeying its synthetic provider, if available."},
{LLDB_OPT_SET_1, false, "depth", 'D', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeCount, "Set the max recurse depth when "
- "dumping aggregate types (default is "
- "infinity)."},
+ nullptr, {}, 0, eArgTypeCount, "Set the max recurse depth when dumping "
+ "aggregate types (default is infinity)."},
{LLDB_OPT_SET_1, false, "flat", 'F', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone, "Display results in a flat format that uses "
- "expression paths for each variable or member."},
+ {}, 0, eArgTypeNone, "Display results in a flat format that uses "
+ "expression paths for each variable or member."},
{LLDB_OPT_SET_1, false, "location", 'L', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone, "Show variable location information."},
+ {}, 0, eArgTypeNone, "Show variable location information."},
{LLDB_OPT_SET_1, false, "object-description", 'O',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Print as an Objective-C object."},
{LLDB_OPT_SET_1, false, "ptr-depth", 'P', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeCount, "The number of pointers to be "
- "traversed when dumping values "
- "(default is zero)."},
+ nullptr, {}, 0, eArgTypeCount, "The number of pointers to be traversed "
+ "when dumping values (default is zero)."},
{LLDB_OPT_SET_1, false, "show-types", 'T', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Show variable types when dumping values."},
{LLDB_OPT_SET_1, false, "no-summary-depth", 'Y',
- OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeCount,
+ OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeCount,
"Set the depth at which omitting summary information stops (default is "
"1)."},
{LLDB_OPT_SET_1, false, "raw-output", 'R', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone, "Don't use formatting options."},
+ nullptr, {}, 0, eArgTypeNone, "Don't use formatting options."},
{LLDB_OPT_SET_1, false, "show-all-children", 'A', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Ignore the upper bound on the number of children to show."},
{LLDB_OPT_SET_1, false, "validate", 'V', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeBoolean, "Show results of type validators."},
+ nullptr, {}, 0, eArgTypeBoolean, "Show results of type validators."},
{LLDB_OPT_SET_1, false, "element-count", 'Z',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount,
"Treat the result of the expression as if its type is an array of this "
"many values."}};
@@ -86,8 +80,8 @@ Status OptionGroupValueObjectDisplay::SetOptionValue(
switch (short_option) {
case 'd': {
int32_t result;
- result = OptionArgParser::ToOptionEnum(option_arg, g_dynamic_value_types, 2,
- error);
+ result = OptionArgParser::ToOptionEnum(option_arg, GetDynamicValueTypes(),
+ 2, error);
if (error.Success())
use_dynamic = (lldb::DynamicValueType)result;
} break;
diff --git a/source/Interpreter/OptionGroupVariable.cpp b/source/Interpreter/OptionGroupVariable.cpp
index 7b7a62be8743..f90212cfcb2f 100644
--- a/source/Interpreter/OptionGroupVariable.cpp
+++ b/source/Interpreter/OptionGroupVariable.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupVariable.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/DataVisualization.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -24,31 +20,34 @@ using namespace lldb_private;
// if you add any options here, remember to update the counters in
// OptionGroupVariable::GetNumDefinitions()
-static OptionDefinition g_variable_options[] = {
+static constexpr OptionDefinition g_variable_options[] = {
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-args", 'a',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Omit function arguments."},
+ {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-recognized-args", 't',
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
+ "Omit recognized function arguments."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "no-locals", 'l',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Omit local variables."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-globals", 'g',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Show the current frame source file global and static variables."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "show-declaration", 'c',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Show variable declaration information (source file and line where the "
"variable was declared)."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "regex", 'r',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeRegularExpression,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeRegularExpression,
"The <variable-name> argument for name lookups are regular expressions."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "scope", 's',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Show variable scope (argument, local, global, static)."},
{LLDB_OPT_SET_1, false, "summary", 'y', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeName,
+ nullptr, {}, 0, eArgTypeName,
"Specify the summary that the variable output should use."},
{LLDB_OPT_SET_2, false, "summary-string", 'z',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeName,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName,
"Specify a summary string to use to format the variable output."},
};
@@ -56,8 +55,8 @@ static Status ValidateNamedSummary(const char *str, void *) {
if (!str || !str[0])
return Status("must specify a valid named summary");
TypeSummaryImplSP summary_sp;
- if (DataVisualization::NamedSummaryFormats::GetSummaryFormat(
- ConstString(str), summary_sp) == false)
+ if (!DataVisualization::NamedSummaryFormats::GetSummaryFormat(
+ ConstString(str), summary_sp))
return Status("must specify a valid named summary");
return Status();
}
@@ -101,6 +100,9 @@ OptionGroupVariable::SetOptionValue(uint32_t option_idx,
case 's':
show_scope = true;
break;
+ case 't':
+ show_recognized_args = false;
+ break;
case 'y':
error = summary.SetCurrentValue(option_arg);
break;
@@ -119,6 +121,7 @@ OptionGroupVariable::SetOptionValue(uint32_t option_idx,
void OptionGroupVariable::OptionParsingStarting(
ExecutionContext *execution_context) {
show_args = true; // Frame option only
+ show_recognized_args = true; // Frame option only
show_locals = true; // Frame option only
show_globals = false; // Frame option only
show_decl = false;
diff --git a/source/Interpreter/OptionGroupWatchpoint.cpp b/source/Interpreter/OptionGroupWatchpoint.cpp
index 0431fefaa7f9..36b4cc5ac4f6 100644
--- a/source/Interpreter/OptionGroupWatchpoint.cpp
+++ b/source/Interpreter/OptionGroupWatchpoint.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionGroupWatchpoint.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/lldb-enumerations.h"
@@ -20,33 +16,31 @@
using namespace lldb;
using namespace lldb_private;
-static OptionEnumValueElement g_watch_type[] = {
+static constexpr OptionEnumValueElement g_watch_type[] = {
{OptionGroupWatchpoint::eWatchRead, "read", "Watch for read"},
{OptionGroupWatchpoint::eWatchWrite, "write", "Watch for write"},
{OptionGroupWatchpoint::eWatchReadWrite, "read_write",
- "Watch for read/write"},
- {0, nullptr, nullptr}};
+ "Watch for read/write"} };
-static OptionEnumValueElement g_watch_size[] = {
+static constexpr OptionEnumValueElement g_watch_size[] = {
{1, "1", "Watch for byte size of 1"},
{2, "2", "Watch for byte size of 2"},
{4, "4", "Watch for byte size of 4"},
- {8, "8", "Watch for byte size of 8"},
- {0, nullptr, nullptr}};
+ {8, "8", "Watch for byte size of 8"} };
-static OptionDefinition g_option_table[] = {
+static constexpr OptionDefinition g_option_table[] = {
{LLDB_OPT_SET_1, false, "watch", 'w', OptionParser::eRequiredArgument,
- nullptr, g_watch_type, 0, eArgTypeWatchType,
+ nullptr, OptionEnumValues(g_watch_type), 0, eArgTypeWatchType,
"Specify the type of watching to perform."},
{LLDB_OPT_SET_1, false, "size", 's', OptionParser::eRequiredArgument,
- nullptr, g_watch_size, 0, eArgTypeByteSize,
+ nullptr, OptionEnumValues(g_watch_size), 0, eArgTypeByteSize,
"Number of bytes to use to watch a region."}};
bool OptionGroupWatchpoint::IsWatchSizeSupported(uint32_t watch_size) {
- for (uint32_t i = 0; i < llvm::array_lengthof(g_watch_size); ++i) {
- if (g_watch_size[i].value == 0)
+ for (const auto& size : g_watch_size) {
+ if (0 == size.value)
break;
- if (watch_size == g_watch_size[i].value)
+ if (watch_size == size.value)
return true;
}
return false;
diff --git a/source/Interpreter/OptionValue.cpp b/source/Interpreter/OptionValue.cpp
index c3f363b05988..4e480dd5784b 100644
--- a/source/Interpreter/OptionValue.cpp
+++ b/source/Interpreter/OptionValue.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValue.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionValues.h"
#include "lldb/Utility/StringList.h"
diff --git a/source/Interpreter/OptionValueArch.cpp b/source/Interpreter/OptionValueArch.cpp
index d4f1fcb8a70a..e4f0b9dd0df0 100644
--- a/source/Interpreter/OptionValueArch.cpp
+++ b/source/Interpreter/OptionValueArch.cpp
@@ -9,15 +9,11 @@
#include "lldb/Interpreter/OptionValueArch.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Interpreter/OptionValueArgs.cpp b/source/Interpreter/OptionValueArgs.cpp
index 26e438548ea3..4fa9e187668d 100644
--- a/source/Interpreter/OptionValueArgs.cpp
+++ b/source/Interpreter/OptionValueArgs.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueArgs.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Args.h"
using namespace lldb;
diff --git a/source/Interpreter/OptionValueArray.cpp b/source/Interpreter/OptionValueArray.cpp
index d3fd1cb5db48..d755fa2fddb9 100644
--- a/source/Interpreter/OptionValueArray.cpp
+++ b/source/Interpreter/OptionValueArray.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueArray.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
@@ -31,13 +27,17 @@ void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
strm.Printf("(%s)", GetTypeAsCString());
}
if (dump_mask & eDumpOptionValue) {
- if (dump_mask & eDumpOptionType)
- strm.Printf(" =%s", (m_values.size() > 0) ? "\n" : "");
- strm.IndentMore();
+ const bool one_line = dump_mask & eDumpOptionCommand;
const uint32_t size = m_values.size();
+ if (dump_mask & eDumpOptionType)
+ strm.Printf(" =%s", (m_values.size() > 0 && !one_line) ? "\n" : "");
+ if (!one_line)
+ strm.IndentMore();
for (uint32_t i = 0; i < size; ++i) {
- strm.Indent();
- strm.Printf("[%u]: ", i);
+ if (!one_line) {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ }
const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
switch (array_element_type) {
default:
@@ -63,10 +63,16 @@ void OptionValueArray::DumpValue(const ExecutionContext *exe_ctx, Stream &strm,
extra_dump_options);
break;
}
- if (i < (size - 1))
- strm.EOL();
+
+ if (!one_line) {
+ if (i < (size - 1))
+ strm.EOL();
+ } else {
+ strm << ' ';
+ }
}
- strm.IndentLess();
+ if (!one_line)
+ strm.IndentLess();
}
}
@@ -215,7 +221,7 @@ Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) {
if (num_remove_indexes) {
// Sort and then erase in reverse so indexes are always valid
if (num_remove_indexes > 1) {
- std::sort(remove_indexes.begin(), remove_indexes.end());
+ llvm::sort(remove_indexes.begin(), remove_indexes.end());
for (std::vector<int>::const_reverse_iterator
pos = remove_indexes.rbegin(),
end = remove_indexes.rend();
diff --git a/source/Interpreter/OptionValueBoolean.cpp b/source/Interpreter/OptionValueBoolean.cpp
index 94c774d69111..a7fe10e79431 100644
--- a/source/Interpreter/OptionValueBoolean.cpp
+++ b/source/Interpreter/OptionValueBoolean.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueBoolean.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/PosixApi.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Interpreter/OptionValueChar.cpp b/source/Interpreter/OptionValueChar.cpp
index 21fe88014724..1307b47a7134 100644
--- a/source/Interpreter/OptionValueChar.cpp
+++ b/source/Interpreter/OptionValueChar.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueChar.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
diff --git a/source/Interpreter/OptionValueDictionary.cpp b/source/Interpreter/OptionValueDictionary.cpp
index 2e8a8427237b..5058064f1ca2 100644
--- a/source/Interpreter/OptionValueDictionary.cpp
+++ b/source/Interpreter/OptionValueDictionary.cpp
@@ -9,15 +9,11 @@
#include "lldb/Interpreter/OptionValueDictionary.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
-#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/OptionValueString.h"
#include "lldb/Utility/Args.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -33,16 +29,23 @@ void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx,
strm.Printf("(%s)", GetTypeAsCString());
}
if (dump_mask & eDumpOptionValue) {
+ const bool one_line = dump_mask & eDumpOptionCommand;
if (dump_mask & eDumpOptionType)
strm.PutCString(" =");
collection::iterator pos, end = m_values.end();
- strm.IndentMore();
+ if (!one_line)
+ strm.IndentMore();
for (pos = m_values.begin(); pos != end; ++pos) {
OptionValue *option_value = pos->second.get();
- strm.EOL();
+
+ if (one_line)
+ strm << ' ';
+ else
+ strm.EOL();
+
strm.Indent(pos->first.GetCString());
const uint32_t extra_dump_options = m_raw_value_dump ? eDumpOptionRaw : 0;
@@ -74,7 +77,8 @@ void OptionValueDictionary::DumpValue(const ExecutionContext *exe_ctx,
break;
}
}
- strm.IndentLess();
+ if (!one_line)
+ strm.IndentLess();
}
}
diff --git a/source/Interpreter/OptionValueEnumeration.cpp b/source/Interpreter/OptionValueEnumeration.cpp
index c7cbcab7fcc8..e65dd2b67831 100644
--- a/source/Interpreter/OptionValueEnumeration.cpp
+++ b/source/Interpreter/OptionValueEnumeration.cpp
@@ -9,17 +9,13 @@
#include "lldb/Interpreter/OptionValueEnumeration.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/StringList.h"
using namespace lldb;
using namespace lldb_private;
OptionValueEnumeration::OptionValueEnumeration(
- const OptionEnumValueElement *enumerators, enum_type value)
+ const OptionEnumValues &enumerators, enum_type value)
: OptionValue(), m_current_value(value), m_default_value(value),
m_enumerations() {
SetEnumerations(enumerators);
@@ -91,18 +87,16 @@ Status OptionValueEnumeration::SetValueFromString(llvm::StringRef value,
}
void OptionValueEnumeration::SetEnumerations(
- const OptionEnumValueElement *enumerators) {
+ const OptionEnumValues &enumerators) {
m_enumerations.Clear();
- if (enumerators) {
- for (size_t i = 0; enumerators[i].string_value != nullptr; ++i) {
- ConstString const_enumerator_name(enumerators[i].string_value);
- EnumeratorInfo enumerator_info = {enumerators[i].value,
- enumerators[i].usage};
- m_enumerations.Append(const_enumerator_name,
- enumerator_info);
- }
- m_enumerations.Sort();
+
+ for (const auto &enumerator : enumerators) {
+ ConstString const_enumerator_name(enumerator.string_value);
+ EnumeratorInfo enumerator_info = {enumerator.value, enumerator.usage};
+ m_enumerations.Append(const_enumerator_name, enumerator_info);
}
+
+ m_enumerations.Sort();
}
lldb::OptionValueSP OptionValueEnumeration::DeepCopy() const {
diff --git a/source/Interpreter/OptionValueFileSpec.cpp b/source/Interpreter/OptionValueFileSpec.cpp
index 2b93628679ce..735a7d86334d 100644
--- a/source/Interpreter/OptionValueFileSpec.cpp
+++ b/source/Interpreter/OptionValueFileSpec.cpp
@@ -9,13 +9,12 @@
#include "lldb/Interpreter/OptionValueFileSpec.h"
-#include "lldb/Core/State.h"
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Utility/Args.h"
-#include "lldb/Utility/DataBufferLLVM.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -75,7 +74,9 @@ Status OptionValueFileSpec::SetValueFromString(llvm::StringRef value,
// or whitespace.
value = value.trim("\"' \t");
m_value_was_set = true;
- m_current_value.SetFile(value.str(), m_resolve, FileSpec::Style::native);
+ m_current_value.SetFile(value.str(), FileSpec::Style::native);
+ if (m_resolve)
+ FileSystem::Instance().Resolve(m_current_value);
m_data_sp.reset();
m_data_mod_time = llvm::sys::TimePoint<>();
NotifyValueChanged();
@@ -109,10 +110,11 @@ size_t OptionValueFileSpec::AutoComplete(CommandInterpreter &interpreter,
const lldb::DataBufferSP &OptionValueFileSpec::GetFileContents() {
if (m_current_value) {
- const auto file_mod_time = FileSystem::GetModificationTime(m_current_value);
+ const auto file_mod_time = FileSystem::Instance().GetModificationTime(m_current_value);
if (m_data_sp && m_data_mod_time == file_mod_time)
return m_data_sp;
- m_data_sp = DataBufferLLVM::CreateFromPath(m_current_value.GetPath());
+ m_data_sp =
+ FileSystem::Instance().CreateDataBuffer(m_current_value.GetPath());
m_data_mod_time = file_mod_time;
}
return m_data_sp;
diff --git a/source/Interpreter/OptionValueFileSpecLIst.cpp b/source/Interpreter/OptionValueFileSpecLIst.cpp
index 7fdc3c780239..fd78bba94fef 100644
--- a/source/Interpreter/OptionValueFileSpecLIst.cpp
+++ b/source/Interpreter/OptionValueFileSpecLIst.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueFileSpecList.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
@@ -25,16 +21,24 @@ void OptionValueFileSpecList::DumpValue(const ExecutionContext *exe_ctx,
if (dump_mask & eDumpOptionType)
strm.Printf("(%s)", GetTypeAsCString());
if (dump_mask & eDumpOptionValue) {
- if (dump_mask & eDumpOptionType)
- strm.Printf(" =%s", m_current_value.GetSize() > 0 ? "\n" : "");
- strm.IndentMore();
+ const bool one_line = dump_mask & eDumpOptionCommand;
const uint32_t size = m_current_value.GetSize();
+ if (dump_mask & eDumpOptionType)
+ strm.Printf(" =%s",
+ (m_current_value.GetSize() > 0 && !one_line) ? "\n" : "");
+ if (!one_line)
+ strm.IndentMore();
for (uint32_t i = 0; i < size; ++i) {
- strm.Indent();
- strm.Printf("[%u]: ", i);
+ if (!one_line) {
+ strm.Indent();
+ strm.Printf("[%u]: ", i);
+ }
m_current_value.GetFileSpecAtIndex(i).Dump(&strm);
+ if (one_line)
+ strm << ' ';
}
- strm.IndentLess();
+ if (!one_line)
+ strm.IndentLess();
}
}
@@ -61,7 +65,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
count);
} else {
for (size_t i = 1; i < argc; ++i, ++idx) {
- FileSpec file(args.GetArgumentAtIndex(i), false);
+ FileSpec file(args.GetArgumentAtIndex(i));
if (idx < count)
m_current_value.Replace(idx, file);
else
@@ -83,7 +87,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
if (argc > 0) {
m_value_was_set = true;
for (size_t i = 0; i < argc; ++i) {
- FileSpec file(args.GetArgumentAtIndex(i), false);
+ FileSpec file(args.GetArgumentAtIndex(i));
m_current_value.Append(file);
}
NotifyValueChanged();
@@ -107,7 +111,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
if (op == eVarSetOperationInsertAfter)
++idx;
for (size_t i = 1; i < argc; ++i, ++idx) {
- FileSpec file(args.GetArgumentAtIndex(i), false);
+ FileSpec file(args.GetArgumentAtIndex(i));
m_current_value.Insert(idx, file);
}
NotifyValueChanged();
@@ -136,7 +140,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value,
size_t num_remove_indexes = remove_indexes.size();
if (num_remove_indexes) {
// Sort and then erase in reverse so indexes are always valid
- std::sort(remove_indexes.begin(), remove_indexes.end());
+ llvm::sort(remove_indexes.begin(), remove_indexes.end());
for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
m_current_value.Remove(j);
}
diff --git a/source/Interpreter/OptionValueFormat.cpp b/source/Interpreter/OptionValueFormat.cpp
index 1837804a4622..945d8bd33615 100644
--- a/source/Interpreter/OptionValueFormat.cpp
+++ b/source/Interpreter/OptionValueFormat.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueFormat.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Interpreter/OptionValueFormatEntity.cpp b/source/Interpreter/OptionValueFormatEntity.cpp
index ce1a84e8dece..18783625b86f 100644
--- a/source/Interpreter/OptionValueFormatEntity.cpp
+++ b/source/Interpreter/OptionValueFormatEntity.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueFormatEntity.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Utility/Stream.h"
@@ -41,14 +37,30 @@ bool OptionValueFormatEntity::Clear() {
return true;
}
+static void EscapeBackticks(llvm::StringRef str, std::string &dst) {
+ dst.clear();
+ dst.reserve(str.size());
+
+ for (size_t i = 0, e = str.size(); i != e; ++i) {
+ char c = str[i];
+ if (c == '`') {
+ if (i == 0 || str[i - 1] != '\\')
+ dst += '\\';
+ }
+ dst += c;
+ }
+}
+
void OptionValueFormatEntity::DumpValue(const ExecutionContext *exe_ctx,
Stream &strm, uint32_t dump_mask) {
if (dump_mask & eDumpOptionType)
strm.Printf("(%s)", GetTypeAsCString());
if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
- strm.PutCString(" = \"");
- strm << m_current_format.c_str() << '"';
+ strm.PutCString(" = ");
+ std::string escaped;
+ EscapeBackticks(m_current_format, escaped);
+ strm << '"' << escaped << '"';
}
}
diff --git a/source/Interpreter/OptionValueLanguage.cpp b/source/Interpreter/OptionValueLanguage.cpp
index 1a82329bf0f3..c6e168d66b4f 100644
--- a/source/Interpreter/OptionValueLanguage.cpp
+++ b/source/Interpreter/OptionValueLanguage.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueLanguage.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/DataFormatters/FormatManager.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/Args.h"
@@ -28,7 +24,8 @@ void OptionValueLanguage::DumpValue(const ExecutionContext *exe_ctx,
if (dump_mask & eDumpOptionValue) {
if (dump_mask & eDumpOptionType)
strm.PutCString(" = ");
- strm.PutCString(Language::GetNameForLanguageType(m_current_value));
+ if (m_current_value != eLanguageTypeUnknown)
+ strm.PutCString(Language::GetNameForLanguageType(m_current_value));
}
}
diff --git a/source/Interpreter/OptionValuePathMappings.cpp b/source/Interpreter/OptionValuePathMappings.cpp
index 8390a8cf5aba..11ec739c5bb9 100644
--- a/source/Interpreter/OptionValuePathMappings.cpp
+++ b/source/Interpreter/OptionValuePathMappings.cpp
@@ -9,10 +9,7 @@
#include "lldb/Interpreter/OptionValuePathMappings.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/FileSpec.h"
@@ -23,7 +20,7 @@ using namespace lldb_private;
namespace {
static bool VerifyPathExists(const char *path) {
if (path && path[0])
- return FileSpec(path, false).Exists();
+ return FileSystem::Instance().Exists(path);
else
return false;
}
@@ -180,7 +177,7 @@ Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value,
size_t num_remove_indexes = remove_indexes.size();
if (num_remove_indexes) {
// Sort and then erase in reverse so indexes are always valid
- std::sort(remove_indexes.begin(), remove_indexes.end());
+ llvm::sort(remove_indexes.begin(), remove_indexes.end());
for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) {
m_path_mappings.Remove(j, m_notify_changes);
}
diff --git a/source/Interpreter/OptionValueProperties.cpp b/source/Interpreter/OptionValueProperties.cpp
index c1887f34b712..327d26b09ebb 100644
--- a/source/Interpreter/OptionValueProperties.cpp
+++ b/source/Interpreter/OptionValueProperties.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueProperties.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Flags.h"
#include "lldb/Core/UserSettingsController.h"
@@ -42,7 +38,7 @@ OptionValueProperties::OptionValueProperties(
for (size_t i = 0; i < num_properties; ++i) {
// Duplicate any values that are not global when constructing properties
// from a global copy
- if (m_properties[i].IsGlobal() == false) {
+ if (!m_properties[i].IsGlobal()) {
lldb::OptionValueSP new_value_sp(m_properties[i].GetValue()->DeepCopy());
m_properties[i].SetOptionValue(new_value_sp);
}
@@ -53,9 +49,9 @@ size_t OptionValueProperties::GetNumProperties() const {
return m_properties.size();
}
-void OptionValueProperties::Initialize(const PropertyDefinition *defs) {
- for (size_t i = 0; defs[i].name; ++i) {
- Property property(defs[i]);
+void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
+ for (const auto &definition : defs) {
+ Property property(definition);
assert(property.IsValid());
m_name_to_index.Append(ConstString(property.GetName()), m_properties.size());
property.GetValue()->SetParent(shared_from_this());
@@ -216,7 +212,7 @@ Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
else {
// Don't set an error if the path contained .experimental. - those are
// allowed to be missing and should silently fail.
- if (name_contains_experimental == false && error.AsCString() == nullptr) {
+ if (!name_contains_experimental && error.AsCString() == nullptr) {
error.SetErrorStringWithFormat("invalid value path '%s'", name.str().c_str());
}
}
diff --git a/source/Interpreter/OptionValueRegex.cpp b/source/Interpreter/OptionValueRegex.cpp
index aee8f97db163..3c06ff3957b0 100644
--- a/source/Interpreter/OptionValueRegex.cpp
+++ b/source/Interpreter/OptionValueRegex.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueRegex.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Stream.h"
using namespace lldb;
diff --git a/source/Interpreter/OptionValueSInt64.cpp b/source/Interpreter/OptionValueSInt64.cpp
index ddd1b9662ca3..c087c3ee24be 100644
--- a/source/Interpreter/OptionValueSInt64.cpp
+++ b/source/Interpreter/OptionValueSInt64.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueSInt64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Interpreter/OptionValueString.cpp b/source/Interpreter/OptionValueString.cpp
index 8383b531270b..c89a0c6bf404 100644
--- a/source/Interpreter/OptionValueString.cpp
+++ b/source/Interpreter/OptionValueString.cpp
@@ -10,10 +10,6 @@
#include "lldb/Interpreter/OptionValueString.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Interpreter/OptionValueUInt64.cpp b/source/Interpreter/OptionValueUInt64.cpp
index c8db1bd532c6..053b5798880e 100644
--- a/source/Interpreter/OptionValueUInt64.cpp
+++ b/source/Interpreter/OptionValueUInt64.cpp
@@ -10,10 +10,6 @@
#include "lldb/Interpreter/OptionValueUInt64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Interpreter/OptionValueUUID.cpp b/source/Interpreter/OptionValueUUID.cpp
index 355e07bb2b5f..5518a0574112 100644
--- a/source/Interpreter/OptionValueUUID.cpp
+++ b/source/Interpreter/OptionValueUUID.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/OptionValueUUID.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Interpreter/Options.cpp b/source/Interpreter/Options.cpp
index c9567e91f6b8..c6357399a7e2 100644
--- a/source/Interpreter/Options.cpp
+++ b/source/Interpreter/Options.cpp
@@ -9,15 +9,11 @@
#include "lldb/Interpreter/Options.h"
-// C Includes
-// C++ Includes
#include <algorithm>
#include <bitset>
#include <map>
#include <set>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -461,7 +457,7 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
}
}
- if (options.empty() == false) {
+ if (!options.empty()) {
// We have some required options with no arguments
strm.PutCString(" -");
for (i = 0; i < 2; ++i)
@@ -480,14 +476,14 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
if (def.usage_mask & opt_set_mask && isprint8(def.short_option)) {
// Add current option to the end of out_stream.
- if (def.required == false &&
+ if (!def.required &&
def.option_has_arg == OptionParser::eNoArgument) {
options.insert(def.short_option);
}
}
}
- if (options.empty() == false) {
+ if (!options.empty()) {
// We have some required options with no arguments
strm.PutCString(" [-");
for (i = 0; i < 2; ++i)
@@ -601,15 +597,17 @@ void Options::GenerateOptionUsage(Stream &strm, CommandObject *cmd,
if (opt_defs[i].usage_text)
OutputFormattedUsageText(strm, opt_defs[i], screen_width);
- if (opt_defs[i].enum_values != nullptr) {
+ if (!opt_defs[i].enum_values.empty()) {
strm.Indent();
strm.Printf("Values: ");
- for (int k = 0; opt_defs[i].enum_values[k].string_value != nullptr;
- k++) {
- if (k == 0)
- strm.Printf("%s", opt_defs[i].enum_values[k].string_value);
+ bool is_first = true;
+ for (const auto &enum_value : opt_defs[i].enum_values) {
+ if (is_first) {
+ strm.Printf("%s", enum_value.string_value);
+ is_first = false;
+ }
else
- strm.Printf(" | %s", opt_defs[i].enum_values[k].string_value);
+ strm.Printf(" | %s", enum_value.string_value);
}
strm.EOL();
}
@@ -770,17 +768,18 @@ bool Options::HandleOptionArgumentCompletion(
// See if this is an enumeration type option, and if so complete it here:
- OptionEnumValueElement *enum_values = opt_defs[opt_defs_index].enum_values;
- if (enum_values != nullptr) {
+ const auto &enum_values = opt_defs[opt_defs_index].enum_values;
+ if (!enum_values.empty()) {
bool return_value = false;
std::string match_string(
request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos),
request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos) +
request.GetCursorCharPosition());
- for (int i = 0; enum_values[i].string_value != nullptr; i++) {
- if (strstr(enum_values[i].string_value, match_string.c_str()) ==
- enum_values[i].string_value) {
- request.AddCompletion(enum_values[i].string_value);
+
+ for (const auto &enum_value : enum_values) {
+ if (strstr(enum_value.string_value, match_string.c_str()) ==
+ enum_value.string_value) {
+ request.AddCompletion(enum_value.string_value);
return_value = true;
}
}
@@ -828,7 +827,7 @@ bool Options::HandleOptionArgumentCompletion(
const char *module_name =
request.GetParsedLine().GetArgumentAtIndex(cur_arg_pos);
if (module_name) {
- FileSpec module_spec(module_name, false);
+ FileSpec module_spec(module_name);
lldb::TargetSP target_sp =
interpreter.GetDebugger().GetSelectedTarget();
// Search filters require a target...
diff --git a/source/Interpreter/Property.cpp b/source/Interpreter/Property.cpp
index 369029bc570d..5f1022347cf4 100644
--- a/source/Interpreter/Property.cpp
+++ b/source/Interpreter/Property.cpp
@@ -9,10 +9,6 @@
#include "lldb/Interpreter/Property.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -102,8 +98,10 @@ Property::Property(const PropertyDefinition &definition)
// "definition.default_uint_value" represents if the
// "definition.default_cstr_value" should be resolved or not
const bool resolve = definition.default_uint_value != 0;
- m_value_sp.reset(new OptionValueFileSpec(
- FileSpec(definition.default_cstr_value, resolve), resolve));
+ FileSpec file_spec = FileSpec(definition.default_cstr_value);
+ if (resolve)
+ FileSystem::Instance().Resolve(file_spec);
+ m_value_sp.reset(new OptionValueFileSpec(file_spec, resolve));
break;
}
@@ -233,7 +231,10 @@ void Property::Dump(const ExecutionContext *exe_ctx, Stream &strm,
uint32_t dump_mask) const {
if (m_value_sp) {
const bool dump_desc = dump_mask & OptionValue::eDumpOptionDescription;
+ const bool dump_cmd = dump_mask & OptionValue::eDumpOptionCommand;
const bool transparent = m_value_sp->ValueIsTransparent();
+ if (dump_cmd && !transparent)
+ strm << "settings set -f ";
if (dump_desc || !transparent) {
if ((dump_mask & OptionValue::eDumpOptionName) && m_name) {
DumpQualifiedName(strm);
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
index e0e293d7ae68..9055660f2d6c 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -9,19 +9,13 @@
#include "ABIMacOSX_arm.h"
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -30,6 +24,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Utility/ARMDefines.h"
@@ -1327,16 +1323,13 @@ size_t ABIMacOSX_arm::GetRedZoneSize() const { return 0; }
ABISP
ABIMacOSX_arm::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
if (vendor_type == llvm::Triple::Apple) {
if ((arch_type == llvm::Triple::arm) ||
(arch_type == llvm::Triple::thumb)) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABIMacOSX_arm(process_sp));
- return g_abi_sp;
+ return ABISP(new ABIMacOSX_arm(process_sp));
}
}
@@ -1477,14 +1470,16 @@ bool ABIMacOSX_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
if (compiler_type) {
bool is_signed = false;
size_t bit_width = 0;
- if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- bit_width = compiler_type.GetBitSize(&thread);
- } else if (compiler_type.IsPointerOrReferenceType()) {
- bit_width = compiler_type.GetBitSize(&thread);
- } else {
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (!bit_size)
+ return false;
+ if (compiler_type.IsIntegerOrEnumerationType(is_signed))
+ bit_width = *bit_size;
+ else if (compiler_type.IsPointerOrReferenceType())
+ bit_width = *bit_size;
+ else
// We only handle integer, pointer and reference types currently...
return false;
- }
if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) {
if (value_idx < 4) {
@@ -1581,9 +1576,11 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl(
const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- size_t bit_width = compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
+ if (!bit_width)
+ return return_valobj_sp;
- switch (bit_width) {
+ switch (*bit_width) {
default:
return return_valobj_sp;
case 128:
@@ -1599,14 +1596,17 @@ ValueObjectSP ABIMacOSX_arm::GetReturnValueObjectImpl(
const RegisterInfo *r3_reg_info =
reg_ctx->GetRegisterInfoByName("r3", 0);
if (r1_reg_info && r2_reg_info && r3_reg_info) {
- const size_t byte_size = compiler_type.GetByteSize(&thread);
+ llvm::Optional<uint64_t> byte_size =
+ compiler_type.GetByteSize(&thread);
+ if (!byte_size)
+ return return_valobj_sp;
ProcessSP process_sp(thread.GetProcess());
- if (byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size +
- r2_reg_info->byte_size +
- r3_reg_info->byte_size &&
+ if (*byte_size <= r0_reg_info->byte_size + r1_reg_info->byte_size +
+ r2_reg_info->byte_size +
+ r3_reg_info->byte_size &&
process_sp) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue r0_reg_value;
RegisterValue r1_reg_value;
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
index d3c20e1e618f..94f1e31a1235 100644
--- a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABIMacOSX_arm_h_
#define liblldb_ABIMacOSX_arm_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
index 85f864ec7561..d8706c4a9cdd 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.cpp
@@ -9,18 +9,13 @@
#include "ABIMacOSX_arm64.h"
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -30,6 +25,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "Utility/ARM64_DWARF_Registers.h"
@@ -1667,15 +1664,12 @@ size_t ABIMacOSX_arm64::GetRedZoneSize() const { return 128; }
ABISP
ABIMacOSX_arm64::CreateInstance(ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
if (vendor_type == llvm::Triple::Apple) {
if (arch_type == llvm::Triple::aarch64) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABIMacOSX_arm64(process_sp));
- return g_abi_sp;
+ return ABISP(new ABIMacOSX_arm64(process_sp));
}
}
@@ -1768,90 +1762,92 @@ bool ABIMacOSX_arm64::GetArgumentValues(Thread &thread,
return false;
CompilerType value_type = value->GetCompilerType();
- if (value_type) {
- bool is_signed = false;
- size_t bit_width = 0;
- if (value_type.IsIntegerOrEnumerationType(is_signed)) {
- bit_width = value_type.GetBitSize(&thread);
- } else if (value_type.IsPointerOrReferenceType()) {
- bit_width = value_type.GetBitSize(&thread);
- } else {
- // We only handle integer, pointer and reference types currently...
- return false;
- }
+ llvm::Optional<uint64_t> bit_size = value_type.GetBitSize(&thread);
+ if (!bit_size)
+ return false;
- if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) {
- if (value_idx < 8) {
- // Arguments 1-6 are in x0-x5...
- const RegisterInfo *reg_info = nullptr;
- // Search by generic ID first, then fall back to by name
- uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
- eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
- if (arg_reg_num != LLDB_INVALID_REGNUM) {
- reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num);
- } else {
- switch (value_idx) {
- case 0:
- reg_info = reg_ctx->GetRegisterInfoByName("x0");
- break;
- case 1:
- reg_info = reg_ctx->GetRegisterInfoByName("x1");
- break;
- case 2:
- reg_info = reg_ctx->GetRegisterInfoByName("x2");
- break;
- case 3:
- reg_info = reg_ctx->GetRegisterInfoByName("x3");
- break;
- case 4:
- reg_info = reg_ctx->GetRegisterInfoByName("x4");
- break;
- case 5:
- reg_info = reg_ctx->GetRegisterInfoByName("x5");
- break;
- case 6:
- reg_info = reg_ctx->GetRegisterInfoByName("x6");
- break;
- case 7:
- reg_info = reg_ctx->GetRegisterInfoByName("x7");
- break;
- }
+ bool is_signed = false;
+ size_t bit_width = 0;
+ if (value_type.IsIntegerOrEnumerationType(is_signed)) {
+ bit_width = *bit_size;
+ } else if (value_type.IsPointerOrReferenceType()) {
+ bit_width = *bit_size;
+ } else {
+ // We only handle integer, pointer and reference types currently...
+ return false;
+ }
+
+ if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8)) {
+ if (value_idx < 8) {
+ // Arguments 1-6 are in x0-x5...
+ const RegisterInfo *reg_info = nullptr;
+ // Search by generic ID first, then fall back to by name
+ uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
+ if (arg_reg_num != LLDB_INVALID_REGNUM) {
+ reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num);
+ } else {
+ switch (value_idx) {
+ case 0:
+ reg_info = reg_ctx->GetRegisterInfoByName("x0");
+ break;
+ case 1:
+ reg_info = reg_ctx->GetRegisterInfoByName("x1");
+ break;
+ case 2:
+ reg_info = reg_ctx->GetRegisterInfoByName("x2");
+ break;
+ case 3:
+ reg_info = reg_ctx->GetRegisterInfoByName("x3");
+ break;
+ case 4:
+ reg_info = reg_ctx->GetRegisterInfoByName("x4");
+ break;
+ case 5:
+ reg_info = reg_ctx->GetRegisterInfoByName("x5");
+ break;
+ case 6:
+ reg_info = reg_ctx->GetRegisterInfoByName("x6");
+ break;
+ case 7:
+ reg_info = reg_ctx->GetRegisterInfoByName("x7");
+ break;
}
+ }
- if (reg_info) {
- RegisterValue reg_value;
+ if (reg_info) {
+ RegisterValue reg_value;
- if (reg_ctx->ReadRegister(reg_info, reg_value)) {
- if (is_signed)
- reg_value.SignExtend(bit_width);
- if (!reg_value.GetScalarValue(value->GetScalar()))
- return false;
- continue;
- }
- }
- return false;
- } else {
- if (sp == 0) {
- // Read the stack pointer if we already haven't read it
- sp = reg_ctx->GetSP(0);
- if (sp == 0)
+ if (reg_ctx->ReadRegister(reg_info, reg_value)) {
+ if (is_signed)
+ reg_value.SignExtend(bit_width);
+ if (!reg_value.GetScalarValue(value->GetScalar()))
return false;
+ continue;
}
-
- // Arguments 5 on up are on the stack
- const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8;
- Status error;
- if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(
- sp, arg_byte_size, is_signed, value->GetScalar(), error))
+ }
+ return false;
+ } else {
+ if (sp == 0) {
+ // Read the stack pointer if we already haven't read it
+ sp = reg_ctx->GetSP(0);
+ if (sp == 0)
return false;
+ }
- sp += arg_byte_size;
- // Align up to the next 8 byte boundary if needed
- if (sp % 8) {
- sp >>= 3;
- sp += 1;
- sp <<= 3;
- }
+ // Arguments 5 on up are on the stack
+ const uint32_t arg_byte_size = (bit_width + (8 - 1)) / 8;
+ Status error;
+ if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(
+ sp, arg_byte_size, is_signed, value->GetScalar(), error))
+ return false;
+
+ sp += arg_byte_size;
+ // Align up to the next 8 byte boundary if needed
+ if (sp % 8) {
+ sp >>= 3;
+ sp += 1;
+ sp <<= 3;
}
}
}
@@ -2115,13 +2111,12 @@ static bool LoadValueFromConsecutiveGPRRegisters(
uint32_t &NGRN, // NGRN (see ABI documentation)
uint32_t &NSRN, // NSRN (see ABI documentation)
DataExtractor &data) {
- const size_t byte_size = value_type.GetByteSize(nullptr);
-
- if (byte_size == 0)
+ llvm::Optional<uint64_t> byte_size = value_type.GetByteSize(nullptr);
+ if (!byte_size || *byte_size == 0)
return false;
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
Status error;
@@ -2133,7 +2128,9 @@ static bool LoadValueFromConsecutiveGPRRegisters(
if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) {
if (!base_type)
return false;
- const size_t base_byte_size = base_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> base_byte_size = base_type.GetByteSize(nullptr);
+ if (!base_byte_size)
+ return false;
uint32_t data_offset = 0;
for (uint32_t i = 0; i < homogeneous_count; ++i) {
@@ -2144,7 +2141,7 @@ static bool LoadValueFromConsecutiveGPRRegisters(
if (reg_info == nullptr)
return false;
- if (base_byte_size > reg_info->byte_size)
+ if (*base_byte_size > reg_info->byte_size)
return false;
RegisterValue reg_value;
@@ -2153,11 +2150,11 @@ static bool LoadValueFromConsecutiveGPRRegisters(
return false;
// Make sure we have enough room in "heap_data_ap"
- if ((data_offset + base_byte_size) <= heap_data_ap->GetByteSize()) {
+ if ((data_offset + *base_byte_size) <= heap_data_ap->GetByteSize()) {
const size_t bytes_copied = reg_value.GetAsMemoryData(
- reg_info, heap_data_ap->GetBytes() + data_offset, base_byte_size,
+ reg_info, heap_data_ap->GetBytes() + data_offset, *base_byte_size,
byte_order, error);
- if (bytes_copied != base_byte_size)
+ if (bytes_copied != *base_byte_size)
return false;
data_offset += bytes_copied;
++NSRN;
@@ -2172,10 +2169,10 @@ static bool LoadValueFromConsecutiveGPRRegisters(
}
const size_t max_reg_byte_size = 16;
- if (byte_size <= max_reg_byte_size) {
- size_t bytes_left = byte_size;
+ if (*byte_size <= max_reg_byte_size) {
+ size_t bytes_left = *byte_size;
uint32_t data_offset = 0;
- while (data_offset < byte_size) {
+ while (data_offset < *byte_size) {
if (NGRN >= 8)
return false;
@@ -2267,7 +2264,10 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
@@ -2276,7 +2276,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
// Extract the register context so we can read arguments from registers
- if (byte_size <= 8) {
+ if (*byte_size <= 8) {
const RegisterInfo *x0_reg_info =
reg_ctx->GetRegisterInfoByName("x0", 0);
if (x0_reg_info) {
@@ -2284,7 +2284,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info,
0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
case 16: // uint128_t
@@ -2294,10 +2294,10 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
reg_ctx->GetRegisterInfoByName("x1", 0);
if (x1_reg_info) {
- if (byte_size <=
+ if (*byte_size <=
x0_reg_info->byte_size + x1_reg_info->byte_size) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order =
exe_ctx.GetProcessRef().GetByteOrder();
RegisterValue x0_reg_value;
@@ -2362,7 +2362,7 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
if (type_flags & eTypeIsComplex) {
// Don't handle complex yet.
} else {
- if (byte_size <= sizeof(long double)) {
+ if (*byte_size <= sizeof(long double)) {
const RegisterInfo *v0_reg_info =
reg_ctx->GetRegisterInfoByName("v0", 0);
RegisterValue v0_value;
@@ -2370,13 +2370,13 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
DataExtractor data;
if (v0_value.GetData(data)) {
lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
value.GetScalar() = data.GetFloat(&offset);
success = true;
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
value.GetScalar() = data.GetDouble(&offset);
success = true;
- } else if (byte_size == sizeof(long double)) {
+ } else if (*byte_size == sizeof(long double)) {
value.GetScalar() = data.GetLongDouble(&offset);
success = true;
}
@@ -2390,14 +2390,14 @@ ValueObjectSP ABIMacOSX_arm64::GetReturnValueObjectImpl(
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
- if (byte_size > 0) {
+ if (*byte_size > 0) {
const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
if (v0_info) {
- if (byte_size <= v0_info->byte_size) {
+ if (*byte_size <= v0_info->byte_size) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
RegisterValue reg_value;
if (reg_ctx->ReadRegister(v0_info, reg_value)) {
diff --git a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
index 2dd7337542db..7a9444c775f4 100644
--- a/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
+++ b/source/Plugins/ABI/MacOSX-arm64/ABIMacOSX_arm64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABIMacOSX_arm64_h_
#define liblldb_ABIMacOSX_arm64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
index 9e5e39ec28ca..a297bd1473b2 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -9,19 +9,13 @@
#include "ABIMacOSX_i386.h"
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
@@ -29,6 +23,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -714,13 +710,10 @@ size_t ABIMacOSX_i386::GetRedZoneSize() const { return 0; }
ABISP
ABIMacOSX_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
if ((arch.GetTriple().getArch() == llvm::Triple::x86) &&
(arch.GetTriple().isMacOSX() || arch.GetTriple().isiOS() ||
arch.GetTriple().isWatchOS())) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABIMacOSX_i386(process_sp));
- return g_abi_sp;
+ return ABISP(new ABIMacOSX_i386(process_sp));
}
return ABISP();
}
@@ -831,18 +824,15 @@ bool ABIMacOSX_i386::GetArgumentValues(Thread &thread,
// We currently only support extracting values with Clang QualTypes. Do we
// care about others?
CompilerType compiler_type(value->GetCompilerType());
- if (compiler_type) {
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (bit_size) {
bool is_signed;
-
- if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- ReadIntegerArgument(value->GetScalar(),
- compiler_type.GetBitSize(&thread), is_signed,
+ if (compiler_type.IsIntegerOrEnumerationType(is_signed))
+ ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
thread.GetProcess().get(), current_stack_argument);
- } else if (compiler_type.IsPointerType()) {
- ReadIntegerArgument(value->GetScalar(),
- compiler_type.GetBitSize(&thread), false,
+ else if (compiler_type.IsPointerType())
+ ReadIntegerArgument(value->GetScalar(), *bit_size, false,
thread.GetProcess().get(), current_stack_argument);
- }
}
}
@@ -943,14 +933,15 @@ ABIMacOSX_i386::GetReturnValueObjectImpl(Thread &thread,
bool is_signed;
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- size_t bit_width = compiler_type.GetBitSize(&thread);
-
+ llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
+ if (!bit_width)
+ return return_valobj_sp;
unsigned eax_id =
reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
unsigned edx_id =
reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
- switch (bit_width) {
+ switch (*bit_width) {
default:
case 128:
// Scalar can't hold 128-bit literals, so we don't handle this
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
index e026e3248672..536132d02586 100644
--- a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABIMacOSX_i386_h_
#define liblldb_ABIMacOSX_i386_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Value.h"
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
index af7ac469e6db..b93a8525010c 100644
--- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.cpp
@@ -9,19 +9,13 @@
#include "ABISysV_arm.h"
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -30,6 +24,8 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Utility/ARMDefines.h"
@@ -1328,16 +1324,13 @@ size_t ABISysV_arm::GetRedZoneSize() const { return 0; }
ABISP
ABISysV_arm::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
if (vendor_type != llvm::Triple::Apple) {
if ((arch_type == llvm::Triple::arm) ||
(arch_type == llvm::Triple::thumb)) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_arm(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_arm(process_sp));
}
}
@@ -1447,10 +1440,7 @@ bool ABISysV_arm::PrepareTrivialCall(Thread &thread, addr_t sp,
~1ull; // clear bit zero since the CPSR will take care of the mode for us
// Set "pc" to the address requested
- if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, function_addr))
- return false;
-
- return true;
+ return reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, function_addr);
}
bool ABISysV_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
@@ -1481,10 +1471,10 @@ bool ABISysV_arm::GetArgumentValues(Thread &thread, ValueList &values) const {
if (compiler_type) {
bool is_signed = false;
size_t bit_width = 0;
- if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- bit_width = compiler_type.GetBitSize(&thread);
- } else if (compiler_type.IsPointerOrReferenceType()) {
- bit_width = compiler_type.GetBitSize(&thread);
+ if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
+ compiler_type.IsPointerOrReferenceType()) {
+ if (llvm::Optional<uint64_t> size = compiler_type.GetBitSize(&thread))
+ bit_width = *size;
} else {
// We only handle integer, pointer and reference types currently...
return false;
@@ -1590,11 +1580,13 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
const RegisterInfo *r0_reg_info =
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
- size_t bit_width = compiler_type.GetBitSize(&thread);
- size_t byte_size = compiler_type.GetByteSize(&thread);
+ llvm::Optional<uint64_t> bit_width = compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> byte_size = compiler_type.GetByteSize(&thread);
+ if (!bit_width || !byte_size)
+ return return_valobj_sp;
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- switch (bit_width) {
+ switch (*bit_width) {
default:
return return_valobj_sp;
case 64: {
@@ -1641,28 +1633,28 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
UINT32_MAX;
value.GetScalar() = ptr;
} else if (compiler_type.IsVectorType(nullptr, nullptr)) {
- if (IsArmHardFloat(thread) && (byte_size == 8 || byte_size == 16)) {
+ if (IsArmHardFloat(thread) && (*byte_size == 8 || *byte_size == 16)) {
is_vfp_candidate = true;
vfp_byte_size = 8;
- vfp_count = (byte_size == 8 ? 1 : 2);
- } else if (byte_size <= 16) {
+ vfp_count = (*byte_size == 8 ? 1 : 2);
+ } else if (*byte_size <= 16) {
DataBufferHeap buffer(16, 0);
uint32_t *buffer_ptr = (uint32_t *)buffer.GetBytes();
- for (uint32_t i = 0; 4 * i < byte_size; ++i) {
+ for (uint32_t i = 0; 4 * i < *byte_size; ++i) {
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
buffer_ptr[i] =
reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX;
}
- value.SetBytes(buffer.GetBytes(), byte_size);
+ value.SetBytes(buffer.GetBytes(), *byte_size);
} else {
- if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
+ if (!GetReturnValuePassedInMemory(thread, reg_ctx, *byte_size, value))
return return_valobj_sp;
}
} else if (compiler_type.IsFloatingPointType(float_count, is_complex)) {
if (float_count == 1 && !is_complex) {
- switch (bit_width) {
+ switch (*bit_width) {
default:
return return_valobj_sp;
case 64: {
@@ -1710,9 +1702,9 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
} else if (is_complex && float_count == 2) {
if (IsArmHardFloat(thread)) {
is_vfp_candidate = true;
- vfp_byte_size = byte_size / 2;
+ vfp_byte_size = *byte_size / 2;
vfp_count = 2;
- } else if (!GetReturnValuePassedInMemory(thread, reg_ctx, bit_width / 8,
+ } else if (!GetReturnValuePassedInMemory(thread, reg_ctx, *bit_width / 8,
value))
return return_valobj_sp;
} else
@@ -1725,19 +1717,21 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
compiler_type.IsHomogeneousAggregate(&base_type);
if (homogeneous_count > 0 && homogeneous_count <= 4) {
+ llvm::Optional<uint64_t> base_byte_size =
+ base_type.GetByteSize(nullptr);
if (base_type.IsVectorType(nullptr, nullptr)) {
- uint64_t base_byte_size = base_type.GetByteSize(nullptr);
- if (base_byte_size == 8 || base_byte_size == 16) {
+ if (base_byte_size &&
+ (*base_byte_size == 8 || *base_byte_size == 16)) {
is_vfp_candidate = true;
vfp_byte_size = 8;
- vfp_count =
- (base_type.GetByteSize(nullptr) == 8 ? homogeneous_count
- : homogeneous_count * 2);
+ vfp_count = (*base_byte_size == 8 ? homogeneous_count
+ : homogeneous_count * 2);
}
} else if (base_type.IsFloatingPointType(float_count, is_complex)) {
if (float_count == 1 && !is_complex) {
is_vfp_candidate = true;
- vfp_byte_size = base_type.GetByteSize(nullptr);
+ if (base_byte_size)
+ vfp_byte_size = *base_byte_size;
vfp_count = homogeneous_count;
}
}
@@ -1752,12 +1746,14 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
compiler_type.GetFieldAtIndex(index, name, NULL, NULL, NULL);
if (base_type.IsFloatingPointType(float_count, is_complex)) {
+ llvm::Optional<uint64_t> base_byte_size =
+ base_type.GetByteSize(nullptr);
if (float_count == 2 && is_complex) {
- if (index != 0 &&
- vfp_byte_size != base_type.GetByteSize(nullptr))
+ if (index != 0 && base_byte_size &&
+ vfp_byte_size != *base_byte_size)
break;
- else
- vfp_byte_size = base_type.GetByteSize(nullptr);
+ else if (base_byte_size)
+ vfp_byte_size = *base_byte_size;
} else
break;
} else
@@ -1773,13 +1769,13 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
}
}
- if (byte_size <= 4) {
+ if (*byte_size <= 4) {
RegisterValue r0_reg_value;
uint32_t raw_value =
reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
- value.SetBytes(&raw_value, byte_size);
+ value.SetBytes(&raw_value, *byte_size);
} else if (!is_vfp_candidate) {
- if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
+ if (!GetReturnValuePassedInMemory(thread, reg_ctx, *byte_size, value))
return return_valobj_sp;
}
} else {
@@ -1791,7 +1787,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
ProcessSP process_sp(thread.GetProcess());
ByteOrder byte_order = process_sp->GetByteOrder();
- DataBufferSP data_sp(new DataBufferHeap(byte_size, 0));
+ DataBufferSP data_sp(new DataBufferHeap(*byte_size, 0));
uint32_t data_offset = 0;
for (uint32_t reg_index = 0; reg_index < vfp_count; reg_index++) {
@@ -1826,7 +1822,7 @@ ValueObjectSP ABISysV_arm::GetReturnValueObjectImpl(
}
}
- if (data_offset == byte_size) {
+ if (data_offset == *byte_size) {
DataExtractor data;
data.SetByteOrder(byte_order);
data.SetAddressByteSize(process_sp->GetAddressByteSize());
diff --git a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
index f046968c213d..7f2d658541ab 100644
--- a/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
+++ b/source/Plugins/ABI/SysV-arm/ABISysV_arm.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_arm_h_
#define liblldb_ABISysV_arm_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
index 2c221689954c..dd3f47303be5 100644
--- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.cpp
@@ -9,19 +9,13 @@
#include "ABISysV_arm64.h"
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -31,6 +25,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "Utility/ARM64_DWARF_Registers.h"
@@ -1671,15 +1667,12 @@ size_t ABISysV_arm64::GetRedZoneSize() const { return 128; }
ABISP
ABISysV_arm64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
const llvm::Triple::VendorType vendor_type = arch.GetTriple().getVendor();
if (vendor_type != llvm::Triple::Apple) {
if (arch_type == llvm::Triple::aarch64) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_arm64(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_arm64(process_sp));
}
}
@@ -1774,10 +1767,13 @@ bool ABISysV_arm64::GetArgumentValues(Thread &thread, ValueList &values) const {
if (value_type) {
bool is_signed = false;
size_t bit_width = 0;
+ llvm::Optional<uint64_t> bit_size = value_type.GetBitSize(&thread);
+ if (!bit_size)
+ return false;
if (value_type.IsIntegerOrEnumerationType(is_signed)) {
- bit_width = value_type.GetBitSize(&thread);
+ bit_width = *bit_size;
} else if (value_type.IsPointerOrReferenceType()) {
- bit_width = value_type.GetBitSize(&thread);
+ bit_width = *bit_size;
} else {
// We only handle integer, pointer and reference types currently...
return false;
@@ -2090,13 +2086,13 @@ static bool LoadValueFromConsecutiveGPRRegisters(
uint32_t &NGRN, // NGRN (see ABI documentation)
uint32_t &NSRN, // NSRN (see ABI documentation)
DataExtractor &data) {
- const size_t byte_size = value_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size = value_type.GetByteSize(nullptr);
- if (byte_size == 0)
+ if (byte_size || *byte_size == 0)
return false;
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
Status error;
@@ -2108,7 +2104,9 @@ static bool LoadValueFromConsecutiveGPRRegisters(
if (NSRN < 8 && (8 - NSRN) >= homogeneous_count) {
if (!base_type)
return false;
- const size_t base_byte_size = base_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> base_byte_size = base_type.GetByteSize(nullptr);
+ if (!base_byte_size)
+ return false;
uint32_t data_offset = 0;
for (uint32_t i = 0; i < homogeneous_count; ++i) {
@@ -2119,7 +2117,7 @@ static bool LoadValueFromConsecutiveGPRRegisters(
if (reg_info == nullptr)
return false;
- if (base_byte_size > reg_info->byte_size)
+ if (*base_byte_size > reg_info->byte_size)
return false;
RegisterValue reg_value;
@@ -2128,11 +2126,11 @@ static bool LoadValueFromConsecutiveGPRRegisters(
return false;
// Make sure we have enough room in "heap_data_ap"
- if ((data_offset + base_byte_size) <= heap_data_ap->GetByteSize()) {
+ if ((data_offset + *base_byte_size) <= heap_data_ap->GetByteSize()) {
const size_t bytes_copied = reg_value.GetAsMemoryData(
- reg_info, heap_data_ap->GetBytes() + data_offset, base_byte_size,
+ reg_info, heap_data_ap->GetBytes() + data_offset, *base_byte_size,
byte_order, error);
- if (bytes_copied != base_byte_size)
+ if (bytes_copied != *base_byte_size)
return false;
data_offset += bytes_copied;
++NSRN;
@@ -2147,10 +2145,10 @@ static bool LoadValueFromConsecutiveGPRRegisters(
}
const size_t max_reg_byte_size = 16;
- if (byte_size <= max_reg_byte_size) {
- size_t bytes_left = byte_size;
+ if (*byte_size <= max_reg_byte_size) {
+ size_t bytes_left = *byte_size;
uint32_t data_offset = 0;
- while (data_offset < byte_size) {
+ while (data_offset < *byte_size) {
if (NGRN >= 8)
return false;
@@ -2235,7 +2233,10 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
if (!reg_ctx)
return return_valobj_sp;
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
if (type_flags & eTypeIsScalar || type_flags & eTypeIsPointer) {
@@ -2244,7 +2245,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
bool success = false;
if (type_flags & eTypeIsInteger || type_flags & eTypeIsPointer) {
// Extract the register context so we can read arguments from registers
- if (byte_size <= 8) {
+ if (*byte_size <= 8) {
const RegisterInfo *x0_reg_info = nullptr;
x0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
LLDB_REGNUM_GENERIC_ARG1);
@@ -2253,7 +2254,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
thread.GetRegisterContext()->ReadRegisterAsUnsigned(x0_reg_info,
0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
case 16: // uint128_t
@@ -2264,10 +2265,10 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
LLDB_REGNUM_GENERIC_ARG2);
if (x1_reg_info) {
- if (byte_size <=
+ if (*byte_size <=
x0_reg_info->byte_size + x1_reg_info->byte_size) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order =
exe_ctx.GetProcessRef().GetByteOrder();
RegisterValue x0_reg_value;
@@ -2332,7 +2333,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
if (type_flags & eTypeIsComplex) {
// Don't handle complex yet.
} else {
- if (byte_size <= sizeof(long double)) {
+ if (*byte_size <= sizeof(long double)) {
const RegisterInfo *v0_reg_info =
reg_ctx->GetRegisterInfoByName("v0", 0);
RegisterValue v0_value;
@@ -2340,13 +2341,13 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
DataExtractor data;
if (v0_value.GetData(data)) {
lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
value.GetScalar() = data.GetFloat(&offset);
success = true;
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
value.GetScalar() = data.GetDouble(&offset);
success = true;
- } else if (byte_size == sizeof(long double)) {
+ } else if (*byte_size == sizeof(long double)) {
value.GetScalar() = data.GetLongDouble(&offset);
success = true;
}
@@ -2359,13 +2360,13 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
if (success)
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
- } else if (type_flags & eTypeIsVector && byte_size <= 16) {
- if (byte_size > 0) {
+ } else if (type_flags & eTypeIsVector && *byte_size <= 16) {
+ if (*byte_size > 0) {
const RegisterInfo *v0_info = reg_ctx->GetRegisterInfoByName("v0", 0);
if (v0_info) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = exe_ctx.GetProcessRef().GetByteOrder();
RegisterValue reg_value;
if (reg_ctx->ReadRegister(v0_info, reg_value)) {
@@ -2382,7 +2383,7 @@ ValueObjectSP ABISysV_arm64::GetReturnValueObjectImpl(
}
}
} else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||
- (type_flags & eTypeIsVector && byte_size > 16)) {
+ (type_flags & eTypeIsVector && *byte_size > 16)) {
DataExtractor data;
uint32_t NGRN = 0; // Search ABI docs for NGRN
diff --git a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
index 8d23c2419bab..b36b4547e626 100644
--- a/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
+++ b/source/Plugins/ABI/SysV-arm64/ABISysV_arm64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_arm64_h_
#define liblldb_ABISysV_arm64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
index a30416cf5a8e..ca40e9a04d7c 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.cpp
@@ -9,16 +9,11 @@
#include "ABISysV_hexagon.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DerivedTypes.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,6 +27,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -1020,11 +1016,8 @@ size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; }
ABISP
ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::hexagon) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_hexagon(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_hexagon(process_sp));
}
return ABISP();
}
diff --git a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
index 5a6809371d9f..6e39c0792e2a 100644
--- a/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
+++ b/source/Plugins/ABI/SysV-hexagon/ABISysV_hexagon.h
@@ -11,10 +11,6 @@
#ifndef liblldb_ABISysV_hexagon_h_
#define liblldb_ABISysV_hexagon_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
index e7ddfccea338..3358eb8c2774 100644
--- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.cpp
@@ -8,16 +8,11 @@
#include "ABISysV_i386.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -31,6 +26,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -203,12 +199,9 @@ ABISysV_i386::GetRegisterInfoArray(uint32_t &count) {
ABISP
ABISysV_i386::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
if (arch.GetTriple().getVendor() != llvm::Triple::Apple) {
if (arch.GetTriple().getArch() == llvm::Triple::x86) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_i386(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_i386(process_sp));
}
}
return ABISP();
@@ -315,15 +308,14 @@ bool ABISysV_i386::GetArgumentValues(Thread &thread, ValueList &values) const {
// Currently: Support for extracting values with Clang QualTypes only.
CompilerType compiler_type(value->GetCompilerType());
- if (compiler_type) {
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (bit_size) {
bool is_signed;
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- ReadIntegerArgument(value->GetScalar(),
- compiler_type.GetBitSize(&thread), is_signed,
+ ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed,
thread.GetProcess().get(), current_stack_argument);
} else if (compiler_type.IsPointerType()) {
- ReadIntegerArgument(value->GetScalar(),
- compiler_type.GetBitSize(&thread), false,
+ ReadIntegerArgument(value->GetScalar(), *bit_size, false,
thread.GetProcess().get(), current_stack_argument);
}
}
@@ -521,7 +513,10 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
(type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
{
value.SetValueType(Value::eValueTypeScalar);
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
bool success = false;
if (type_flags & eTypeIsInteger) // 'Integral' except enum
@@ -535,7 +530,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
0xffffffff)
<< 32;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
@@ -591,7 +586,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsFloat) // 'Floating Point'
{
- if (byte_size <= 12) // handles float, double, long double, __float80
+ if (*byte_size <= 12) // handles float, double, long double, __float80
{
const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
RegisterValue st0_value;
@@ -602,21 +597,20 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
lldb::offset_t offset = 0;
long double value_long_double = data.GetLongDouble(&offset);
- if (byte_size == 4) // float is 4 bytes
- {
+ // float is 4 bytes.
+ if (*byte_size == 4) {
float value_float = (float)value_long_double;
value.GetScalar() = value_float;
success = true;
- } else if (byte_size == 8) // double is 8 bytes
- {
+ } else if (*byte_size == 8) {
+ // double is 8 bytes
// On Android Platform: long double is also 8 bytes It will be
// handled here only.
double value_double = (double)value_long_double;
value.GetScalar() = value_double;
success = true;
- } else if (byte_size ==
- 12) // long double and __float80 are 12 bytes on i386
- {
+ } else if (*byte_size == 12) {
+ // long double and __float80 are 12 bytes on i386.
value.GetScalar() = value_long_double;
success = true;
}
@@ -626,7 +620,7 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
if (success)
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
- } else if (byte_size == 16) // handles __float128
+ } else if (*byte_size == 16) // handles __float128
{
lldb::addr_t storage_addr = (uint32_t)(
thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) &
@@ -644,18 +638,19 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
// ToDo: Yet to be implemented
} else if (type_flags & eTypeIsVector) // 'Packed'
{
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size > 0) {
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (byte_size && *byte_size > 0) {
const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
if (vec_reg == nullptr)
vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
if (vec_reg) {
- if (byte_size <= vec_reg->byte_size) {
+ if (*byte_size <= vec_reg->byte_size) {
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue reg_value;
if (reg_ctx->ReadRegister(vec_reg, reg_value)) {
@@ -672,14 +667,14 @@ ValueObjectSP ABISysV_i386::GetReturnValueObjectSimple(
}
}
}
- } else if (byte_size <= vec_reg->byte_size * 2) {
+ } else if (*byte_size <= vec_reg->byte_size * 2) {
const RegisterInfo *vec_reg2 =
reg_ctx->GetRegisterInfoByName("xmm1", 0);
if (vec_reg2) {
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue reg_value;
RegisterValue reg_value2;
diff --git a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
index 4dce54c4f073..336a2754c6ca 100644
--- a/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
+++ b/source/Plugins/ABI/SysV-i386/ABISysV_i386.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_i386_h_
#define liblldb_ABISysV_i386_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
index ce02f8677a63..6f3d2e3b3696 100644
--- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.cpp
@@ -9,16 +9,11 @@
#include "ABISysV_mips.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,6 +27,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -560,13 +556,10 @@ size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
ABISP
ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
if ((arch_type == llvm::Triple::mips) ||
(arch_type == llvm::Triple::mipsel)) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_mips(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_mips(process_sp));
}
return ABISP();
}
@@ -819,9 +812,11 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
// In MIPS register "r2" (v0) holds the integer function return values
const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
- size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
+ if (!bit_width)
+ return return_valobj_sp;
if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- switch (bit_width) {
+ switch (*bit_width) {
default:
return return_valobj_sp;
case 64: {
@@ -880,7 +875,7 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
if (count != 1 && is_complex)
return return_valobj_sp;
- switch (bit_width) {
+ switch (*bit_width) {
default:
return return_valobj_sp;
case 32:
@@ -912,7 +907,7 @@ ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
lldb::offset_t offset = 0;
if (count == 1 && !is_complex) {
- switch (bit_width) {
+ switch (*bit_width) {
default:
return return_valobj_sp;
case 64: {
diff --git a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
index 0de8e7751fce..d23dbe9d97bd 100644
--- a/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
+++ b/source/Plugins/ABI/SysV-mips/ABISysV_mips.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_mips_h_
#define liblldb_ABISysV_mips_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
index b958abf25637..1d6738d9fda9 100644
--- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -9,16 +9,11 @@
#include "ABISysV_mips64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,6 +27,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -560,13 +556,10 @@ size_t ABISysV_mips64::GetRedZoneSize() const { return 0; }
ABISP
ABISysV_mips64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
if ((arch_type == llvm::Triple::mips64) ||
(arch_type == llvm::Triple::mips64el)) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_mips64(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_mips64(process_sp));
}
return ABISP();
}
@@ -769,7 +762,10 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
Target *target = exe_ctx.GetTargetPtr();
const ArchSpec target_arch = target->GetArchitecture();
ByteOrder target_byte_order = target_arch.GetByteOrder();
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
const uint32_t type_flags = return_compiler_type.GetTypeInfo(nullptr);
uint32_t fp_flag =
target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
@@ -788,7 +784,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
@@ -829,7 +825,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
// Don't handle complex yet.
} else if (IsSoftFloat(fp_flag)) {
uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_info, 0);
- switch (byte_size) {
+ switch (*byte_size) {
case 4:
value.GetScalar() = *((float *)(&raw_value));
success = true;
@@ -854,7 +850,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
}
} else {
- if (byte_size <= sizeof(long double)) {
+ if (*byte_size <= sizeof(long double)) {
const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
RegisterValue f0_value;
@@ -865,13 +861,13 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
f0_value.GetData(f0_data);
lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
value.GetScalar() = (float)f0_data.GetFloat(&offset);
success = true;
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
value.GetScalar() = (double)f0_data.GetDouble(&offset);
success = true;
- } else if (byte_size == sizeof(long double)) {
+ } else if (*byte_size == sizeof(long double)) {
const RegisterInfo *f2_info =
reg_ctx->GetRegisterInfoByName("f2", 0);
RegisterValue f2_value;
@@ -886,21 +882,21 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
if (target_byte_order == eByteOrderLittle) {
copy_from_extractor = &f0_data;
copy_from_extractor->CopyByteOrderedData(
- 0, 8, data_sp->GetBytes(), byte_size - 8, target_byte_order);
+ 0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
f2_value.GetData(f2_data);
copy_from_extractor = &f2_data;
copy_from_extractor->CopyByteOrderedData(
- 0, 8, data_sp->GetBytes() + 8, byte_size - 8,
+ 0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
target_byte_order);
} else {
copy_from_extractor = &f0_data;
copy_from_extractor->CopyByteOrderedData(
- 0, 8, data_sp->GetBytes() + 8, byte_size - 8,
+ 0, 8, data_sp->GetBytes() + 8, *byte_size - 8,
target_byte_order);
f2_value.GetData(f2_data);
copy_from_extractor = &f2_data;
copy_from_extractor->CopyByteOrderedData(
- 0, 8, data_sp->GetBytes(), byte_size - 8, target_byte_order);
+ 0, 8, data_sp->GetBytes(), *byte_size - 8, target_byte_order);
}
return_valobj_sp = ValueObjectConstResult::Create(
@@ -917,7 +913,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
} else if (type_flags & eTypeIsStructUnion || type_flags & eTypeIsClass ||
type_flags & eTypeIsVector) {
// Any structure of up to 16 bytes in size is returned in the registers.
- if (byte_size <= 16) {
+ if (*byte_size <= 16) {
DataBufferSP data_sp(new DataBufferHeap(16, 0));
DataExtractor return_ext(data_sp, target_byte_order,
target->GetArchitecture().GetAddressByteSize());
@@ -975,8 +971,10 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
CompilerType field_compiler_type =
return_compiler_type.GetFieldAtIndex(
idx, name, &field_bit_offset, nullptr, nullptr);
- const size_t field_byte_width =
+ llvm::Optional<uint64_t> field_byte_width =
field_compiler_type.GetByteSize(nullptr);
+ if (!field_byte_width)
+ return return_valobj_sp;
DataExtractor *copy_from_extractor = nullptr;
uint64_t return_value[2];
@@ -984,7 +982,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
if (idx == 0) {
// This case is for long double type.
- if (field_byte_width == 16) {
+ if (*field_byte_width == 16) {
// If structure contains long double type, then it is returned
// in fp0/fp1 registers.
@@ -1002,7 +1000,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
return_value[0] = f1_data.GetU64(&offset);
}
- f0_data.SetData(return_value, field_byte_width,
+ f0_data.SetData(return_value, *field_byte_width,
target_byte_order);
}
copy_from_extractor = &f0_data; // This is in f0, copy from
@@ -1016,13 +1014,13 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
// Sanity check to avoid crash
if (!copy_from_extractor ||
- field_byte_width > copy_from_extractor->GetByteSize())
+ *field_byte_width > copy_from_extractor->GetByteSize())
return return_valobj_sp;
// copy the register contents into our data buffer
copy_from_extractor->CopyByteOrderedData(
- 0, field_byte_width,
- data_sp->GetBytes() + (field_bit_offset / 8), field_byte_width,
+ 0, *field_byte_width,
+ data_sp->GetBytes() + (field_bit_offset / 8), *field_byte_width,
target_byte_order);
}
@@ -1045,12 +1043,12 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
idx, name, &field_bit_offset, nullptr, nullptr);
- const size_t field_byte_width =
+ llvm::Optional<uint64_t> field_byte_width =
field_compiler_type.GetByteSize(nullptr);
// if we don't know the size of the field (e.g. invalid type), just
// bail out
- if (field_byte_width == 0)
+ if (!field_byte_width || *field_byte_width == 0)
break;
uint32_t field_byte_offset = field_bit_offset / 8;
@@ -1062,24 +1060,24 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
if (integer_bytes < 8) {
// We have not yet consumed r2 completely.
- if (integer_bytes + field_byte_width + padding <= 8) {
+ if (integer_bytes + *field_byte_width + padding <= 8) {
// This field fits in r2, copy its value from r2 to our result
// structure
- integer_bytes = integer_bytes + field_byte_width +
+ integer_bytes = integer_bytes + *field_byte_width +
padding; // Increase the consumed bytes.
use_r2 = 1;
} else {
// There isn't enough space left in r2 for this field, so this
// will be in r3.
- integer_bytes = integer_bytes + field_byte_width +
+ integer_bytes = integer_bytes + *field_byte_width +
padding; // Increase the consumed bytes.
use_r3 = 1;
}
}
// We already have consumed at-least 8 bytes that means r2 is done,
// and this field will be in r3. Check if this field can fit in r3.
- else if (integer_bytes + field_byte_width + padding <= 16) {
- integer_bytes = integer_bytes + field_byte_width + padding;
+ else if (integer_bytes + *field_byte_width + padding <= 16) {
+ integer_bytes = integer_bytes + *field_byte_width + padding;
use_r3 = 1;
} else {
// There isn't any space left for this field, this should not
@@ -1092,7 +1090,7 @@ ValueObjectSP ABISysV_mips64::GetReturnValueObjectImpl(
}
// Vector types up to 16 bytes are returned in GP return registers
if (type_flags & eTypeIsVector) {
- if (byte_size <= 8)
+ if (*byte_size <= 8)
use_r2 = 1;
else {
use_r2 = 1;
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
index 6258c08e35f9..c7670f467114 100644
--- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_mips64_h_
#define liblldb_ABISysV_mips64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
index e93dcdbe1a59..1fe7a6718a91 100644
--- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.cpp
@@ -9,16 +9,11 @@
#include "ABISysV_ppc.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,6 +27,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -224,11 +220,8 @@ size_t ABISysV_ppc::GetRedZoneSize() const { return 224; }
ABISP
ABISysV_ppc::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::ppc) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_ppc(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_ppc(process_sp));
}
return ABISP();
}
@@ -405,19 +398,18 @@ bool ABISysV_ppc::GetArgumentValues(Thread &thread, ValueList &values) const {
// We currently only support extracting values with Clang QualTypes. Do we
// care about others?
CompilerType compiler_type = value->GetCompilerType();
- if (!compiler_type)
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (!bit_size)
return false;
bool is_signed;
-
- if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- is_signed, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
- } else if (compiler_type.IsPointerType()) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- false, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
- }
+ if (compiler_type.IsIntegerOrEnumerationType(is_signed))
+ ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
+ else if (compiler_type.IsPointerType())
+ ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
}
return true;
@@ -474,8 +466,13 @@ Status ABISysV_ppc::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
error.SetErrorString(
"We don't support returning complex values at present");
else {
- size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
- if (bit_width <= 64) {
+ llvm::Optional<uint64_t> bit_width =
+ compiler_type.GetBitSize(frame_sp.get());
+ if (!bit_width) {
+ error.SetErrorString("can't get type size");
+ return error;
+ }
+ if (*bit_width <= 64) {
DataExtractor data;
Status data_error;
size_t num_bytes = new_value_sp->GetData(data, data_error);
@@ -533,11 +530,14 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple(
if (type_flags & eTypeIsInteger) {
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
reg_ctx->GetRegisterInfoByName("r3", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
@@ -577,18 +577,19 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple(
if (type_flags & eTypeIsComplex) {
// Don't handle complex yet.
} else {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size <= sizeof(long double)) {
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (byte_size && *byte_size <= sizeof(long double)) {
const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
RegisterValue f1_value;
if (reg_ctx->ReadRegister(f1_info, f1_value)) {
DataExtractor data;
if (f1_value.GetData(data)) {
lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
value.GetScalar() = (float)data.GetFloat(&offset);
success = true;
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
value.GetScalar() = (double)data.GetDouble(&offset);
success = true;
}
@@ -610,15 +611,16 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple(
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size > 0) {
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (byte_size && *byte_size > 0) {
const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0);
if (altivec_reg) {
- if (byte_size <= altivec_reg->byte_size) {
+ if (*byte_size <= altivec_reg->byte_size) {
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue reg_value;
if (reg_ctx->ReadRegister(altivec_reg, reg_value)) {
@@ -627,9 +629,10 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectSimple(
altivec_reg, heap_data_ap->GetBytes(),
heap_data_ap->GetByteSize(), byte_order, error)) {
DataExtractor data(DataBufferSP(heap_data_ap.release()),
- byte_order, process_sp->GetTarget()
- .GetArchitecture()
- .GetAddressByteSize());
+ byte_order,
+ process_sp->GetTarget()
+ .GetArchitecture()
+ .GetAddressByteSize());
return_valobj_sp = ValueObjectConstResult::Create(
&thread, return_compiler_type, ConstString(""), data);
}
@@ -659,11 +662,13 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
+ if (!bit_width)
+ return return_valobj_sp;
if (return_compiler_type.IsAggregateType()) {
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
- if (bit_width <= 128) {
+ if (*bit_width <= 128) {
ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
DataBufferSP data_sp(new DataBufferHeap(16, 0));
DataExtractor return_ext(data_sp, target_byte_order,
@@ -701,15 +706,18 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
idx, name, &field_bit_offset, nullptr, nullptr);
- const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> field_bit_width =
+ field_compiler_type.GetBitSize(&thread);
+ if (!field_bit_width)
+ return return_valobj_sp;
// If there are any unaligned fields, this is stored in memory.
- if (field_bit_offset % field_bit_width != 0) {
+ if (field_bit_offset % *field_bit_width != 0) {
is_memory = true;
break;
}
- uint32_t field_byte_width = field_bit_width / 8;
+ uint32_t field_byte_width = *field_bit_width / 8;
uint32_t field_byte_offset = field_bit_offset / 8;
DataExtractor *copy_from_extractor = nullptr;
@@ -742,13 +750,13 @@ ValueObjectSP ABISysV_ppc::GetReturnValueObjectImpl(
}
} else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
// Structs with long doubles are always passed in memory.
- if (field_bit_width == 128) {
+ if (*field_bit_width == 128) {
is_memory = true;
break;
- } else if (field_bit_width == 64) {
+ } else if (*field_bit_width == 64) {
copy_from_offset = 0;
fp_bytes += field_byte_width;
- } else if (field_bit_width == 32) {
+ } else if (*field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
// with another float, we'll be stuffed into an xmm register with
// it. If we are in an "eightbyte" with one or more ints, then we
diff --git a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
index df3ebe83faf8..3559cbb45200 100644
--- a/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
+++ b/source/Plugins/ABI/SysV-ppc/ABISysV_ppc.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_ppc_h_
#define liblldb_ABISysV_ppc_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
index d0140a0c894a..fb46b7dc7fb6 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.cpp
@@ -9,18 +9,13 @@
#include "ABISysV_ppc64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "Utility/PPC64LE_DWARF_Registers.h"
#include "Utility/PPC64_DWARF_Registers.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -35,6 +30,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "clang/AST/ASTContext.h"
@@ -284,18 +280,19 @@ bool ABISysV_ppc64::GetArgumentValues(Thread &thread, ValueList &values) const {
// We currently only support extracting values with Clang QualTypes. Do we
// care about others?
CompilerType compiler_type = value->GetCompilerType();
- if (!compiler_type)
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (!bit_size)
return false;
bool is_signed;
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- is_signed, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
+ ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
} else if (compiler_type.IsPointerType()) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- false, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
+ ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
}
}
@@ -353,8 +350,13 @@ Status ABISysV_ppc64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
error.SetErrorString(
"We don't support returning complex values at present");
else {
- size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
- if (bit_width <= 64) {
+ llvm::Optional<uint64_t> bit_width =
+ compiler_type.GetBitSize(frame_sp.get());
+ if (!bit_width) {
+ error.SetErrorString("can't get size of type");
+ return error;
+ }
+ if (*bit_width <= 64) {
DataExtractor data;
Status data_error;
size_t num_bytes = new_value_sp->GetData(data, data_error);
@@ -575,7 +577,7 @@ private:
ReturnValueExtractor(Thread &thread, CompilerType &type,
RegisterContext *reg_ctx, ProcessSP process_sp)
: m_thread(thread), m_type(type),
- m_byte_size(m_type.GetByteSize(nullptr)),
+ m_byte_size(m_type.GetByteSize(nullptr).getValueOr(0)),
m_data_ap(new DataBufferHeap(m_byte_size, 0)), m_reg_ctx(reg_ctx),
m_process_sp(process_sp), m_byte_order(process_sp->GetByteOrder()),
m_addr_size(
@@ -643,7 +645,7 @@ private:
uint64_t raw_data;
auto reg = GetFPR(reg_index);
if (!reg.GetRawData(raw_data))
- return ValueSP();
+ return {};
// build value from data
ValueSP value_sp(NewScalarValue(type));
@@ -651,8 +653,10 @@ private:
DataExtractor de(&raw_data, sizeof(raw_data), m_byte_order, m_addr_size);
offset_t offset = 0;
- size_t byte_size = type.GetByteSize(nullptr);
- switch (byte_size) {
+ llvm::Optional<uint64_t> byte_size = type.GetByteSize(nullptr);
+ if (!byte_size)
+ return {};
+ switch (*byte_size) {
case sizeof(float):
value_sp->GetScalar() = (float)de.GetDouble(&offset);
break;
@@ -759,7 +763,7 @@ private:
uint64_t addr;
auto reg = GetGPR(0);
if (!reg.GetRawData(addr))
- return ValueObjectSP();
+ return {};
Status error;
size_t rc = m_process_sp->ReadMemory(addr, m_data_ap->GetBytes(),
@@ -773,37 +777,39 @@ private:
// get number of children
const bool omit_empty_base_classes = true;
- uint32_t n = m_type.GetNumChildren(omit_empty_base_classes);
+ uint32_t n = m_type.GetNumChildren(omit_empty_base_classes, nullptr);
if (!n) {
LLDB_LOG(m_log, LOG_PREFIX "No children found in struct");
- return ValueObjectSP();
+ return {};
}
// case 2: homogeneous double or float aggregate
CompilerType elem_type;
if (m_type.IsHomogeneousAggregate(&elem_type)) {
uint32_t type_flags = elem_type.GetTypeInfo();
- uint64_t elem_size = elem_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> elem_size = elem_type.GetByteSize(nullptr);
+ if (!elem_size)
+ return {};
if (type_flags & eTypeIsComplex || !(type_flags & eTypeIsFloat)) {
LLDB_LOG(m_log,
LOG_PREFIX "Unexpected type found in homogeneous aggregate");
- return ValueObjectSP();
+ return {};
}
for (uint32_t i = 0; i < n; i++) {
ValueSP val_sp = GetFloatValue(elem_type, i);
if (!val_sp)
- return ValueObjectSP();
+ return {};
// copy to buffer
Status error;
size_t rc = val_sp->GetScalar().GetAsMemoryData(
- m_data_ap->GetBytes() + m_dst_offs, elem_size, m_byte_order, error);
- if (rc != elem_size) {
+ m_data_ap->GetBytes() + m_dst_offs, *elem_size, m_byte_order, error);
+ if (rc != *elem_size) {
LLDB_LOG(m_log, LOG_PREFIX "Failed to get float data");
- return ValueObjectSP();
+ return {};
}
- m_dst_offs += elem_size;
+ m_dst_offs += *elem_size;
}
return BuildValueObject();
}
diff --git a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
index 52765a773c0b..54f461e1001b 100644
--- a/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
+++ b/source/Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_ppc64_h_
#define liblldb_ABISysV_ppc64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
index 31e2825c0fa2..d8056ea7d356 100644
--- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
+++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
@@ -9,16 +9,11 @@
#include "ABISysV_s390x.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,6 +27,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -206,11 +202,8 @@ size_t ABISysV_s390x::GetRedZoneSize() const { return 0; }
ABISP
ABISysV_s390x::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::systemz) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_s390x(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_s390x(process_sp));
}
return ABISP();
}
@@ -383,18 +376,19 @@ bool ABISysV_s390x::GetArgumentValues(Thread &thread, ValueList &values) const {
// We currently only support extracting values with Clang QualTypes. Do we
// care about others?
CompilerType compiler_type = value->GetCompilerType();
- if (!compiler_type)
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (!bit_size)
return false;
bool is_signed;
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- is_signed, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
+ ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
} else if (compiler_type.IsPointerType()) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- false, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
+ ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
}
}
@@ -452,8 +446,13 @@ Status ABISysV_s390x::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
error.SetErrorString(
"We don't support returning complex values at present");
else {
- size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
- if (bit_width <= 64) {
+ llvm::Optional<uint64_t> bit_width =
+ compiler_type.GetBitSize(frame_sp.get());
+ if (!bit_width) {
+ error.SetErrorString("can't get type size");
+ return error;
+ }
+ if (*bit_width <= 64) {
const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
RegisterValue f0_value;
DataExtractor data;
@@ -513,13 +512,15 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple(
bool success = false;
if (type_flags & eTypeIsInteger) {
- // Extract the register context so we can read arguments from registers
-
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ // Extract the register context so we can read arguments from registers.
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
reg_ctx->GetRegisterInfoByName("r2", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
@@ -559,21 +560,22 @@ ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple(
if (type_flags & eTypeIsComplex) {
// Don't handle complex yet.
} else {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size <= sizeof(long double)) {
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (byte_size && *byte_size <= sizeof(long double)) {
const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
RegisterValue f0_value;
if (reg_ctx->ReadRegister(f0_info, f0_value)) {
DataExtractor data;
if (f0_value.GetData(data)) {
lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
value.GetScalar() = (float)data.GetFloat(&offset);
success = true;
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
value.GetScalar() = (double)data.GetDouble(&offset);
success = true;
- } else if (byte_size == sizeof(long double)) {
+ } else if (*byte_size == sizeof(long double)) {
// Don't handle long double yet.
}
}
diff --git a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h
index 5e3d20d7898b..5433ebb4593e 100644
--- a/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h
+++ b/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_s390x_h_
#define liblldb_ABISysV_s390x_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
@@ -61,9 +57,7 @@ public:
bool CodeAddressIsValid(lldb::addr_t pc) override {
// Code addressed must be 2 byte aligned
- if (pc & 1ull)
- return false;
- return true;
+ return (pc & 1ull) == 0;
}
const lldb_private::RegisterInfo *
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 36ae3a49827c..dc3e475e3b8e 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -9,17 +9,12 @@
#include "ABISysV_x86_64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -33,6 +28,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
@@ -1095,11 +1091,8 @@ size_t ABISysV_x86_64::GetRedZoneSize() const { return 128; }
ABISP
ABISysV_x86_64::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
- static ABISP g_abi_sp;
if (arch.GetTriple().getArch() == llvm::Triple::x86_64) {
- if (!g_abi_sp)
- g_abi_sp.reset(new ABISysV_x86_64(process_sp));
- return g_abi_sp;
+ return ABISP(new ABISysV_x86_64(process_sp));
}
return ABISP();
}
@@ -1270,18 +1263,19 @@ bool ABISysV_x86_64::GetArgumentValues(Thread &thread,
// We currently only support extracting values with Clang QualTypes. Do we
// care about others?
CompilerType compiler_type = value->GetCompilerType();
- if (!compiler_type)
+ llvm::Optional<uint64_t> bit_size = compiler_type.GetBitSize(&thread);
+ if (!bit_size)
return false;
bool is_signed;
if (compiler_type.IsIntegerOrEnumerationType(is_signed)) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- is_signed, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
+ ReadIntegerArgument(value->GetScalar(), *bit_size, is_signed, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
} else if (compiler_type.IsPointerType()) {
- ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread),
- false, thread, argument_register_ids,
- current_argument_register, current_stack_argument);
+ ReadIntegerArgument(value->GetScalar(), *bit_size, false, thread,
+ argument_register_ids, current_argument_register,
+ current_stack_argument);
}
}
@@ -1339,8 +1333,13 @@ Status ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
error.SetErrorString(
"We don't support returning complex values at present");
else {
- size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
- if (bit_width <= 64) {
+ llvm::Optional<uint64_t> bit_width =
+ compiler_type.GetBitSize(frame_sp.get());
+ if (!bit_width) {
+ error.SetErrorString("can't get type size");
+ return error;
+ }
+ if (*bit_width <= 64) {
const RegisterInfo *xmm0_info =
reg_ctx->GetRegisterInfoByName("xmm0", 0);
RegisterValue xmm0_value;
@@ -1403,11 +1402,14 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
if (type_flags & eTypeIsInteger) {
// Extract the register context so we can read arguments from registers
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (!byte_size)
+ return return_valobj_sp;
uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
reg_ctx->GetRegisterInfoByName("rax", 0), 0);
const bool is_signed = (type_flags & eTypeIsSigned) != 0;
- switch (byte_size) {
+ switch (*byte_size) {
default:
break;
@@ -1447,8 +1449,9 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
if (type_flags & eTypeIsComplex) {
// Don't handle complex yet.
} else {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size <= sizeof(long double)) {
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (byte_size && *byte_size <= sizeof(long double)) {
const RegisterInfo *xmm0_info =
reg_ctx->GetRegisterInfoByName("xmm0", 0);
RegisterValue xmm0_value;
@@ -1456,13 +1459,13 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
DataExtractor data;
if (xmm0_value.GetData(data)) {
lldb::offset_t offset = 0;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
value.GetScalar() = (float)data.GetFloat(&offset);
success = true;
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
value.GetScalar() = (double)data.GetDouble(&offset);
success = true;
- } else if (byte_size == sizeof(long double)) {
+ } else if (*byte_size == sizeof(long double)) {
// Don't handle long double since that can be encoded as 80 bit
// floats...
}
@@ -1485,19 +1488,20 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
} else if (type_flags & eTypeIsVector) {
- const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
- if (byte_size > 0) {
+ llvm::Optional<uint64_t> byte_size =
+ return_compiler_type.GetByteSize(nullptr);
+ if (byte_size && *byte_size > 0) {
const RegisterInfo *altivec_reg =
reg_ctx->GetRegisterInfoByName("xmm0", 0);
if (altivec_reg == nullptr)
altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
if (altivec_reg) {
- if (byte_size <= altivec_reg->byte_size) {
+ if (*byte_size <= altivec_reg->byte_size) {
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue reg_value;
if (reg_ctx->ReadRegister(altivec_reg, reg_value)) {
@@ -1514,14 +1518,14 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple(
}
}
}
- } else if (byte_size <= altivec_reg->byte_size * 2) {
+ } else if (*byte_size <= altivec_reg->byte_size * 2) {
const RegisterInfo *altivec_reg2 =
reg_ctx->GetRegisterInfoByName("xmm1", 0);
if (altivec_reg2) {
ProcessSP process_sp(thread.GetProcess());
if (process_sp) {
std::unique_ptr<DataBufferHeap> heap_data_ap(
- new DataBufferHeap(byte_size, 0));
+ new DataBufferHeap(*byte_size, 0));
const ByteOrder byte_order = process_sp->GetByteOrder();
RegisterValue reg_value;
RegisterValue reg_value2;
@@ -1571,11 +1575,13 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
if (!reg_ctx_sp)
return return_valobj_sp;
- const size_t bit_width = return_compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
+ if (!bit_width)
+ return return_valobj_sp;
if (return_compiler_type.IsAggregateType()) {
Target *target = exe_ctx.GetTargetPtr();
bool is_memory = true;
- if (bit_width <= 128) {
+ if (*bit_width <= 128) {
ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
DataBufferSP data_sp(new DataBufferHeap(16, 0));
DataExtractor return_ext(data_sp, target_byte_order,
@@ -1622,20 +1628,21 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
CompilerType field_compiler_type = return_compiler_type.GetFieldAtIndex(
idx, name, &field_bit_offset, nullptr, nullptr);
- const size_t field_bit_width = field_compiler_type.GetBitSize(&thread);
+ llvm::Optional<uint64_t> field_bit_width =
+ field_compiler_type.GetBitSize(&thread);
// if we don't know the size of the field (e.g. invalid type), just
// bail out
- if (field_bit_width == 0)
+ if (!field_bit_width || *field_bit_width == 0)
break;
// If there are any unaligned fields, this is stored in memory.
- if (field_bit_offset % field_bit_width != 0) {
+ if (field_bit_offset % *field_bit_width != 0) {
is_memory = true;
break;
}
- uint32_t field_byte_width = field_bit_width / 8;
+ uint32_t field_byte_width = *field_bit_width / 8;
uint32_t field_byte_offset = field_bit_offset / 8;
DataExtractor *copy_from_extractor = nullptr;
@@ -1668,10 +1675,10 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
}
} else if (field_compiler_type.IsFloatingPointType(count, is_complex)) {
// Structs with long doubles are always passed in memory.
- if (field_bit_width == 128) {
+ if (*field_bit_width == 128) {
is_memory = true;
break;
- } else if (field_bit_width == 64) {
+ } else if (*field_bit_width == 64) {
// These have to be in a single xmm register.
if (fp_bytes == 0)
copy_from_extractor = &xmm0_data;
@@ -1680,7 +1687,7 @@ ValueObjectSP ABISysV_x86_64::GetReturnValueObjectImpl(
copy_from_offset = 0;
fp_bytes += field_byte_width;
- } else if (field_bit_width == 32) {
+ } else if (*field_bit_width == 32) {
// This one is kind of complicated. If we are in an "eightbyte"
// with another float, we'll be stuffed into an xmm register with
// it. If we are in an "eightbyte" with one or more ints, then we
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 5b67e8656d36..4afc8c4cad62 100644
--- a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ABISysV_x86_64_h_
#define liblldb_ABISysV_x86_64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.cpp b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
index 1b7ecc88c35e..6993222ba5d4 100644
--- a/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
+++ b/source/Plugins/Architecture/Arm/ArchitectureArm.cpp
@@ -126,3 +126,33 @@ void ArchitectureArm::OverrideStopInfo(Thread &thread) const {
}
}
}
+
+addr_t ArchitectureArm::GetCallableLoadAddress(addr_t code_addr,
+ AddressClass addr_class) const {
+ bool is_alternate_isa = false;
+
+ switch (addr_class) {
+ case AddressClass::eData:
+ case AddressClass::eDebug:
+ return LLDB_INVALID_ADDRESS;
+ case AddressClass::eCodeAlternateISA:
+ is_alternate_isa = true;
+ break;
+ default: break;
+ }
+
+ if ((code_addr & 2u) || is_alternate_isa)
+ return code_addr | 1u;
+ return code_addr;
+}
+
+addr_t ArchitectureArm::GetOpcodeLoadAddress(addr_t opcode_addr,
+ AddressClass addr_class) const {
+ switch (addr_class) {
+ case AddressClass::eData:
+ case AddressClass::eDebug:
+ return LLDB_INVALID_ADDRESS;
+ default: break;
+ }
+ return opcode_addr & ~(1ull);
+}
diff --git a/source/Plugins/Architecture/Arm/ArchitectureArm.h b/source/Plugins/Architecture/Arm/ArchitectureArm.h
index 484c4a52fcc6..1a052c76b2c9 100644
--- a/source/Plugins/Architecture/Arm/ArchitectureArm.h
+++ b/source/Plugins/Architecture/Arm/ArchitectureArm.h
@@ -25,6 +25,12 @@ public:
void OverrideStopInfo(Thread &thread) const override;
+ lldb::addr_t GetCallableLoadAddress(lldb::addr_t load_addr,
+ AddressClass addr_class) const override;
+
+ lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr,
+ AddressClass addr_class) const override;
+
private:
static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
ArchitectureArm() = default;
diff --git a/source/Plugins/Architecture/CMakeLists.txt b/source/Plugins/Architecture/CMakeLists.txt
index 01365a64cf96..14ad91644595 100644
--- a/source/Plugins/Architecture/CMakeLists.txt
+++ b/source/Plugins/Architecture/CMakeLists.txt
@@ -1,2 +1,3 @@
add_subdirectory(Arm)
+add_subdirectory(Mips)
add_subdirectory(PPC64)
diff --git a/source/Plugins/Architecture/Mips/ArchitectureMips.cpp b/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
new file mode 100644
index 000000000000..0cbbd9922321
--- /dev/null
+++ b/source/Plugins/Architecture/Mips/ArchitectureMips.cpp
@@ -0,0 +1,241 @@
+//===-- ArchitectureMips.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Architecture/Mips/ArchitectureMips.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Log.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+ConstString ArchitectureMips::GetPluginNameStatic() {
+ return ConstString("mips");
+}
+
+void ArchitectureMips::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ "Mips-specific algorithms",
+ &ArchitectureMips::Create);
+}
+
+void ArchitectureMips::Terminate() {
+ PluginManager::UnregisterPlugin(&ArchitectureMips::Create);
+}
+
+std::unique_ptr<Architecture> ArchitectureMips::Create(const ArchSpec &arch) {
+ return arch.IsMIPS() ?
+ std::unique_ptr<Architecture>(new ArchitectureMips(arch)) : nullptr;
+}
+
+ConstString ArchitectureMips::GetPluginName() { return GetPluginNameStatic(); }
+uint32_t ArchitectureMips::GetPluginVersion() { return 1; }
+
+addr_t ArchitectureMips::GetCallableLoadAddress(addr_t code_addr,
+ AddressClass addr_class) const {
+ bool is_alternate_isa = false;
+
+ switch (addr_class) {
+ case AddressClass::eData:
+ case AddressClass::eDebug:
+ return LLDB_INVALID_ADDRESS;
+ case AddressClass::eCodeAlternateISA:
+ is_alternate_isa = true;
+ break;
+ default: break;
+ }
+
+ if ((code_addr & 2ull) || is_alternate_isa)
+ return code_addr | 1u;
+ return code_addr;
+}
+
+addr_t ArchitectureMips::GetOpcodeLoadAddress(addr_t opcode_addr,
+ AddressClass addr_class) const {
+ switch (addr_class) {
+ case AddressClass::eData:
+ case AddressClass::eDebug:
+ return LLDB_INVALID_ADDRESS;
+ default: break;
+ }
+ return opcode_addr & ~(1ull);
+}
+
+lldb::addr_t ArchitectureMips::GetBreakableLoadAddress(lldb::addr_t addr,
+ Target &target) const {
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+
+ Address resolved_addr;
+
+ SectionLoadList &section_load_list = target.GetSectionLoadList();
+ if (section_load_list.IsEmpty())
+ // No sections are loaded, so we must assume we are not running yet and
+ // need to operate only on file address.
+ target.ResolveFileAddress(addr, resolved_addr);
+ else
+ target.ResolveLoadAddress(addr, resolved_addr);
+
+ addr_t current_offset = 0;
+
+ // Get the function boundaries to make sure we don't scan back before the
+ // beginning of the current function.
+ ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
+ if (temp_addr_module_sp) {
+ SymbolContext sc;
+ SymbolContextItem resolve_scope =
+ eSymbolContextFunction | eSymbolContextSymbol;
+ temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
+ resolve_scope, sc);
+ Address sym_addr;
+ if (sc.function)
+ sym_addr = sc.function->GetAddressRange().GetBaseAddress();
+ else if (sc.symbol)
+ sym_addr = sc.symbol->GetAddress();
+
+ addr_t function_start = sym_addr.GetLoadAddress(&target);
+ if (function_start == LLDB_INVALID_ADDRESS)
+ function_start = sym_addr.GetFileAddress();
+
+ if (function_start)
+ current_offset = addr - function_start;
+ }
+
+ // If breakpoint address is start of function then we dont have to do
+ // anything.
+ if (current_offset == 0)
+ return addr;
+
+ ExecutionContext ctx;
+ target.CalculateExecutionContext(ctx);
+ auto insn = GetInstructionAtAddress(ctx, current_offset, addr);
+
+ if (nullptr == insn || !insn->HasDelaySlot())
+ return addr;
+
+ // Adjust the breakable address
+ uint64_t breakable_addr = addr - insn->GetOpcode().GetByteSize();
+ if (log)
+ log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64
+ " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
+ __FUNCTION__, addr, breakable_addr);
+
+ return breakable_addr;
+}
+
+Instruction *ArchitectureMips::GetInstructionAtAddress(
+ const ExecutionContext &exe_ctx, const Address &resolved_addr,
+ addr_t symbol_offset) const {
+
+ auto loop_count = symbol_offset / 2;
+
+ uint32_t arch_flags = m_arch.GetFlags();
+ bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
+ bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
+
+ if (loop_count > 3) {
+ // Scan previous 6 bytes
+ if (IsMips16 | IsMicromips)
+ loop_count = 3;
+ // For mips-only, instructions are always 4 bytes, so scan previous 4
+ // bytes only.
+ else
+ loop_count = 2;
+ }
+
+ // Create Disassembler Instance
+ lldb::DisassemblerSP disasm_sp(
+ Disassembler::FindPlugin(m_arch, nullptr, nullptr));
+
+ InstructionList instruction_list;
+ InstructionSP prev_insn;
+ bool prefer_file_cache = true; // Read from file
+ uint32_t inst_to_choose = 0;
+
+ Address addr = resolved_addr;
+
+ for (uint32_t i = 1; i <= loop_count; i++) {
+ // Adjust the address to read from.
+ addr.Slide(-2);
+ AddressRange range(addr, i * 2);
+ uint32_t insn_size = 0;
+
+ disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
+
+ uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
+ if (num_insns) {
+ prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
+ insn_size = prev_insn->GetOpcode().GetByteSize();
+ if (i == 1 && insn_size == 2) {
+ // This looks like a valid 2-byte instruction (but it could be a part
+ // of upper 4 byte instruction).
+ instruction_list.Append(prev_insn);
+ inst_to_choose = 1;
+ }
+ else if (i == 2) {
+ // Here we may get one 4-byte instruction or two 2-byte instructions.
+ if (num_insns == 2) {
+ // Looks like there are two 2-byte instructions above our
+ // breakpoint target address. Now the upper 2-byte instruction is
+ // either a valid 2-byte instruction or could be a part of it's
+ // upper 4-byte instruction. In both cases we don't care because in
+ // this case lower 2-byte instruction is definitely a valid
+ // instruction and whatever i=1 iteration has found out is true.
+ inst_to_choose = 1;
+ break;
+ }
+ else if (insn_size == 4) {
+ // This instruction claims its a valid 4-byte instruction. But it
+ // could be a part of it's upper 4-byte instruction. Lets try
+ // scanning upper 2 bytes to verify this.
+ instruction_list.Append(prev_insn);
+ inst_to_choose = 2;
+ }
+ }
+ else if (i == 3) {
+ if (insn_size == 4)
+ // FIXME: We reached here that means instruction at [target - 4] has
+ // already claimed to be a 4-byte instruction, and now instruction
+ // at [target - 6] is also claiming that it's a 4-byte instruction.
+ // This can not be true. In this case we can not decide the valid
+ // previous instruction so we let lldb set the breakpoint at the
+ // address given by user.
+ inst_to_choose = 0;
+ else
+ // This is straight-forward
+ inst_to_choose = 2;
+ break;
+ }
+ }
+ else {
+ // Decode failed, bytes do not form a valid instruction. So whatever
+ // previous iteration has found out is true.
+ if (i > 1) {
+ inst_to_choose = i - 1;
+ break;
+ }
+ }
+ }
+
+ // Check if we are able to find any valid instruction.
+ if (inst_to_choose) {
+ if (inst_to_choose > instruction_list.GetSize())
+ inst_to_choose--;
+ return instruction_list.GetInstructionAtIndex(inst_to_choose - 1).get();
+ }
+
+ return nullptr;
+}
diff --git a/source/Plugins/Architecture/Mips/ArchitectureMips.h b/source/Plugins/Architecture/Mips/ArchitectureMips.h
new file mode 100644
index 000000000000..2338daf2e468
--- /dev/null
+++ b/source/Plugins/Architecture/Mips/ArchitectureMips.h
@@ -0,0 +1,52 @@
+//===-- ArchitectureMips.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_PLUGIN_ARCHITECTURE_MIPS_H
+#define LLDB_PLUGIN_ARCHITECTURE_MIPS_H
+
+#include "lldb/Core/Architecture.h"
+#include "lldb/Utility/ArchSpec.h"
+
+namespace lldb_private {
+
+class ArchitectureMips : public Architecture {
+public:
+ static ConstString GetPluginNameStatic();
+ static void Initialize();
+ static void Terminate();
+
+ ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+
+ void OverrideStopInfo(Thread &thread) const override {}
+
+ lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr,
+ Target &) const override;
+
+ lldb::addr_t GetCallableLoadAddress(lldb::addr_t load_addr,
+ AddressClass addr_class) const override;
+
+ lldb::addr_t GetOpcodeLoadAddress(lldb::addr_t load_addr,
+ AddressClass addr_class) const override;
+
+private:
+ Instruction *GetInstructionAtAddress(const ExecutionContext &exe_ctx,
+ const Address &resolved_addr,
+ lldb::addr_t symbol_offset) const;
+
+
+ static std::unique_ptr<Architecture> Create(const ArchSpec &arch);
+ ArchitectureMips(const ArchSpec &arch) : m_arch(arch) {}
+
+ ArchSpec m_arch;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_PLUGIN_ARCHITECTURE_MIPS_H
diff --git a/source/Plugins/Architecture/Mips/CMakeLists.txt b/source/Plugins/Architecture/Mips/CMakeLists.txt
new file mode 100644
index 000000000000..9734edc6b12b
--- /dev/null
+++ b/source/Plugins/Architecture/Mips/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginArchitectureMips PLUGIN
+ ArchitectureMips.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbTarget
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 9b381dd3b96c..5df842250591 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Project includes
#include "DisassemblerLLVMC.h"
-// Other libraries and framework includes
#include "llvm-c/Disassembler.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -98,16 +94,15 @@ public:
bool DoesBranch() override {
if (m_does_branch == eLazyBoolCalculate) {
- std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
- if (disasm_sp) {
- disasm_sp->Lock(this, NULL);
+ DisassemblerScope disasm(*this);
+ if (disasm) {
DataExtractor data;
if (m_opcode.GetData(data)) {
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
- GetDisasmToUse(is_alternate_isa);
+ GetDisasmToUse(is_alternate_isa, disasm);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
llvm::MCInst inst;
@@ -125,7 +120,6 @@ public:
m_does_branch = eLazyBoolNo;
}
}
- disasm_sp->Unlock();
}
}
return m_does_branch == eLazyBoolYes;
@@ -133,16 +127,15 @@ public:
bool HasDelaySlot() override {
if (m_has_delay_slot == eLazyBoolCalculate) {
- std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
- if (disasm_sp) {
- disasm_sp->Lock(this, NULL);
+ DisassemblerScope disasm(*this);
+ if (disasm) {
DataExtractor data;
if (m_opcode.GetData(data)) {
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
- GetDisasmToUse(is_alternate_isa);
+ GetDisasmToUse(is_alternate_isa, disasm);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
llvm::MCInst inst;
@@ -160,27 +153,14 @@ public:
m_has_delay_slot = eLazyBoolNo;
}
}
- disasm_sp->Unlock();
}
}
return m_has_delay_slot == eLazyBoolYes;
}
DisassemblerLLVMC::MCDisasmInstance *GetDisasmToUse(bool &is_alternate_isa) {
- is_alternate_isa = false;
- std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
- if (disasm_sp) {
- if (disasm_sp->m_alternate_disasm_up) {
- const AddressClass address_class = GetAddressClass();
-
- if (address_class == AddressClass::eCodeAlternateISA) {
- is_alternate_isa = true;
- return disasm_sp->m_alternate_disasm_up.get();
- }
- }
- return disasm_sp->m_disasm_up.get();
- }
- return nullptr;
+ DisassemblerScope disasm(*this);
+ return GetDisasmToUse(is_alternate_isa, disasm);
}
size_t Decode(const lldb_private::Disassembler &disassembler,
@@ -189,9 +169,9 @@ public:
// All we have to do is read the opcode which can be easy for some
// architectures
bool got_op = false;
- std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
- if (disasm_sp) {
- const ArchSpec &arch = disasm_sp->GetArchitecture();
+ DisassemblerScope disasm(*this);
+ if (disasm) {
+ const ArchSpec &arch = disasm->GetArchitecture();
const lldb::ByteOrder byte_order = data.GetByteOrder();
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
@@ -232,7 +212,7 @@ public:
if (!got_op) {
bool is_alternate_isa = false;
DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
- GetDisasmToUse(is_alternate_isa);
+ GetDisasmToUse(is_alternate_isa, disasm);
const llvm::Triple::ArchType machine = arch.GetMachine();
if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) {
@@ -261,10 +241,8 @@ public:
const addr_t pc = m_address.GetFileAddress();
llvm::MCInst inst;
- disasm_sp->Lock(this, NULL);
const size_t inst_size =
mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst);
- disasm_sp->Unlock();
if (inst_size == 0)
m_opcode.Clear();
else {
@@ -296,19 +274,19 @@ public:
std::string out_string;
std::string comment_string;
- std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
- if (disasm_sp) {
+ DisassemblerScope disasm(*this, exe_ctx);
+ if (disasm) {
DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr;
if (address_class == AddressClass::eCodeAlternateISA)
- mc_disasm_ptr = disasm_sp->m_alternate_disasm_up.get();
+ mc_disasm_ptr = disasm->m_alternate_disasm_up.get();
else
- mc_disasm_ptr = disasm_sp->m_disasm_up.get();
+ mc_disasm_ptr = disasm->m_disasm_up.get();
lldb::addr_t pc = m_address.GetFileAddress();
m_using_file_addr = true;
- const bool data_from_file = disasm_sp->m_data_from_file;
+ const bool data_from_file = disasm->m_data_from_file;
bool use_hex_immediates = true;
Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
@@ -328,8 +306,6 @@ public:
}
}
- disasm_sp->Lock(this, exe_ctx);
-
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
llvm::MCInst inst;
@@ -345,8 +321,6 @@ public:
}
}
- disasm_sp->Unlock();
-
if (inst_size == 0) {
m_comment.assign("unknown opcode");
inst_size = m_opcode.GetByteSize();
@@ -423,9 +397,27 @@ public:
bool UsingFileAddress() const { return m_using_file_addr; }
size_t GetByteSize() const { return m_opcode.GetByteSize(); }
- std::shared_ptr<DisassemblerLLVMC> GetDisassembler() {
- return m_disasm_wp.lock();
- }
+ /// Grants exclusive access to the disassembler and initializes it with the
+ /// given InstructionLLVMC and an optional ExecutionContext.
+ class DisassemblerScope {
+ std::shared_ptr<DisassemblerLLVMC> m_disasm;
+
+ public:
+ explicit DisassemblerScope(
+ InstructionLLVMC &i,
+ const lldb_private::ExecutionContext *exe_ctx = nullptr)
+ : m_disasm(i.m_disasm_wp.lock()) {
+ m_disasm->m_mutex.lock();
+ m_disasm->m_inst = &i;
+ m_disasm->m_exe_ctx = exe_ctx;
+ }
+ ~DisassemblerScope() { m_disasm->m_mutex.unlock(); }
+
+ /// Evaluates to true if this scope contains a valid disassembler.
+ operator bool() const { return static_cast<bool>(m_disasm); }
+
+ std::shared_ptr<DisassemblerLLVMC> operator->() { return m_disasm; }
+ };
static llvm::StringRef::const_iterator
ConsumeWhitespace(llvm::StringRef::const_iterator osi,
@@ -876,16 +868,15 @@ public:
bool IsCall() override {
if (m_is_call == eLazyBoolCalculate) {
- std::shared_ptr<DisassemblerLLVMC> disasm_sp(GetDisassembler());
- if (disasm_sp) {
- disasm_sp->Lock(this, NULL);
+ DisassemblerScope disasm(*this);
+ if (disasm) {
DataExtractor data;
if (m_opcode.GetData(data)) {
bool is_alternate_isa;
lldb::addr_t pc = m_address.GetFileAddress();
DisassemblerLLVMC::MCDisasmInstance *mc_disasm_ptr =
- GetDisasmToUse(is_alternate_isa);
+ GetDisasmToUse(is_alternate_isa, disasm);
const uint8_t *opcode_data = data.GetDataStart();
const size_t opcode_data_len = data.GetByteSize();
llvm::MCInst inst;
@@ -900,7 +891,6 @@ public:
m_is_call = eLazyBoolNo;
}
}
- disasm_sp->Unlock();
}
}
return m_is_call == eLazyBoolYes;
@@ -913,6 +903,24 @@ protected:
LazyBool m_is_call;
bool m_is_valid;
bool m_using_file_addr;
+
+private:
+ DisassemblerLLVMC::MCDisasmInstance *
+ GetDisasmToUse(bool &is_alternate_isa, DisassemblerScope &disasm) {
+ is_alternate_isa = false;
+ if (disasm) {
+ if (disasm->m_alternate_disasm_up) {
+ const AddressClass address_class = GetAddressClass();
+
+ if (address_class == AddressClass::eCodeAlternateISA) {
+ is_alternate_isa = true;
+ return disasm->m_alternate_disasm_up.get();
+ }
+ }
+ return disasm->m_disasm_up.get();
+ }
+ return nullptr;
+ }
};
std::unique_ptr<DisassemblerLLVMC::MCDisasmInstance>
@@ -1114,11 +1122,13 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
triple.getSubArch() == llvm::Triple::NoSubArch)
triple.setArchName("armv8.2a");
+ std::string features_str = "";
const char *triple_str = triple.getTriple().c_str();
// ARM Cortex M0-M7 devices only execute thumb instructions
if (arch.IsAlwaysThumbInstructions()) {
triple_str = thumb_arch.GetTriple().getTriple().c_str();
+ features_str += "+fp-armv8,";
}
const char *cpu = "";
@@ -1169,7 +1179,6 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
break;
}
- std::string features_str = "";
if (triple.getArch() == llvm::Triple::mips ||
triple.getArch() == llvm::Triple::mipsel ||
triple.getArch() == llvm::Triple::mips64 ||
@@ -1201,7 +1210,8 @@ DisassemblerLLVMC::DisassemblerLLVMC(const ArchSpec &arch,
if (llvm_arch == llvm::Triple::arm) {
std::string thumb_triple(thumb_arch.GetTriple().getTriple());
m_alternate_disasm_up =
- MCDisasmInstance::Create(thumb_triple.c_str(), "", "", flavor, *this);
+ MCDisasmInstance::Create(thumb_triple.c_str(), "", features_str.c_str(),
+ flavor, *this);
if (!m_alternate_disasm_up)
m_disasm_up.reset();
@@ -1326,10 +1336,7 @@ bool DisassemblerLLVMC::FlavorValidForArchSpec(
if (triple.getArch() == llvm::Triple::x86 ||
triple.getArch() == llvm::Triple::x86_64) {
- if (strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0)
- return true;
- else
- return false;
+ return strcmp(flavor, "intel") == 0 || strcmp(flavor, "att") == 0;
} else
return false;
}
@@ -1368,7 +1375,7 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr,
}
SymbolContext sym_ctx;
- const uint32_t resolve_scope =
+ const SymbolContextItem resolve_scope =
eSymbolContextFunction | eSymbolContextSymbol;
if (pc_so_addr.IsValid() && pc_so_addr.GetModule()) {
pc_so_addr.GetModule()->ResolveSymbolContextForAddress(
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
index b7e9ccb34701..8b9f7c37d2b8 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -10,13 +10,10 @@
#ifndef liblldb_DisassemblerLLVMC_h_
#define liblldb_DisassemblerLLVMC_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <mutex>
#include <string>
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/PluginManager.h"
@@ -77,19 +74,6 @@ protected:
uint64_t ReferencePC,
const char **ReferenceName);
- void Lock(InstructionLLVMC *inst,
- const lldb_private::ExecutionContext *exe_ctx) {
- m_mutex.lock();
- m_inst = inst;
- m_exe_ctx = exe_ctx;
- }
-
- void Unlock() {
- m_inst = NULL;
- m_exe_ctx = NULL;
- m_mutex.unlock();
- }
-
const lldb_private::ExecutionContext *m_exe_ctx;
InstructionLLVMC *m_inst;
std::mutex m_mutex;
diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
index 8999000dff8c..3a80c68dd4d7 100644
--- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
+++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp
@@ -15,7 +15,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Interpreter/OptionValueProperties.h"
@@ -29,6 +28,7 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "DynamicLoaderDarwinKernel.h"
@@ -58,7 +58,7 @@ enum KASLRScanType {
// range looking for a kernel
};
-OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = {
+static constexpr OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = {
{eKASLRScanNone, "none",
"Do not read memory looking for a Darwin kernel when attaching."},
{eKASLRScanLowgloAddresses, "basic", "Check for the Darwin kernel's load "
@@ -68,17 +68,15 @@ OptionEnumValueElement g_kaslr_kernel_scan_enum_values[] = {
"the Darwin kernel's load address."},
{eKASLRScanExhaustiveScan, "exhaustive-scan",
"Scan through the entire potential address range of Darwin kernel (only "
- "on 32-bit targets)."},
- {0, NULL, NULL}};
+ "on 32-bit targets)."}};
-static PropertyDefinition g_properties[] = {
- {"load-kexts", OptionValue::eTypeBoolean, true, true, NULL, NULL,
+static constexpr PropertyDefinition g_properties[] = {
+ {"load-kexts", OptionValue::eTypeBoolean, true, true, NULL, {},
"Automatically loads kext images when attaching to a kernel."},
{"scan-type", OptionValue::eTypeEnum, true, eKASLRScanNearPC, NULL,
- g_kaslr_kernel_scan_enum_values, "Control how many reads lldb will make "
- "while searching for a Darwin kernel on "
- "attach."},
- {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
+ OptionEnumValues(g_kaslr_kernel_scan_enum_values),
+ "Control how many reads lldb will make while searching for a Darwin "
+ "kernel on attach."}};
enum { ePropertyLoadKexts, ePropertyScanType };
@@ -149,6 +147,7 @@ DynamicLoader *DynamicLoaderDarwinKernel::CreateInstance(Process *process,
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
case llvm::Triple::WatchOS:
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
if (triple_ref.getVendor() != llvm::Triple::Apple) {
return NULL;
}
@@ -212,13 +211,13 @@ DynamicLoaderDarwinKernel::SearchForKernelAtSameLoadAddr(Process *process) {
exe_objfile->GetStrata() != ObjectFile::eStrataKernel)
return LLDB_INVALID_ADDRESS;
- if (!exe_objfile->GetHeaderAddress().IsValid())
+ if (!exe_objfile->GetBaseAddress().IsValid())
return LLDB_INVALID_ADDRESS;
if (CheckForKernelImageAtAddress(
- exe_objfile->GetHeaderAddress().GetFileAddress(), process) ==
+ exe_objfile->GetBaseAddress().GetFileAddress(), process) ==
exe_module->GetUUID())
- return exe_objfile->GetHeaderAddress().GetFileAddress();
+ return exe_objfile->GetBaseAddress().GetFileAddress();
return LLDB_INVALID_ADDRESS;
}
@@ -294,6 +293,18 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) {
return LLDB_INVALID_ADDRESS;
addr_t pc = thread->GetRegisterContext()->GetPC(LLDB_INVALID_ADDRESS);
+ // The kernel is always loaded in high memory, if the top bit is zero,
+ // this isn't a kernel.
+ if (process->GetTarget().GetArchitecture().GetAddressByteSize() == 8) {
+ if ((pc & (1ULL << 63)) == 0) {
+ return LLDB_INVALID_ADDRESS;
+ }
+ } else {
+ if ((pc & (1ULL << 31)) == 0) {
+ return LLDB_INVALID_ADDRESS;
+ }
+ }
+
if (pc == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
@@ -308,12 +319,13 @@ DynamicLoaderDarwinKernel::SearchForKernelNearPC(Process *process) {
// Search backwards 32 megabytes, looking for the start of the kernel at each
// one-megabyte boundary.
for (int i = 0; i < 32; i++, addr -= 0x100000) {
+ // x86_64 kernels are at offset 0
if (CheckForKernelImageAtAddress(addr, process).IsValid())
return addr;
+ // 32-bit arm kernels are at offset 0x1000 (one 4k page)
if (CheckForKernelImageAtAddress(addr + 0x1000, process).IsValid())
return addr + 0x1000;
- if (CheckForKernelImageAtAddress(addr + 0x2000, process).IsValid())
- return addr + 0x2000;
+ // 64-bit arm kernels are at offset 0x4000 (one 16k page)
if (CheckForKernelImageAtAddress(addr + 0x4000, process).IsValid())
return addr + 0x4000;
}
@@ -352,12 +364,13 @@ lldb::addr_t DynamicLoaderDarwinKernel::SearchForKernelViaExhaustiveSearch(
addr_t addr = kernel_range_low;
while (addr >= kernel_range_low && addr < kernel_range_high) {
+ // x86_64 kernels are at offset 0
if (CheckForKernelImageAtAddress(addr, process).IsValid())
return addr;
+ // 32-bit arm kernels are at offset 0x1000 (one 4k page)
if (CheckForKernelImageAtAddress(addr + 0x1000, process).IsValid())
return addr + 0x1000;
- if (CheckForKernelImageAtAddress(addr + 0x2000, process).IsValid())
- return addr + 0x2000;
+ // 64-bit arm kernels are at offset 0x4000 (one 16k page)
if (CheckForKernelImageAtAddress(addr + 0x4000, process).IsValid())
return addr + 0x4000;
addr += 0x100000;
@@ -388,8 +401,8 @@ DynamicLoaderDarwinKernel::ReadMachHeader(addr_t addr, Process *process, llvm::M
if (::memcmp (&header.magic, &magicks[i], sizeof (uint32_t)) == 0)
found_matching_pattern = true;
- if (found_matching_pattern == false)
- return false;
+ if (!found_matching_pattern)
+ return false;
if (header.magic == llvm::MachO::MH_CIGAM ||
header.magic == llvm::MachO::MH_CIGAM_64) {
@@ -425,7 +438,7 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
llvm::MachO::mach_header header;
- if (ReadMachHeader (addr, process, header) == false)
+ if (!ReadMachHeader(addr, process, header))
return UUID();
// First try a quick test -- read the first 4 bytes and see if there is a
@@ -436,8 +449,8 @@ DynamicLoaderDarwinKernel::CheckForKernelImageAtAddress(lldb::addr_t addr,
if (header.filetype == llvm::MachO::MH_EXECUTE &&
(header.flags & llvm::MachO::MH_DYLDLINK) == 0) {
// Create a full module to get the UUID
- ModuleSP memory_module_sp = process->ReadModuleFromMemory(
- FileSpec("temp_mach_kernel", false), addr);
+ ModuleSP memory_module_sp =
+ process->ReadModuleFromMemory(FileSpec("temp_mach_kernel"), addr);
if (!memory_module_sp.get())
return UUID();
@@ -605,16 +618,10 @@ void DynamicLoaderDarwinKernel::KextImageInfo::SetProcessStopId(
bool DynamicLoaderDarwinKernel::KextImageInfo::
operator==(const KextImageInfo &rhs) {
if (m_uuid.IsValid() || rhs.GetUUID().IsValid()) {
- if (m_uuid == rhs.GetUUID()) {
- return true;
- }
- return false;
+ return m_uuid == rhs.GetUUID();
}
- if (m_name == rhs.GetName() && m_load_address == rhs.GetLoadAddress())
- return true;
-
- return false;
+ return m_name == rhs.GetName() && m_load_address == rhs.GetLoadAddress();
}
void DynamicLoaderDarwinKernel::KextImageInfo::SetName(const char *name) {
@@ -647,16 +654,16 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule(
if (m_load_address == LLDB_INVALID_ADDRESS)
return false;
- FileSpec file_spec;
- file_spec.SetFile(m_name.c_str(), false, FileSpec::Style::native);
+ FileSpec file_spec(m_name.c_str());
llvm::MachO::mach_header mh;
size_t size_to_read = 512;
- if (ReadMachHeader (m_load_address, process, mh)) {
- if (mh.magic == llvm::MachO::MH_CIGAM || llvm::MachO::MH_MAGIC)
- size_to_read = sizeof (llvm::MachO::mach_header) + mh.sizeofcmds;
- if (mh.magic == llvm::MachO::MH_CIGAM_64 || llvm::MachO::MH_MAGIC_64)
- size_to_read = sizeof (llvm::MachO::mach_header_64) + mh.sizeofcmds;
+ if (ReadMachHeader(m_load_address, process, mh)) {
+ if (mh.magic == llvm::MachO::MH_CIGAM || mh.magic == llvm::MachO::MH_MAGIC)
+ size_to_read = sizeof(llvm::MachO::mach_header) + mh.sizeofcmds;
+ if (mh.magic == llvm::MachO::MH_CIGAM_64 ||
+ mh.magic == llvm::MachO::MH_MAGIC_64)
+ size_to_read = sizeof(llvm::MachO::mach_header_64) + mh.sizeofcmds;
}
ModuleSP memory_module_sp =
@@ -732,7 +739,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::ReadMemoryModule(
}
bool DynamicLoaderDarwinKernel::KextImageInfo::IsKernel() const {
- return m_kernel_image == true;
+ return m_kernel_image;
}
void DynamicLoaderDarwinKernel::KextImageInfo::SetIsKernel(bool is_kernel) {
@@ -784,7 +791,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
// to do anything useful. This will force a clal to
if (IsKernel()) {
if (Symbols::DownloadObjectAndSymbolFile(module_spec, true)) {
- if (module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
m_module_sp.reset(new Module(module_spec.GetFileSpec(),
target.GetArchitecture()));
if (m_module_sp.get() &&
@@ -807,7 +814,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
PlatformDarwinKernel::GetPluginNameStatic());
if (platform_name == g_platform_name) {
ModuleSpec kext_bundle_module_spec(module_spec);
- FileSpec kext_filespec(m_name.c_str(), false);
+ FileSpec kext_filespec(m_name.c_str());
kext_bundle_module_spec.GetFileSpec() = kext_filespec;
platform_sp->GetSharedModule(
kext_bundle_module_spec, process, m_module_sp,
@@ -847,7 +854,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
target.GetImages().AppendIfNeeded(m_module_sp);
if (IsKernel() &&
target.GetExecutableModulePointer() != m_module_sp.get()) {
- target.SetExecutableModule(m_module_sp, false);
+ target.SetExecutableModule(m_module_sp, eLoadDependentsNo);
}
}
}
@@ -932,7 +939,7 @@ bool DynamicLoaderDarwinKernel::KextImageInfo::LoadImageUsingMemoryModule(
ObjectFile *kernel_object_file = m_module_sp->GetObjectFile();
if (kernel_object_file) {
addr_t file_address =
- kernel_object_file->GetHeaderAddress().GetFileAddress();
+ kernel_object_file->GetBaseAddress().GetFileAddress();
if (m_load_address != LLDB_INVALID_ADDRESS &&
file_address != LLDB_INVALID_ADDRESS) {
s->Printf("Kernel slid 0x%" PRIx64 " in memory.\n",
@@ -1006,10 +1013,10 @@ void DynamicLoaderDarwinKernel::LoadKernelModuleIfNeeded() {
ObjectFile *kernel_object_file = m_kernel.GetModule()->GetObjectFile();
if (kernel_object_file) {
addr_t load_address =
- kernel_object_file->GetHeaderAddress().GetLoadAddress(
+ kernel_object_file->GetBaseAddress().GetLoadAddress(
&m_process->GetTarget());
addr_t file_address =
- kernel_object_file->GetHeaderAddress().GetFileAddress();
+ kernel_object_file->GetBaseAddress().GetFileAddress();
if (load_address != LLDB_INVALID_ADDRESS && load_address != 0) {
m_kernel.SetLoadAddress(load_address);
if (load_address != file_address) {
@@ -1281,7 +1288,7 @@ bool DynamicLoaderDarwinKernel::ParseKextSummaries(
const uint32_t num_of_new_kexts = kext_summaries.size();
for (uint32_t new_kext = 0; new_kext < num_of_new_kexts; new_kext++) {
- if (to_be_added[new_kext] == true) {
+ if (to_be_added[new_kext]) {
KextImageInfo &image_info = kext_summaries[new_kext];
if (load_kexts) {
if (!image_info.LoadImageUsingMemoryModule(m_process)) {
diff --git a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
index 75998f1cc3be..7aacebd9b50f 100644
--- a/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
+++ b/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
@@ -10,17 +10,13 @@
#ifndef liblldb_DynamicLoaderDarwinKernel_h_
#define liblldb_DynamicLoaderDarwinKernel_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <string>
#include <vector>
-// Other libraries and framework includes
-#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Host/SafeMachO.h"
-// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
index 5ca20229d018..81eab8fdd970 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.cpp
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
@@ -179,7 +176,7 @@ ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() {
return executable;
// The target executable file does not exits
- if (!executable->GetFileSpec().Exists())
+ if (!FileSystem::Instance().Exists(executable->GetFileSpec()))
return executable;
// Prep module for loading
@@ -205,8 +202,7 @@ ModuleSP DynamicLoaderHexagonDYLD::GetTargetExecutable() {
if (executable.get() != target.GetExecutableModulePointer()) {
// Don't load dependent images since we are in dyld where we will know and
// find out about all images that are loaded
- const bool get_dependent_images = false;
- target.SetExecutableModule(executable, get_dependent_images);
+ target.SetExecutableModule(executable, eLoadDependentsNo);
}
return executable;
@@ -368,7 +364,8 @@ void DynamicLoaderHexagonDYLD::RefreshModules() {
E = m_rendezvous.loaded_end();
for (I = m_rendezvous.loaded_begin(); I != E; ++I) {
- FileSpec file(I->path, true);
+ FileSpec file(I->path);
+ FileSystem::Instance().Resolve(file);
ModuleSP module_sp =
LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get()) {
@@ -392,7 +389,8 @@ void DynamicLoaderHexagonDYLD::RefreshModules() {
E = m_rendezvous.unloaded_end();
for (I = m_rendezvous.unloaded_begin(); I != E; ++I) {
- FileSpec file(I->path, true);
+ FileSpec file(I->path);
+ FileSystem::Instance().Resolve(file);
ModuleSpec module_spec(file);
ModuleSP module_sp = loaded_modules.FindFirstModule(module_spec);
@@ -455,7 +453,7 @@ DynamicLoaderHexagonDYLD::GetStepThroughTrampolinePlan(Thread &thread,
AddressVector::iterator start = addrs.begin();
AddressVector::iterator end = addrs.end();
- std::sort(start, end);
+ llvm::sort(start, end);
addrs.erase(std::unique(start, end), end);
thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
}
@@ -486,7 +484,7 @@ void DynamicLoaderHexagonDYLD::LoadAllCurrentModules() {
for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) {
const char *module_path = I->path.c_str();
- FileSpec file(module_path, false);
+ FileSpec file(module_path);
ModuleSP module_sp =
LoadModuleAtAddress(file, I->link_addr, I->base_addr, true);
if (module_sp.get()) {
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
index 200a4171bd1c..d39f14e8b3fb 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/DynamicLoaderHexagonDYLD.h
@@ -10,10 +10,6 @@
#ifndef liblldb_DynamicLoaderHexagonDYLD_h_
#define liblldb_DynamicLoaderHexagonDYLD_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Target/DynamicLoader.h"
diff --git a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
index bdf6bae75197..758f358dc618 100644
--- a/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.h
@@ -10,14 +10,11 @@
#ifndef liblldb_HexagonDYLDRendezvous_H_
#define liblldb_HexagonDYLDRendezvous_H_
-// C Includes
-#include <limits.h> // for PATH_MAX
-// C++ Includes
+#include <limits.h>
#include <list>
#include <map>
#include <string>
-// Other libraries and framework includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
index c6439a30c8a3..944be9633e00 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp
@@ -15,7 +15,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -32,6 +31,7 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
//#define ENABLE_DEBUG_PRINTF // COMMENT THIS LINE OUT PRIOR TO CHECKIN
#ifdef ENABLE_DEBUG_PRINTF
@@ -115,7 +115,7 @@ ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo(
// No UUID, we must rely upon the cached module modification time and the
// modification time of the file on disk
if (module_sp->GetModificationTime() !=
- FileSystem::GetModificationTime(module_sp->GetFileSpec()))
+ FileSystem::Instance().GetModificationTime(module_sp->GetFileSpec()))
module_sp.reset();
}
@@ -359,22 +359,24 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
if (image_sp.get() == nullptr || image_sp->GetAsDictionary() == nullptr)
return false;
StructuredData::Dictionary *image = image_sp->GetAsDictionary();
- if (image->HasKey("load_address") == false ||
- image->HasKey("pathname") == false ||
- image->HasKey("mod_date") == false ||
- image->HasKey("mach_header") == false ||
+ // clang-format off
+ if (!image->HasKey("load_address") ||
+ !image->HasKey("pathname") ||
+ !image->HasKey("mod_date") ||
+ !image->HasKey("mach_header") ||
image->GetValueForKey("mach_header")->GetAsDictionary() == nullptr ||
- image->HasKey("segments") == false ||
+ !image->HasKey("segments") ||
image->GetValueForKey("segments")->GetAsArray() == nullptr ||
- image->HasKey("uuid") == false) {
+ !image->HasKey("uuid")) {
return false;
}
+ // clang-format on
image_infos[i].address =
image->GetValueForKey("load_address")->GetAsInteger()->GetValue();
image_infos[i].mod_date =
image->GetValueForKey("mod_date")->GetAsInteger()->GetValue();
image_infos[i].file_spec.SetFile(
- image->GetValueForKey("pathname")->GetAsString()->GetValue(), false,
+ image->GetValueForKey("pathname")->GetAsString()->GetValue(),
FileSpec::Style::native);
StructuredData::Dictionary *mh =
@@ -400,6 +402,8 @@ bool DynamicLoaderDarwin::JSONImageInformationIntoImageInfo(
image_infos[i].os_type = llvm::Triple::TvOS;
else if (os_name == "watchos")
image_infos[i].os_type = llvm::Triple::WatchOS;
+ // NEED_BRIDGEOS_TRIPLE else if (os_name == "bridgeos")
+ // NEED_BRIDGEOS_TRIPLE image_infos[i].os_type = llvm::Triple::BridgeOS;
}
if (image->HasKey("min_version_os_sdk")) {
image_infos[i].min_version_os_sdk =
@@ -513,11 +517,12 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos(
const size_t image_infos_size = image_infos.size();
for (size_t i = 0; i < image_infos_size; i++) {
if (image_infos[i].header.filetype == llvm::MachO::MH_DYLINKER) {
- // In a "simulator" process (an x86 process that is ios/tvos/watchos) we
- // will have two dyld modules -- a "dyld" that we want to keep track of,
- // and a "dyld_sim" which we don't need to keep track of here. If the
- // target is an x86 system and the OS of the dyld binary is
- // ios/tvos/watchos, then we are looking at dyld_sym.
+ // In a "simulator" process (an x86 process that is
+ // ios/tvos/watchos/bridgeos) we will have two dyld modules --
+ // a "dyld" that we want to keep track of, and a "dyld_sim" which
+ // we don't need to keep track of here. If the target is an x86
+ // system and the OS of the dyld binary is ios/tvos/watchos/bridgeos,
+ // then we are looking at dyld_sym.
// debugserver has only recently (late 2016) started sending up the os
// type for each binary it sees -- so if we don't have an os type, use a
@@ -531,6 +536,7 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos(
if (image_infos[i].os_type != llvm::Triple::OSType::IOS &&
image_infos[i].os_type != llvm::Triple::TvOS &&
image_infos[i].os_type != llvm::Triple::WatchOS) {
+ // NEED_BRIDGEOS_TRIPLE image_infos[i].os_type != llvm::Triple::BridgeOS) {
dyld_idx = i;
}
}
@@ -555,8 +561,7 @@ void DynamicLoaderDarwin::UpdateSpecialBinariesFromNewImageInfos(
target.GetImages().AppendIfNeeded(exe_module_sp);
UpdateImageLoadAddress(exe_module_sp.get(), image_infos[exe_idx]);
if (exe_module_sp.get() != target.GetExecutableModulePointer()) {
- const bool get_dependent_images = false;
- target.SetExecutableModule(exe_module_sp, get_dependent_images);
+ target.SetExecutableModule(exe_module_sp, eLoadDependentsNo);
}
}
}
@@ -709,11 +714,7 @@ bool DynamicLoaderDarwin::AlwaysRelyOnEHUnwindInfo(SymbolContext &sym_ctx) {
return false;
ObjCLanguageRuntime *objc_runtime = m_process->GetObjCLanguageRuntime();
- if (objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary(module_sp)) {
- return true;
- }
-
- return false;
+ return objc_runtime != NULL && objc_runtime->IsModuleObjCLibrary(module_sp);
}
//----------------------------------------------------------------------
@@ -1124,6 +1125,10 @@ bool DynamicLoaderDarwin::UseDYLDSPI(Process *process) {
// watchOS 3 and newer
if (os_type == llvm::Triple::WatchOS && version >= llvm::VersionTuple(3))
use_new_spi_interface = true;
+
+ // NEED_BRIDGEOS_TRIPLE // Any BridgeOS
+ // NEED_BRIDGEOS_TRIPLE if (os_type == llvm::Triple::BridgeOS)
+ // NEED_BRIDGEOS_TRIPLE use_new_spi_interface = true;
}
if (log) {
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
index a02d1ad9bee3..690253ba5ff2 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.h
@@ -10,18 +10,14 @@
#ifndef liblldb_DynamicLoaderDarwin_h_
#define liblldb_DynamicLoaderDarwin_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
index 4a8ad38d1785..1ff0ec2c7937 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp
@@ -12,7 +12,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolVendor.h"
@@ -21,6 +20,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "DynamicLoaderDarwin.h"
#include "DynamicLoaderMacOS.h"
@@ -55,6 +55,7 @@ DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process,
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
case llvm::Triple::WatchOS:
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
create = triple_ref.getVendor() == llvm::Triple::Apple;
break;
default:
@@ -64,7 +65,7 @@ DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process,
}
}
- if (UseDYLDSPI(process) == false) {
+ if (!UseDYLDSPI(process)) {
create = false;
}
@@ -78,7 +79,8 @@ DynamicLoader *DynamicLoaderMacOS::CreateInstance(Process *process,
//----------------------------------------------------------------------
DynamicLoaderMacOS::DynamicLoaderMacOS(Process *process)
: DynamicLoaderDarwin(process), m_image_infos_stop_id(UINT32_MAX),
- m_break_id(LLDB_INVALID_BREAK_ID), m_mutex() {}
+ m_break_id(LLDB_INVALID_BREAK_ID), m_mutex(),
+ m_maybe_image_infos_address(LLDB_INVALID_ADDRESS) {}
//----------------------------------------------------------------------
// Destructor
@@ -94,16 +96,31 @@ bool DynamicLoaderMacOS::ProcessDidExec() {
if (m_process) {
// If we are stopped after an exec, we will have only one thread...
if (m_process->GetThreadList().GetSize() == 1) {
- // See if we are stopped at '_dyld_start'
- ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
- if (thread_sp) {
- lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
- if (frame_sp) {
- const Symbol *symbol =
- frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
- if (symbol) {
- if (symbol->GetName() == ConstString("_dyld_start"))
- did_exec = true;
+ // Maybe we still have an image infos address around? If so see
+ // if that has changed, and if so we have exec'ed.
+ if (m_maybe_image_infos_address != LLDB_INVALID_ADDRESS) {
+ lldb::addr_t image_infos_address = m_process->GetImageInfoAddress();
+ if (image_infos_address != m_maybe_image_infos_address) {
+ // We don't really have to reset this here, since we are going to
+ // call DoInitialImageFetch right away to handle the exec. But in
+ // case anybody looks at it in the meantime, it can't hurt.
+ m_maybe_image_infos_address = image_infos_address;
+ did_exec = true;
+ }
+ }
+
+ if (!did_exec) {
+ // See if we are stopped at '_dyld_start'
+ ThreadSP thread_sp(m_process->GetThreadList().GetThreadAtIndex(0));
+ if (thread_sp) {
+ lldb::StackFrameSP frame_sp(thread_sp->GetStackFrameAtIndex(0));
+ if (frame_sp) {
+ const Symbol *symbol =
+ frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+ if (symbol) {
+ if (symbol->GetName() == ConstString("_dyld_start"))
+ did_exec = true;
+ }
}
}
}
@@ -179,6 +196,7 @@ void DynamicLoaderMacOS::DoInitialImageFetch() {
}
m_dyld_image_infos_stop_id = m_process->GetStopID();
+ m_maybe_image_infos_address = m_process->GetImageInfoAddress();
}
bool DynamicLoaderMacOS::NeedToDoInitialImageFetch() { return true; }
@@ -485,8 +503,7 @@ bool DynamicLoaderMacOS::GetSharedCacheInformation(
info_dict->GetValueForKey("shared_cache_uuid")->GetStringValue();
if (!uuid_str.empty())
uuid.SetFromStringRef(uuid_str);
- if (info_dict->GetValueForKey("no_shared_cache")->GetBooleanValue() ==
- false)
+ if (!info_dict->GetValueForKey("no_shared_cache")->GetBooleanValue())
using_shared_cache = eLazyBoolYes;
else
using_shared_cache = eLazyBoolNo;
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
index db90966e5615..6303c066511c 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS /
-// watchOS)
+// watchOS / BridgeOS)
// platforms late 2016 and newer, where lldb will call dyld SPI functions to get
// information about shared libraries, information about the shared cache, and
// the _dyld_debugger_notification function we put a breakpoint on give us an
@@ -18,17 +18,12 @@
#ifndef liblldb_DynamicLoaderMacOS_h_
#define liblldb_DynamicLoaderMacOS_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"
@@ -109,6 +104,12 @@ protected:
// loaded/unloaded images
lldb::user_id_t m_break_id;
mutable std::recursive_mutex m_mutex;
+ lldb::addr_t m_maybe_image_infos_address; // If dyld is still maintaining the
+ // all_image_infos address, store it
+ // here so we can use it to detect
+ // exec's when talking to
+ // debugservers that don't support
+ // the "reason:exec" annotation.
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderMacOS);
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index 265f19d0ca06..ec459a783f94 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -13,7 +13,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -27,6 +26,7 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "DynamicLoaderDarwin.h"
#include "DynamicLoaderMacOSXDYLD.h"
@@ -75,6 +75,7 @@ DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process,
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
case llvm::Triple::WatchOS:
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
create = triple_ref.getVendor() == llvm::Triple::Apple;
break;
default:
@@ -84,7 +85,7 @@ DynamicLoader *DynamicLoaderMacOSXDYLD::CreateInstance(Process *process,
}
}
- if (UseDYLDSPI(process) == true) {
+ if (UseDYLDSPI(process)) {
create = false;
}
@@ -121,12 +122,12 @@ bool DynamicLoaderMacOSXDYLD::ProcessDidExec() {
// value differs from the Process' image info address. When a process
// execs itself it might cause a change if ASLR is enabled.
const addr_t shlib_addr = m_process->GetImageInfoAddress();
- if (m_process_image_addr_is_all_images_infos == true &&
+ if (m_process_image_addr_is_all_images_infos &&
shlib_addr != m_dyld_all_image_infos_addr) {
// The image info address from the process is the
// 'dyld_all_image_infos' address and it has changed.
did_exec = true;
- } else if (m_process_image_addr_is_all_images_infos == false &&
+ } else if (!m_process_image_addr_is_all_images_infos &&
shlib_addr == m_dyld.address) {
// The image info address from the process is the mach_header address
// for dyld and it has changed.
@@ -692,9 +693,7 @@ bool DynamicLoaderMacOSXDYLD::ReadImageInfos(
error);
// don't resolve the path
if (error.Success()) {
- const bool resolve_path = false;
- image_infos[i].file_spec.SetFile(raw_path, resolve_path,
- FileSpec::Style::native);
+ image_infos[i].file_spec.SetFile(raw_path, FileSpec::Style::native);
}
}
return true;
@@ -893,7 +892,8 @@ uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data,
const lldb::offset_t name_offset =
load_cmd_offset + data.GetU32(&offset);
const char *path = data.PeekCStr(name_offset);
- lc_id_dylinker->SetFile(path, true, FileSpec::Style::native);
+ lc_id_dylinker->SetFile(path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(*lc_id_dylinker);
}
break;
@@ -975,9 +975,8 @@ void DynamicLoaderMacOSXDYLD::UpdateImageInfosHeaderAndLoadCommands(
// re-add it back to make sure it is always in the list.
ModuleSP dyld_module_sp(GetDYLDModule());
- const bool get_dependent_images = false;
m_process->GetTarget().SetExecutableModule(exe_module_sp,
- get_dependent_images);
+ eLoadDependentsNo);
if (dyld_module_sp) {
if (target.GetImages().AppendIfNeeded(dyld_module_sp)) {
diff --git a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
index 8b5052e4e230..3dc0f15bddf7 100644
--- a/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
+++ b/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
// This is the DynamicLoader plugin for Darwin (macOS / iPhoneOS / tvOS /
-// watchOS)
+// watchOS / BridgeOS)
// platforms earlier than 2016, where lldb would read the "dyld_all_image_infos"
// dyld internal structure to understand where things were loaded and the
// solib loaded/unloaded notification function we put a breakpoint on gives us
@@ -21,17 +21,13 @@
#ifndef liblldb_DynamicLoaderMacOSXDYLD_h_
#define liblldb_DynamicLoaderMacOSXDYLD_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UUID.h"
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
index 7dd2b57da0cb..8068795df53a 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
@@ -100,7 +100,7 @@ const char *AuxVector::GetEntryName(EntryType type) {
#define ENTRY_NAME(_type) \
_type: \
- name = #_type + 5
+ name = &#_type[5]
switch (type) {
case ENTRY_NAME(AUXV_AT_NULL); break;
case ENTRY_NAME(AUXV_AT_IGNORE); break;
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
index 3b06fe18f0c6..25446e33afd4 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
@@ -10,11 +10,8 @@
#ifndef liblldb_AuxVector_H_
#define liblldb_AuxVector_H_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "lldb/lldb-forward.h"
namespace lldb_private {
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index b1513b51a90a..b30a1ab2cf1f 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -243,7 +243,7 @@ bool DYLDRendezvous::FillSOEntryFromModuleInfo(
entry.base_addr = base_addr;
entry.dyn_addr = dyn_addr;
- entry.file_spec.SetFile(name, false, FileSpec::Style::native);
+ entry.file_spec.SetFile(name, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, name);
@@ -455,14 +455,10 @@ static bool isLoadBiasIncorrect(Target &target, const std::string &file_path) {
// On Android L (API 21, 22) the load address of the "/system/bin/linker"
// isn't filled in correctly.
unsigned os_major = target.GetPlatform()->GetOSVersion().getMajor();
- if (target.GetArchitecture().GetTriple().isAndroid() &&
- (os_major == 21 || os_major == 22) &&
- (file_path == "/system/bin/linker" ||
- file_path == "/system/bin/linker64")) {
- return true;
- }
-
- return false;
+ return target.GetArchitecture().GetTriple().isAndroid() &&
+ (os_major == 21 || os_major == 22) &&
+ (file_path == "/system/bin/linker" ||
+ file_path == "/system/bin/linker64");
}
void DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry,
@@ -517,7 +513,7 @@ bool DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry) {
return false;
std::string file_path = ReadStringFromMemory(entry.path_addr);
- entry.file_spec.SetFile(file_path, false, FileSpec::Style::native);
+ entry.file_spec.SetFile(file_path, FileSpec::Style::native);
UpdateBaseAddrIfNecessary(entry, file_path);
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index a7071801f569..f1a62c3bf9d8 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -10,12 +10,9 @@
#ifndef liblldb_Rendezvous_H_
#define liblldb_Rendezvous_H_
-// C Includes
-// C++ Includes
#include <list>
#include <string>
-// Other libraries and framework includes
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 26825d879f04..6774b4fd1291 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -10,10 +10,8 @@
// Main header include
#include "DynamicLoaderPOSIXDYLD.h"
-// Project includes
#include "AuxVector.h"
-// Other libraries and framework includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
@@ -29,8 +27,6 @@
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Utility/Log.h"
-// C++ Includes
-// C Includes
using namespace lldb;
using namespace lldb_private;
@@ -121,7 +117,7 @@ void DynamicLoaderPOSIXDYLD::DidAttach() {
EvalSpecialModulesStatus();
// if we dont have a load address we cant re-base
- bool rebase_exec = (load_offset == LLDB_INVALID_ADDRESS) ? false : true;
+ bool rebase_exec = load_offset != LLDB_INVALID_ADDRESS;
// if we have a valid executable
if (executable_sp.get()) {
@@ -500,7 +496,7 @@ DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread,
AddressVector::iterator start = addrs.begin();
AddressVector::iterator end = addrs.end();
- std::sort(start, end);
+ llvm::sort(start, end);
addrs.erase(std::unique(start, end), end);
thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
}
@@ -512,7 +508,7 @@ void DynamicLoaderPOSIXDYLD::LoadVDSO() {
if (m_vdso_base == LLDB_INVALID_ADDRESS)
return;
- FileSpec file("[vdso]", false);
+ FileSpec file("[vdso]");
MemoryRegionInfo info;
Status status = m_process->GetMemoryRegionInfo(m_vdso_base, info);
@@ -543,7 +539,7 @@ ModuleSP DynamicLoaderPOSIXDYLD::LoadInterpreterModule() {
return nullptr;
}
- FileSpec file(info.GetName().GetCString(), false);
+ FileSpec file(info.GetName().GetCString());
ModuleSpec module_spec(file, target.GetArchitecture());
if (ModuleSP module_sp = target.GetSharedModule(module_spec)) {
@@ -756,7 +752,7 @@ void DynamicLoaderPOSIXDYLD::ResolveExecutableModule(
return;
}
- target.SetExecutableModule(module_sp, false);
+ target.SetExecutableModule(module_sp, eLoadDependentsNo);
}
bool DynamicLoaderPOSIXDYLD::AlwaysRelyOnEHUnwindInfo(
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 0456baf4a658..c5f2d3bcffbc 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -10,13 +10,9 @@
#ifndef liblldb_DynamicLoaderPOSIXDYLD_h_
#define liblldb_DynamicLoaderPOSIXDYLD_h_
-// C Includes
-// C++ Includes
#include <map>
#include <memory>
-// Other libraries and framework includes
-// Project includes
#include "DYLDRendezvous.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/ModuleList.h"
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
index 2d18ec86afd3..7f8f82c76f72 100644
--- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
@@ -10,10 +10,6 @@
#ifndef liblldb_DynamicLoaderStatic_h_
#define liblldb_DynamicLoaderStatic_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
index 6502d7a7a58c..9405b1a5cfdc 100644
--- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
+++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.cpp
@@ -10,12 +10,14 @@
#include "DynamicLoaderWindowsDYLD.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Utility/Log.h"
#include "llvm/ADT/Triple.h"
@@ -60,7 +62,39 @@ DynamicLoader *DynamicLoaderWindowsDYLD::CreateInstance(Process *process,
return nullptr;
}
-void DynamicLoaderWindowsDYLD::DidAttach() {}
+void DynamicLoaderWindowsDYLD::DidAttach() {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+ if (log)
+ log->Printf("DynamicLoaderWindowsDYLD::%s()", __FUNCTION__);
+
+ ModuleSP executable = GetTargetExecutable();
+
+ if (!executable.get())
+ return;
+
+ // Try to fetch the load address of the file from the process, since there
+ // could be randomization of the load address.
+
+ // It might happen that the remote has a different dir for the file, so we
+ // only send the basename of the executable in the query. I think this is safe
+ // because I doubt that two executables with the same basenames are loaded in
+ // memory...
+ FileSpec file_spec(
+ executable->GetPlatformFileSpec().GetFilename().GetCString());
+ bool is_loaded;
+ addr_t base_addr = 0;
+ lldb::addr_t load_addr;
+ Status error = m_process->GetFileLoadAddress(file_spec, is_loaded, load_addr);
+ if (error.Success() && is_loaded) {
+ base_addr = load_addr;
+ UpdateLoadedSections(executable, LLDB_INVALID_ADDRESS, base_addr, false);
+ }
+
+ ModuleList module_list;
+ module_list.Append(executable);
+ m_process->GetTarget().ModulesDidLoad(module_list);
+ m_process->LoadModules();
+}
void DynamicLoaderWindowsDYLD::DidLaunch() {}
diff --git a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
index de6e295f7891..342b32b10927 100644
--- a/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
+++ b/source/Plugins/DynamicLoader/Windows-DYLD/DynamicLoaderWindowsDYLD.h
@@ -10,10 +10,6 @@
#ifndef liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
#define liblldb_Plugins_Process_Windows_DynamicLoaderWindowsDYLD_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/DynamicLoader.h"
#include "lldb/lldb-forward.h"
diff --git a/source/Plugins/ExpressionParser/CMakeLists.txt b/source/Plugins/ExpressionParser/CMakeLists.txt
index dc0540ad30a1..17c40aee44cc 100644
--- a/source/Plugins/ExpressionParser/CMakeLists.txt
+++ b/source/Plugins/ExpressionParser/CMakeLists.txt
@@ -1,2 +1 @@
add_subdirectory(Clang)
-add_subdirectory(Go)
diff --git a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
index fa49a51f32a6..c2bc18a04e95 100644
--- a/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp
@@ -87,7 +87,8 @@ void ASTResultSynthesizer::TransformTopLevelDecl(Decl *D) {
SynthesizeObjCMethodResult(method_decl);
}
} else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D)) {
- if (m_ast_context &&
+ // When completing user input the body of the function may be a nullptr.
+ if (m_ast_context && function_decl->hasBody() &&
!function_decl->getNameInfo().getAsString().compare("$__lldb_expr")) {
RecordPersistentTypes(function_decl);
SynthesizeFunctionResult(function_decl);
diff --git a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index d98a2b25fbb7..84771e59531d 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -332,11 +332,9 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
TypeList types;
- SymbolContext null_sc;
ConstString name(tag_decl->getName().str().c_str());
- i->first->FindTypesInNamespace(null_sc, name, &i->second, UINT32_MAX,
- types);
+ i->first->FindTypesInNamespace(name, &i->second, UINT32_MAX, types);
for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; ++ti) {
lldb::TypeSP type = types.GetTypeAtIndex(ti);
@@ -366,7 +364,6 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
} else {
TypeList types;
- SymbolContext null_sc;
ConstString name(tag_decl->getName().str().c_str());
CompilerDeclContext namespace_decl;
@@ -374,7 +371,7 @@ void ClangASTSource::CompleteType(TagDecl *tag_decl) {
bool exact_match = false;
llvm::DenseSet<SymbolFile *> searched_symbol_files;
- module_list.FindTypes(null_sc, name, exact_match, UINT32_MAX,
+ module_list.FindTypes(nullptr, name, exact_match, UINT32_MAX,
searched_symbol_files, types);
for (uint32_t ti = 0, te = types.GetSize(); ti != te && !found; ++ti) {
@@ -771,18 +768,16 @@ bool ClangASTSource::IgnoreName(const ConstString name,
static const ConstString id_name("id");
static const ConstString Class_name("Class");
- if (name == id_name || name == Class_name)
- return true;
+ if (m_ast_context->getLangOpts().ObjC)
+ if (name == id_name || name == Class_name)
+ return true;
StringRef name_string_ref = name.GetStringRef();
// The ClangASTSource is not responsible for finding $-names.
- if (name_string_ref.empty() ||
- (ignore_all_dollar_names && name_string_ref.startswith("$")) ||
- name_string_ref.startswith("_$"))
- return true;
-
- return false;
+ return name_string_ref.empty() ||
+ (ignore_all_dollar_names && name_string_ref.startswith("$")) ||
+ name_string_ref.startswith("_$");
}
void ClangASTSource::FindExternalVisibleDecls(
@@ -804,10 +799,8 @@ void ClangASTSource::FindExternalVisibleDecls(
SymbolVendor *symbol_vendor = module_sp->GetSymbolVendor();
if (symbol_vendor) {
- SymbolContext null_sc;
-
found_namespace_decl =
- symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
+ symbol_vendor->FindNamespace(name, &namespace_decl);
if (found_namespace_decl) {
context.m_namespace_map->push_back(
@@ -837,10 +830,8 @@ void ClangASTSource::FindExternalVisibleDecls(
if (!symbol_vendor)
continue;
- SymbolContext null_sc;
-
found_namespace_decl =
- symbol_vendor->FindNamespace(null_sc, name, &namespace_decl);
+ symbol_vendor->FindNamespace(name, &namespace_decl);
if (found_namespace_decl) {
context.m_namespace_map->push_back(
@@ -860,15 +851,12 @@ void ClangASTSource::FindExternalVisibleDecls(
break;
TypeList types;
- SymbolContext null_sc;
const bool exact_match = true;
llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files;
if (module_sp && namespace_decl)
- module_sp->FindTypesInNamespace(null_sc, name, &namespace_decl, 1, types);
+ module_sp->FindTypesInNamespace(name, &namespace_decl, 1, types);
else {
- SymbolContext sc;
- sc.module_sp = module_sp;
- m_target->GetImages().FindTypes(sc, name, exact_match, 1,
+ m_target->GetImages().FindTypes(module_sp.get(), name, exact_match, 1,
searched_symbol_files, types);
}
@@ -1655,10 +1643,10 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map,
std::vector<PairType> sorted_items;
sorted_items.reserve(source_map.size());
sorted_items.assign(source_map.begin(), source_map.end());
- std::sort(sorted_items.begin(), sorted_items.end(),
- [](const PairType &lhs, const PairType &rhs) {
- return lhs.second < rhs.second;
- });
+ llvm::sort(sorted_items.begin(), sorted_items.end(),
+ [](const PairType &lhs, const PairType &rhs) {
+ return lhs.second < rhs.second;
+ });
for (const auto &item : sorted_items) {
DeclFromUser<D> user_decl(const_cast<D *>(item.first));
@@ -1883,10 +1871,8 @@ void ClangASTSource::CompleteNamespaceMap(
if (!symbol_vendor)
continue;
- SymbolContext null_sc;
-
- found_namespace_decl = symbol_vendor->FindNamespace(
- null_sc, name, &module_parent_namespace_decl);
+ found_namespace_decl =
+ symbol_vendor->FindNamespace(name, &module_parent_namespace_decl);
if (!found_namespace_decl)
continue;
@@ -1918,10 +1904,8 @@ void ClangASTSource::CompleteNamespaceMap(
if (!symbol_vendor)
continue;
- SymbolContext null_sc;
-
found_namespace_decl =
- symbol_vendor->FindNamespace(null_sc, name, &null_namespace_decl);
+ symbol_vendor->FindNamespace(name, &null_namespace_decl);
if (!found_namespace_decl)
continue;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index 0811a7999920..9c2f8c4b6c92 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -17,7 +17,6 @@
#include "lldb/Core/Address.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"
#include "lldb/Expression/Materializer.h"
@@ -44,6 +43,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private.h"
#include "clang/AST/ASTConsumer.h"
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
index b67387930190..93fa57876bce 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h
@@ -10,18 +10,14 @@
#ifndef liblldb_ClangExpressionDeclMap_h_
#define liblldb_ClangExpressionDeclMap_h_
-// C Includes
#include <signal.h>
#include <stdint.h>
-// C++ Includes
#include <vector>
#include "ClangASTSource.h"
#include "ClangExpressionVariable.h"
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/Materializer.h"
@@ -325,12 +321,6 @@ public:
/// @param[in] namespace_decl
/// If valid and module is non-NULL, the parent namespace.
///
- /// @param[in] name
- /// The name as a plain C string. The NameSearchContext contains
- /// a DeclarationName for the name so at first the name may seem
- /// redundant, but ClangExpressionDeclMap operates in RTTI land so
- /// it can't access DeclarationName.
- ///
/// @param[in] current_id
/// The ID for the current FindExternalVisibleDecls invocation,
/// for logging purposes.
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
index e0d3ace15bd1..b5b640c9185f 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionHelper.h
@@ -10,14 +10,10 @@
#ifndef liblldb_ClangExpression_h_
#define liblldb_ClangExpression_h_
-// C Includes
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Expression/ExpressionTypeSystemHelper.h"
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index c5406fcc3340..6650c0db967f 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -7,12 +7,11 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
+#include <cctype>
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/PrettyPrinter.h"
#include "clang/Basic/DiagnosticIDs.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceLocation.h"
@@ -34,6 +33,8 @@
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Core/Rewriter.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/ADT/StringRef.h"
@@ -55,7 +56,6 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Signals.h"
-// Project includes
#include "ClangDiagnostic.h"
#include "ClangExpressionParser.h"
@@ -222,7 +222,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
Expression &expr,
bool generate_debug_info)
: ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(),
- m_code_generator(), m_pp_callbacks(nullptr) {
+ m_pp_callbacks(nullptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
// We can't compile expressions without a target. So if the exe_scope is
@@ -377,8 +377,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
m_compiler->getLangOpts().CPlusPlus = true;
break;
case lldb::eLanguageTypeObjC:
- m_compiler->getLangOpts().ObjC1 = true;
- m_compiler->getLangOpts().ObjC2 = true;
+ m_compiler->getLangOpts().ObjC = true;
// FIXME: the following language option is a temporary workaround,
// to "ask for ObjC, get ObjC++" (see comment above).
m_compiler->getLangOpts().CPlusPlus = true;
@@ -399,16 +398,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
LLVM_FALLTHROUGH;
case lldb::eLanguageTypeC_plus_plus_03:
m_compiler->getLangOpts().CPlusPlus = true;
- // FIXME: the following language option is a temporary workaround,
- // to "ask for C++, get ObjC++". Apple hopes to remove this requirement on
- // non-Apple platforms, but for now it is needed.
- m_compiler->getLangOpts().ObjC1 = true;
+ if (process_sp)
+ m_compiler->getLangOpts().ObjC =
+ process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC) != nullptr;
break;
case lldb::eLanguageTypeObjC_plus_plus:
case lldb::eLanguageTypeUnknown:
default:
- m_compiler->getLangOpts().ObjC1 = true;
- m_compiler->getLangOpts().ObjC2 = true;
+ m_compiler->getLangOpts().ObjC = true;
m_compiler->getLangOpts().CPlusPlus = true;
m_compiler->getLangOpts().CPlusPlus11 = true;
m_compiler->getHeaderSearchOpts().UseLibcxx = true;
@@ -432,7 +429,7 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
// long time parsing and importing debug information.
m_compiler->getLangOpts().SpellChecking = false;
- if (process_sp && m_compiler->getLangOpts().ObjC1) {
+ if (process_sp && m_compiler->getLangOpts().ObjC) {
if (process_sp->GetObjCLanguageRuntime()) {
if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() ==
ObjCLanguageRuntime::ObjCRuntimeVersions::eAppleObjC_V2)
@@ -452,6 +449,10 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
false; // Debuggers get universal access
m_compiler->getLangOpts().DollarIdents =
true; // $ indicates a persistent variable name
+ // We enable all builtin functions beside the builtins from libc/libm (e.g.
+ // 'fopen'). Those libc functions are already correctly handled by LLDB, and
+ // additionally enabling them as expandable builtins is breaking Clang.
+ m_compiler->getLangOpts().NoBuiltin = true;
// Set CodeGen options
m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
@@ -507,15 +508,14 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
// 8. Most of this we get from the CompilerInstance, but we also want to give
// the context an ExternalASTSource.
- m_selector_table.reset(new SelectorTable());
- m_builtin_context.reset(new Builtin::Context());
- std::unique_ptr<clang::ASTContext> ast_context(
- new ASTContext(m_compiler->getLangOpts(), m_compiler->getSourceManager(),
- m_compiler->getPreprocessor().getIdentifierTable(),
- *m_selector_table.get(), *m_builtin_context.get()));
+ auto &PP = m_compiler->getPreprocessor();
+ auto &builtin_context = PP.getBuiltinInfo();
+ builtin_context.initializeBuiltins(PP.getIdentifierTable(),
+ m_compiler->getLangOpts());
- ast_context->InitBuiltinTypes(m_compiler->getTarget());
+ m_compiler->createASTContext();
+ clang::ASTContext &ast_context = m_compiler->getASTContext();
ClangExpressionHelper *type_system_helper =
dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
@@ -524,14 +524,13 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
if (decl_map) {
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(
decl_map->CreateProxy());
- decl_map->InstallASTContext(*ast_context, m_compiler->getFileManager());
- ast_context->setExternalSource(ast_source);
+ decl_map->InstallASTContext(ast_context, m_compiler->getFileManager());
+ ast_context.setExternalSource(ast_source);
}
m_ast_context.reset(
new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str()));
- m_ast_context->setASTContext(ast_context.get());
- m_compiler->setASTContext(ast_context.release());
+ m_ast_context->setASTContext(&ast_context);
std::string module_name("$__lldb_module");
@@ -544,7 +543,270 @@ ClangExpressionParser::ClangExpressionParser(ExecutionContextScope *exe_scope,
ClangExpressionParser::~ClangExpressionParser() {}
+namespace {
+
+//----------------------------------------------------------------------
+/// @class CodeComplete
+///
+/// A code completion consumer for the clang Sema that is responsible for
+/// creating the completion suggestions when a user requests completion
+/// of an incomplete `expr` invocation.
+//----------------------------------------------------------------------
+class CodeComplete : public CodeCompleteConsumer {
+ CodeCompletionTUInfo m_info;
+
+ std::string m_expr;
+ unsigned m_position = 0;
+ CompletionRequest &m_request;
+ /// The printing policy we use when printing declarations for our completion
+ /// descriptions.
+ clang::PrintingPolicy m_desc_policy;
+
+ /// Returns true if the given character can be used in an identifier.
+ /// This also returns true for numbers because for completion we usually
+ /// just iterate backwards over iterators.
+ ///
+ /// Note: lldb uses '$' in its internal identifiers, so we also allow this.
+ static bool IsIdChar(char c) {
+ return c == '_' || std::isalnum(c) || c == '$';
+ }
+
+ /// Returns true if the given character is used to separate arguments
+ /// in the command line of lldb.
+ static bool IsTokenSeparator(char c) { return c == ' ' || c == '\t'; }
+
+ /// Drops all tokens in front of the expression that are unrelated for
+ /// the completion of the cmd line. 'unrelated' means here that the token
+ /// is not interested for the lldb completion API result.
+ StringRef dropUnrelatedFrontTokens(StringRef cmd) {
+ if (cmd.empty())
+ return cmd;
+
+ // If we are at the start of a word, then all tokens are unrelated to
+ // the current completion logic.
+ if (IsTokenSeparator(cmd.back()))
+ return StringRef();
+
+ // Remove all previous tokens from the string as they are unrelated
+ // to completing the current token.
+ StringRef to_remove = cmd;
+ while (!to_remove.empty() && !IsTokenSeparator(to_remove.back())) {
+ to_remove = to_remove.drop_back();
+ }
+ cmd = cmd.drop_front(to_remove.size());
+
+ return cmd;
+ }
+
+ /// Removes the last identifier token from the given cmd line.
+ StringRef removeLastToken(StringRef cmd) {
+ while (!cmd.empty() && IsIdChar(cmd.back())) {
+ cmd = cmd.drop_back();
+ }
+ return cmd;
+ }
+
+ /// Attemps to merge the given completion from the given position into the
+ /// existing command. Returns the completion string that can be returned to
+ /// the lldb completion API.
+ std::string mergeCompletion(StringRef existing, unsigned pos,
+ StringRef completion) {
+ StringRef existing_command = existing.substr(0, pos);
+ // We rewrite the last token with the completion, so let's drop that
+ // token from the command.
+ existing_command = removeLastToken(existing_command);
+ // We also should remove all previous tokens from the command as they
+ // would otherwise be added to the completion that already has the
+ // completion.
+ existing_command = dropUnrelatedFrontTokens(existing_command);
+ return existing_command.str() + completion.str();
+ }
+
+public:
+ /// Constructs a CodeComplete consumer that can be attached to a Sema.
+ /// @param[out] matches
+ /// The list of matches that the lldb completion API expects as a result.
+ /// This may already contain matches, so it's only allowed to append
+ /// to this variable.
+ /// @param[out] expr
+ /// The whole expression string that we are currently parsing. This
+ /// string needs to be equal to the input the user typed, and NOT the
+ /// final code that Clang is parsing.
+ /// @param[out] position
+ /// The character position of the user cursor in the `expr` parameter.
+ ///
+ CodeComplete(CompletionRequest &request, clang::LangOptions ops,
+ std::string expr, unsigned position)
+ : CodeCompleteConsumer(CodeCompleteOptions(), false),
+ m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
+ m_position(position), m_request(request), m_desc_policy(ops) {
+
+ // Ensure that the printing policy is producing a description that is as
+ // short as possible.
+ m_desc_policy.SuppressScope = true;
+ m_desc_policy.SuppressTagKeyword = true;
+ m_desc_policy.FullyQualifiedName = false;
+ m_desc_policy.TerseOutput = true;
+ m_desc_policy.IncludeNewlines = false;
+ m_desc_policy.UseVoidForZeroParams = false;
+ m_desc_policy.Bool = true;
+ }
+
+ /// Deregisters and destroys this code-completion consumer.
+ virtual ~CodeComplete() {}
+
+ /// \name Code-completion filtering
+ /// Check if the result should be filtered out.
+ bool isResultFilteredOut(StringRef Filter,
+ CodeCompletionResult Result) override {
+ // This code is mostly copied from CodeCompleteConsumer.
+ switch (Result.Kind) {
+ case CodeCompletionResult::RK_Declaration:
+ return !(
+ Result.Declaration->getIdentifier() &&
+ Result.Declaration->getIdentifier()->getName().startswith(Filter));
+ case CodeCompletionResult::RK_Keyword:
+ return !StringRef(Result.Keyword).startswith(Filter);
+ case CodeCompletionResult::RK_Macro:
+ return !Result.Macro->getName().startswith(Filter);
+ case CodeCompletionResult::RK_Pattern:
+ return !StringRef(Result.Pattern->getAsString()).startswith(Filter);
+ }
+ // If we trigger this assert or the above switch yields a warning, then
+ // CodeCompletionResult has been enhanced with more kinds of completion
+ // results. Expand the switch above in this case.
+ assert(false && "Unknown completion result type?");
+ // If we reach this, then we should just ignore whatever kind of unknown
+ // result we got back. We probably can't turn it into any kind of useful
+ // completion suggestion with the existing code.
+ return true;
+ }
+
+ /// \name Code-completion callbacks
+ /// Process the finalized code-completion results.
+ void ProcessCodeCompleteResults(Sema &SemaRef, CodeCompletionContext Context,
+ CodeCompletionResult *Results,
+ unsigned NumResults) override {
+
+ // The Sema put the incomplete token we try to complete in here during
+ // lexing, so we need to retrieve it here to know what we are completing.
+ StringRef Filter = SemaRef.getPreprocessor().getCodeCompletionFilter();
+
+ // Iterate over all the results. Filter out results we don't want and
+ // process the rest.
+ for (unsigned I = 0; I != NumResults; ++I) {
+ // Filter the results with the information from the Sema.
+ if (!Filter.empty() && isResultFilteredOut(Filter, Results[I]))
+ continue;
+
+ CodeCompletionResult &R = Results[I];
+ std::string ToInsert;
+ std::string Description;
+ // Handle the different completion kinds that come from the Sema.
+ switch (R.Kind) {
+ case CodeCompletionResult::RK_Declaration: {
+ const NamedDecl *D = R.Declaration;
+ ToInsert = R.Declaration->getNameAsString();
+ // If we have a function decl that has no arguments we want to
+ // complete the empty parantheses for the user. If the function has
+ // arguments, we at least complete the opening bracket.
+ if (const FunctionDecl *F = dyn_cast<FunctionDecl>(D)) {
+ if (F->getNumParams() == 0)
+ ToInsert += "()";
+ else
+ ToInsert += "(";
+ raw_string_ostream OS(Description);
+ F->print(OS, m_desc_policy, false);
+ OS.flush();
+ } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
+ Description = V->getType().getAsString(m_desc_policy);
+ } else if (const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
+ Description = F->getType().getAsString(m_desc_policy);
+ } else if (const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
+ // If we try to complete a namespace, then we can directly append
+ // the '::'.
+ if (!N->isAnonymousNamespace())
+ ToInsert += "::";
+ }
+ break;
+ }
+ case CodeCompletionResult::RK_Keyword:
+ ToInsert = R.Keyword;
+ break;
+ case CodeCompletionResult::RK_Macro:
+ ToInsert = R.Macro->getName().str();
+ break;
+ case CodeCompletionResult::RK_Pattern:
+ ToInsert = R.Pattern->getTypedText();
+ break;
+ }
+ // At this point all information is in the ToInsert string.
+
+ // We also filter some internal lldb identifiers here. The user
+ // shouldn't see these.
+ if (StringRef(ToInsert).startswith("$__lldb_"))
+ continue;
+ if (!ToInsert.empty()) {
+ // Merge the suggested Token into the existing command line to comply
+ // with the kind of result the lldb API expects.
+ std::string CompletionSuggestion =
+ mergeCompletion(m_expr, m_position, ToInsert);
+ m_request.AddCompletion(CompletionSuggestion, Description);
+ }
+ }
+ }
+
+ /// \param S the semantic-analyzer object for which code-completion is being
+ /// done.
+ ///
+ /// \param CurrentArg the index of the current argument.
+ ///
+ /// \param Candidates an array of overload candidates.
+ ///
+ /// \param NumCandidates the number of overload candidates
+ void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
+ OverloadCandidate *Candidates,
+ unsigned NumCandidates,
+ SourceLocation OpenParLoc) override {
+ // At the moment we don't filter out any overloaded candidates.
+ }
+
+ CodeCompletionAllocator &getAllocator() override {
+ return m_info.getAllocator();
+ }
+
+ CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return m_info; }
+};
+} // namespace
+
+bool ClangExpressionParser::Complete(CompletionRequest &request, unsigned line,
+ unsigned pos, unsigned typed_pos) {
+ DiagnosticManager mgr;
+ // We need the raw user expression here because that's what the CodeComplete
+ // class uses to provide completion suggestions.
+ // However, the `Text` method only gives us the transformed expression here.
+ // To actually get the raw user input here, we have to cast our expression to
+ // the LLVMUserExpression which exposes the right API. This should never fail
+ // as we always have a ClangUserExpression whenever we call this.
+ LLVMUserExpression &llvm_expr = *static_cast<LLVMUserExpression *>(&m_expr);
+ CodeComplete CC(request, m_compiler->getLangOpts(), llvm_expr.GetUserText(),
+ typed_pos);
+ // We don't need a code generator for parsing.
+ m_code_generator.reset();
+ // Start parsing the expression with our custom code completion consumer.
+ ParseInternal(mgr, &CC, line, pos);
+ return true;
+}
+
unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) {
+ return ParseInternal(diagnostic_manager);
+}
+
+unsigned
+ClangExpressionParser::ParseInternal(DiagnosticManager &diagnostic_manager,
+ CodeCompleteConsumer *completion_consumer,
+ unsigned completion_line,
+ unsigned completion_column) {
ClangDiagnosticManagerAdapter *adapter =
static_cast<ClangDiagnosticManagerAdapter *>(
m_compiler->getDiagnostics().getClient());
@@ -557,10 +819,20 @@ unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) {
clang::SourceManager &source_mgr = m_compiler->getSourceManager();
bool created_main_file = false;
- if (m_compiler->getCodeGenOpts().getDebugInfo() ==
- codegenoptions::FullDebugInfo) {
+
+ // Clang wants to do completion on a real file known by Clang's file manager,
+ // so we have to create one to make this work.
+ // TODO: We probably could also simulate to Clang's file manager that there
+ // is a real file that contains our code.
+ bool should_create_file = completion_consumer != nullptr;
+
+ // We also want a real file on disk if we generate full debug info.
+ should_create_file |= m_compiler->getCodeGenOpts().getDebugInfo() ==
+ codegenoptions::FullDebugInfo;
+
+ if (should_create_file) {
int temp_fd = -1;
- llvm::SmallString<PATH_MAX> result_path;
+ llvm::SmallString<128> result_path;
if (FileSpec tmpdir_file_spec = HostInfo::GetProcessTempDir()) {
tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr");
std::string temp_source_path = tmpdir_file_spec.GetPath();
@@ -603,14 +875,30 @@ unsigned ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) {
if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
decl_map->InstallCodeGenerator(m_code_generator.get());
+ // If we want to parse for code completion, we need to attach our code
+ // completion consumer to the Sema and specify a completion position.
+ // While parsing the Sema will call this consumer with the provided
+ // completion suggestions.
+ if (completion_consumer) {
+ auto main_file = source_mgr.getFileEntryForID(source_mgr.getMainFileID());
+ auto &PP = m_compiler->getPreprocessor();
+ // Lines and columns start at 1 in Clang, but code completion positions are
+ // indexed from 0, so we need to add 1 to the line and column here.
+ ++completion_line;
+ ++completion_column;
+ PP.SetCodeCompletionPoint(main_file, completion_line, completion_column);
+ }
+
if (ast_transformer) {
ast_transformer->Initialize(m_compiler->getASTContext());
ParseAST(m_compiler->getPreprocessor(), ast_transformer,
- m_compiler->getASTContext());
+ m_compiler->getASTContext(), false, TU_Complete,
+ completion_consumer);
} else {
m_code_generator->Initialize(m_compiler->getASTContext());
ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(),
- m_compiler->getASTContext());
+ m_compiler->getASTContext(), false, TU_Complete,
+ completion_consumer);
}
diag_buf->EndSourceFile();
@@ -891,9 +1179,9 @@ lldb_private::Status ClangExpressionParser::PrepareForExecution(
if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) {
if (install_diagnostics.Diagnostics().size())
- err.SetErrorString("couldn't install checkers, unknown error");
- else
err.SetErrorString(install_diagnostics.GetString().c_str());
+ else
+ err.SetErrorString("couldn't install checkers, unknown error");
return err;
}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
index 4058ec1270b3..03ff55f614d5 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h
@@ -20,6 +20,10 @@
#include <string>
#include <vector>
+namespace clang {
+class CodeCompleteConsumer;
+}
+
namespace lldb_private {
class IRExecutionUnit;
@@ -58,6 +62,9 @@ public:
//------------------------------------------------------------------
~ClangExpressionParser() override;
+ bool Complete(CompletionRequest &request, unsigned line, unsigned pos,
+ unsigned typed_pos) override;
+
//------------------------------------------------------------------
/// Parse a single expression and convert it to IR using Clang. Don't wrap
/// the expression in anything at all.
@@ -143,16 +150,39 @@ public:
std::string GetClangTargetABI(const ArchSpec &target_arch);
private:
+ //------------------------------------------------------------------
+ /// Parses the expression.
+ ///
+ /// @param[in] diagnostic_manager
+ /// The diagnostic manager that should receive the diagnostics
+ /// from the parsing process.
+ ///
+ /// @param[in] completion
+ /// The completion consumer that should be used during parsing
+ /// (or a nullptr if no consumer should be attached).
+ ///
+ /// @param[in] completion_line
+ /// The line in which the completion marker should be placed.
+ /// The first line is represented by the value 0.
+ ///
+ /// @param[in] completion_column
+ /// The column in which the completion marker should be placed.
+ /// The first column is represented by the value 0.
+ ///
+ /// @return
+ /// The number of parsing errors.
+ //-------------------------------------------------------------------
+ unsigned ParseInternal(DiagnosticManager &diagnostic_manager,
+ clang::CodeCompleteConsumer *completion = nullptr,
+ unsigned completion_line = 0,
+ unsigned completion_column = 0);
+
std::unique_ptr<llvm::LLVMContext>
m_llvm_context; ///< The LLVM context to generate IR into
std::unique_ptr<clang::FileManager>
m_file_manager; ///< The Clang file manager object used by the compiler
std::unique_ptr<clang::CompilerInstance>
m_compiler; ///< The Clang compiler used to parse expressions into IR
- std::unique_ptr<clang::Builtin::Context>
- m_builtin_context; ///< Context for Clang built-ins
- std::unique_ptr<clang::SelectorTable>
- m_selector_table; ///< Selector table for Objective-C methods
std::unique_ptr<clang::CodeGenerator>
m_code_generator; ///< The Clang object that generates IR
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
index 7d5ced5b4705..6886f0940adb 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h
@@ -10,20 +10,16 @@
#ifndef liblldb_ClangExpressionVariable_h_
#define liblldb_ClangExpressionVariable_h_
-// C Includes
#include <signal.h>
#include <stdint.h>
#include <string.h>
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "llvm/Support/Casting.h"
-// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/ExpressionVariable.h"
diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
index e3e0ed49181e..8ec9ff2235f5 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp
@@ -12,9 +12,6 @@
#include "ASTStructExtractor.h"
#include "ClangExpressionParser.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/CodeGen/CodeGenAction.h"
@@ -25,9 +22,7 @@
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/Module.h"
-// Project includes
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Expression/IRExecutionUnit.h"
@@ -44,6 +39,7 @@
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb_private;
diff --git a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
index 438cf0c713da..9d933bfa6095 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ClangFunctionCaller_h_
#define liblldb_ClangFunctionCaller_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "ClangExpressionHelper.h"
#include "lldb/Core/Address.h"
diff --git a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
index 4251d2ee75b9..44a13353818a 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangHost.cpp
@@ -17,7 +17,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.h"
-// Project includes
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#if !defined(_WIN32)
#include "lldb/Host/posix/HostInfoPosix.h"
@@ -42,7 +42,7 @@ static bool DefaultComputeClangDirectory(FileSpec &file_spec) {
#if defined(__APPLE__)
static bool VerifyClangPath(const llvm::Twine &clang_path) {
- if (llvm::sys::fs::is_directory(clang_path))
+ if (FileSystem::Instance().IsDirectory(clang_path))
return true;
Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
if (log)
@@ -84,7 +84,8 @@ bool lldb_private::ComputeClangDirectory(FileSpec &lldb_shlib_spec,
"Developer/Toolchains/XcodeDefault.xctoolchain",
swift_clang_resource_dir);
if (!verify || VerifyClangPath(clang_path)) {
- file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native);
+ file_spec.SetFile(clang_path.c_str(), FileSpec::Style::native);
+ FileSystem::Instance().Resolve(file_spec);
return true;
}
} else if (parent != r_end && *parent == "PrivateFrameworks" &&
@@ -98,7 +99,8 @@ bool lldb_private::ComputeClangDirectory(FileSpec &lldb_shlib_spec,
raw_path.resize(parent - r_end);
llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir);
if (!verify || VerifyClangPath(clang_path)) {
- file_spec.SetFile(clang_path.c_str(), true, FileSpec::Style::native);
+ file_spec.SetFile(clang_path.c_str(), FileSpec::Style::native);
+ FileSystem::Instance().Resolve(file_spec);
return true;
}
raw_path = lldb_shlib_spec.GetPath();
@@ -110,7 +112,8 @@ bool lldb_private::ComputeClangDirectory(FileSpec &lldb_shlib_spec,
// Fall back to the Clang resource directory inside the framework.
raw_path.append("LLDB.framework/Resources/Clang");
- file_spec.SetFile(raw_path.c_str(), true, FileSpec::Style::native);
+ file_spec.SetFile(raw_path.c_str(), FileSpec::Style::native);
+ FileSystem::Instance().Resolve(file_spec);
return true;
}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
index 665195f01774..ced21dfe0dda 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.cpp
@@ -7,11 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendActions.h"
@@ -24,7 +21,6 @@
#include "llvm/Support/Path.h"
#include "llvm/Support/Threading.h"
-// Project includes
#include "ClangHost.h"
#include "ClangModulesDeclVendor.h"
@@ -601,7 +597,7 @@ ClangModulesDeclVendor::Create(Target &target) {
{
FileSpec clang_resource_dir = GetClangResourceDir();
- if (llvm::sys::fs::is_directory(clang_resource_dir.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(clang_resource_dir.GetPath())) {
compiler_invocation_arguments.push_back("-resource-dir");
compiler_invocation_arguments.push_back(clang_resource_dir.GetPath());
}
@@ -612,7 +608,8 @@ ClangModulesDeclVendor::Create(Target &target) {
new StoringDiagnosticConsumer);
std::vector<const char *> compiler_invocation_argument_cstrs;
-
+ compiler_invocation_argument_cstrs.reserve(
+ compiler_invocation_arguments.size());
for (const std::string &arg : compiler_invocation_arguments) {
compiler_invocation_argument_cstrs.push_back(arg.c_str());
}
diff --git a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
index 59126974616d..c4438c7e2203 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ClangPersistentVariables_h_
#define liblldb_ClangPersistentVariables_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
-// Project includes
#include "ClangExpressionVariable.h"
#include "ClangModulesDeclVendor.h"
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
index 2e61f704127a..f42955df07aa 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp
@@ -376,9 +376,9 @@ static void SetupDeclVendor(ExecutionContext &exe_ctx, Target *target) {
}
}
-llvm::Optional<lldb::LanguageType> ClangUserExpression::GetLanguageForExpr(
+void ClangUserExpression::UpdateLanguageForExpr(
DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) {
- lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown;
+ m_expr_lang = lldb::LanguageType::eLanguageTypeUnknown;
std::string prefix = m_expr_prefix;
@@ -390,20 +390,29 @@ llvm::Optional<lldb::LanguageType> ClangUserExpression::GetLanguageForExpr(
m_expr_text.c_str()));
if (m_in_cplusplus_method)
- lang_type = lldb::eLanguageTypeC_plus_plus;
+ m_expr_lang = lldb::eLanguageTypeC_plus_plus;
else if (m_in_objectivec_method)
- lang_type = lldb::eLanguageTypeObjC;
+ m_expr_lang = lldb::eLanguageTypeObjC;
else
- lang_type = lldb::eLanguageTypeC;
+ m_expr_lang = lldb::eLanguageTypeC;
- if (!source_code->GetText(m_transformed_text, lang_type, m_in_static_method,
- exe_ctx)) {
+ if (!source_code->GetText(m_transformed_text, m_expr_lang,
+ m_in_static_method, exe_ctx)) {
diagnostic_manager.PutString(eDiagnosticSeverityError,
"couldn't construct expression body");
- return llvm::Optional<lldb::LanguageType>();
+ return;
+ }
+
+ // Find and store the start position of the original code inside the
+ // transformed code. We need this later for the code completion.
+ std::size_t original_start;
+ std::size_t original_end;
+ bool found_bounds = source_code->GetOriginalBodyBounds(
+ m_transformed_text, m_expr_lang, original_start, original_end);
+ if (found_bounds) {
+ m_user_expression_start_pos = original_start;
}
}
- return lang_type;
}
bool ClangUserExpression::PrepareForParsing(
@@ -427,6 +436,8 @@ bool ClangUserExpression::PrepareForParsing(
ApplyObjcCastHack(m_expr_text);
SetupDeclVendor(exe_ctx, m_target);
+
+ UpdateLanguageForExpr(diagnostic_manager, exe_ctx);
return true;
}
@@ -440,11 +451,6 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
if (!PrepareForParsing(diagnostic_manager, exe_ctx))
return false;
- lldb::LanguageType lang_type = lldb::LanguageType::eLanguageTypeUnknown;
- if (auto new_lang = GetLanguageForExpr(diagnostic_manager, exe_ctx)) {
- lang_type = new_lang.getValue();
- }
-
if (log)
log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
@@ -504,7 +510,7 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
const std::string &fixed_expression =
diagnostic_manager.GetFixedExpression();
if (ExpressionSourceCode::GetOriginalBodyBounds(
- fixed_expression, lang_type, fixed_start, fixed_end))
+ fixed_expression, m_expr_lang, fixed_start, fixed_end))
m_fixed_text =
fixed_expression.substr(fixed_start, fixed_end - fixed_start);
}
@@ -591,6 +597,116 @@ bool ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager,
return true;
}
+//------------------------------------------------------------------
+/// Converts an absolute position inside a given code string into
+/// a column/line pair.
+///
+/// @param[in] abs_pos
+/// A absolute position in the code string that we want to convert
+/// to a column/line pair.
+///
+/// @param[in] code
+/// A multi-line string usually representing source code.
+///
+/// @param[out] line
+/// The line in the code that contains the given absolute position.
+/// The first line in the string is indexed as 1.
+///
+/// @param[out] column
+/// The column in the line that contains the absolute position.
+/// The first character in a line is indexed as 0.
+//------------------------------------------------------------------
+static void AbsPosToLineColumnPos(size_t abs_pos, llvm::StringRef code,
+ unsigned &line, unsigned &column) {
+ // Reset to code position to beginning of the file.
+ line = 0;
+ column = 0;
+
+ assert(abs_pos <= code.size() && "Absolute position outside code string?");
+
+ // We have to walk up to the position and count lines/columns.
+ for (std::size_t i = 0; i < abs_pos; ++i) {
+ // If we hit a line break, we go back to column 0 and enter a new line.
+ // We only handle \n because that's what we internally use to make new
+ // lines for our temporary code strings.
+ if (code[i] == '\n') {
+ ++line;
+ column = 0;
+ continue;
+ }
+ ++column;
+ }
+}
+
+bool ClangUserExpression::Complete(ExecutionContext &exe_ctx,
+ CompletionRequest &request,
+ unsigned complete_pos) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+ // We don't want any visible feedback when completing an expression. Mostly
+ // because the results we get from an incomplete invocation are probably not
+ // correct.
+ DiagnosticManager diagnostic_manager;
+
+ if (!PrepareForParsing(diagnostic_manager, exe_ctx))
+ return false;
+
+ if (log)
+ log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
+
+ //////////////////////////
+ // Parse the expression
+ //
+
+ m_materializer_ap.reset(new Materializer());
+
+ ResetDeclMap(exe_ctx, m_result_delegate, /*keep result in memory*/ true);
+
+ OnExit on_exit([this]() { ResetDeclMap(); });
+
+ if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) {
+ diagnostic_manager.PutString(
+ eDiagnosticSeverityError,
+ "current process state is unsuitable for expression parsing");
+
+ return false;
+ }
+
+ if (m_options.GetExecutionPolicy() == eExecutionPolicyTopLevel) {
+ DeclMap()->SetLookupsEnabled(true);
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+ ExecutionContextScope *exe_scope = process;
+
+ if (!exe_scope)
+ exe_scope = exe_ctx.GetTargetPtr();
+
+ ClangExpressionParser parser(exe_scope, *this, false);
+
+ // We have to find the source code location where the user text is inside
+ // the transformed expression code. When creating the transformed text, we
+ // already stored the absolute position in the m_transformed_text string. The
+ // only thing left to do is to transform it into the line:column format that
+ // Clang expects.
+
+ // The line and column of the user expression inside the transformed source
+ // code.
+ unsigned user_expr_line, user_expr_column;
+ if (m_user_expression_start_pos.hasValue())
+ AbsPosToLineColumnPos(*m_user_expression_start_pos, m_transformed_text,
+ user_expr_line, user_expr_column);
+ else
+ return false;
+
+ // The actual column where we have to complete is the start column of the
+ // user expression + the offset inside the user code that we were given.
+ const unsigned completion_column = user_expr_column + complete_pos;
+ parser.Complete(request, user_expr_line, completion_column, complete_pos);
+
+ return true;
+}
+
bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx,
std::vector<lldb::addr_t> &args,
lldb::addr_t struct_address,
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
index ac363bf91747..7e4cba661850 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ClangUserExpression_h_
#define liblldb_ClangUserExpression_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "ASTResultSynthesizer.h"
#include "ASTStructExtractor.h"
#include "ClangExpressionDeclMap.h"
@@ -143,6 +139,9 @@ public:
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory, bool generate_debug_info) override;
+ bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request,
+ unsigned complete_pos) override;
+
ExpressionTypeSystemHelper *GetTypeSystemHelper() override {
return &m_type_system_helper;
}
@@ -174,8 +173,8 @@ private:
lldb::addr_t struct_address,
DiagnosticManager &diagnostic_manager) override;
- llvm::Optional<lldb::LanguageType> GetLanguageForExpr(
- DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx);
+ void UpdateLanguageForExpr(DiagnosticManager &diagnostic_manager,
+ ExecutionContext &exe_ctx);
bool SetupPersistentState(DiagnosticManager &diagnostic_manager,
ExecutionContext &exe_ctx);
bool PrepareForParsing(DiagnosticManager &diagnostic_manager,
@@ -198,6 +197,13 @@ private:
lldb::TargetSP m_target_sp;
};
+ /// The language type of the current expression.
+ lldb::LanguageType m_expr_lang = lldb::eLanguageTypeUnknown;
+
+ /// The absolute character position in the transformed source code where the
+ /// user code (as typed by the user) starts. If the variable is empty, then we
+ /// were not able to calculate this position.
+ llvm::Optional<size_t> m_user_expression_start_pos;
ResultDelegate m_result_delegate;
};
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
index 0f2aeef27e57..fe6ca450a79d 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp
@@ -11,13 +11,11 @@
#include "ClangExpressionDeclMap.h"
#include "ClangExpressionParser.h"
-// C Includes
#include <stdio.h>
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
-// C++ Includes
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
diff --git a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
index a897a2b17087..b0650f0eda02 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
+++ b/source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h
@@ -10,14 +10,10 @@
#ifndef liblldb_ClangUtilityFunction_h_
#define liblldb_ClangUtilityFunction_h_
-// C Includes
-// C++ Includes
#include <map>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "ClangExpressionHelper.h"
#include "lldb/Core/ClangForward.h"
diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index e51c9ee07b9f..3a7cd58b70ab 100644
--- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -25,7 +25,6 @@
#include "clang/AST/ASTContext.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Expression/IRInterpreter.h"
@@ -36,6 +35,7 @@
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
#include <map>
@@ -310,12 +310,14 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
lldb::TargetSP target_sp(m_execution_unit.GetTarget());
lldb_private::ExecutionContext exe_ctx(target_sp, true);
- if (m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope()) == 0) {
+ llvm::Optional<uint64_t> bit_size =
+ m_result_type.GetBitSize(exe_ctx.GetBestExecutionContextScope());
+ if (!bit_size) {
lldb_private::StreamString type_desc_stream;
m_result_type.DumpTypeDescription(&type_desc_stream);
if (log)
- log->Printf("Result type has size 0");
+ log->Printf("Result type has unknown size");
m_error_stream.Printf("Error [IRForTarget]: Size of result type '%s' "
"couldn't be determined\n",
@@ -334,7 +336,8 @@ bool IRForTarget::CreateResultVariable(llvm::Function &llvm_function) {
if (log)
log->Printf("Creating a new result global: \"%s\" with size 0x%" PRIx64,
- m_result_name.GetCString(), m_result_type.GetByteSize(nullptr));
+ m_result_name.GetCString(),
+ m_result_type.GetByteSize(nullptr).getValueOr(0));
// Construct a new result global and set up its metadata
@@ -778,11 +781,8 @@ bool IRForTarget::RewriteObjCConstStrings() {
static bool IsObjCSelectorRef(Value *value) {
GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
- if (!global_variable || !global_variable->hasName() ||
- !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"))
- return false;
-
- return true;
+ return !(!global_variable || !global_variable->hasName() ||
+ !global_variable->getName().startswith("OBJC_SELECTOR_REFERENCES_"));
}
// This function does not report errors; its callers are responsible.
@@ -953,11 +953,8 @@ bool IRForTarget::RewriteObjCSelectors(BasicBlock &basic_block) {
static bool IsObjCClassReference(Value *value) {
GlobalVariable *global_variable = dyn_cast<GlobalVariable>(value);
- if (!global_variable || !global_variable->hasName() ||
- !global_variable->getName().startswith("OBJC_CLASS_REFERENCES_"))
- return false;
-
- return true;
+ return !(!global_variable || !global_variable->hasName() ||
+ !global_variable->getName().startswith("OBJC_CLASS_REFERENCES_"));
}
// This function does not report errors; its callers are responsible.
@@ -1259,12 +1256,9 @@ bool IRForTarget::MaterializeInitializer(uint8_t *data, Constant *initializer) {
llvm::NextPowerOf2(constant_size) * 8);
lldb_private::Status get_data_error;
- if (!scalar.GetAsMemoryData(data, constant_size,
- lldb_private::endian::InlHostByteOrder(),
- get_data_error))
- return false;
-
- return true;
+ return scalar.GetAsMemoryData(data, constant_size,
+ lldb_private::endian::InlHostByteOrder(),
+ get_data_error) != 0;
} else if (ConstantDataArray *array_initializer =
dyn_cast<ConstantDataArray>(initializer)) {
if (array_initializer->isString()) {
@@ -1376,7 +1370,9 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
value_type = global_variable->getType();
}
- const uint64_t value_size = compiler_type.GetByteSize(nullptr);
+ llvm::Optional<uint64_t> value_size = compiler_type.GetByteSize(nullptr);
+ if (!value_size)
+ return false;
lldb::offset_t value_alignment =
(compiler_type.GetTypeBitAlign() + 7ull) / 8ull;
@@ -1387,13 +1383,13 @@ bool IRForTarget::MaybeHandleVariable(Value *llvm_value_ptr) {
lldb_private::ClangUtil::GetQualType(compiler_type)
.getAsString()
.c_str(),
- PrintType(value_type).c_str(), value_size, value_alignment);
+ PrintType(value_type).c_str(), *value_size, value_alignment);
}
if (named_decl &&
!m_decl_map->AddValueToStruct(
named_decl, lldb_private::ConstString(name.c_str()), llvm_value_ptr,
- value_size, value_alignment)) {
+ *value_size, value_alignment)) {
if (!global_variable->hasExternalLinkage())
return true;
else
diff --git a/source/Plugins/ExpressionParser/Go/CMakeLists.txt b/source/Plugins/ExpressionParser/Go/CMakeLists.txt
deleted file mode 100644
index 3d552aafa0d7..000000000000
--- a/source/Plugins/ExpressionParser/Go/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-add_lldb_library(lldbPluginExpressionParserGo PLUGIN
- GoLexer.cpp
- GoParser.cpp
- GoUserExpression.cpp
-
- LINK_LIBS
- lldbCore
- lldbExpression
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
- )
diff --git a/source/Plugins/ExpressionParser/Go/GoAST.h b/source/Plugins/ExpressionParser/Go/GoAST.h
deleted file mode 100644
index d24e6c548718..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoAST.h
+++ /dev/null
@@ -1,1977 +0,0 @@
-//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// DO NOT EDIT.
-// Generated by gen_go_ast.py
-
-#ifndef liblldb_GoAST_h
-#define liblldb_GoAST_h
-
-#include "Plugins/ExpressionParser/Go/GoLexer.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private.h"
-#include "llvm/Support/Casting.h"
-
-namespace lldb_private {
-
-class GoASTNode {
-public:
- typedef GoLexer::TokenType TokenType;
- typedef GoLexer::Token Token;
- enum ChanDir {
- eChanBidir,
- eChanSend,
- eChanRecv,
- };
- enum NodeKind {
- eBadDecl,
- eFuncDecl,
- eGenDecl,
- eArrayType,
- eBadExpr,
- eBasicLit,
- eBinaryExpr,
- eIdent,
- eCallExpr,
- eChanType,
- eCompositeLit,
- eEllipsis,
- eFuncType,
- eFuncLit,
- eIndexExpr,
- eInterfaceType,
- eKeyValueExpr,
- eMapType,
- eParenExpr,
- eSelectorExpr,
- eSliceExpr,
- eStarExpr,
- eStructType,
- eTypeAssertExpr,
- eUnaryExpr,
- eImportSpec,
- eTypeSpec,
- eValueSpec,
- eAssignStmt,
- eBadStmt,
- eBlockStmt,
- eBranchStmt,
- eCaseClause,
- eCommClause,
- eDeclStmt,
- eDeferStmt,
- eEmptyStmt,
- eExprStmt,
- eForStmt,
- eGoStmt,
- eIfStmt,
- eIncDecStmt,
- eLabeledStmt,
- eRangeStmt,
- eReturnStmt,
- eSelectStmt,
- eSendStmt,
- eSwitchStmt,
- eTypeSwitchStmt,
- eField,
- eFieldList,
- };
-
- virtual ~GoASTNode() = default;
-
- NodeKind GetKind() const { return m_kind; }
-
- virtual const char *GetKindName() const = 0;
-
- template <typename V> void WalkChildren(V &v);
-
-protected:
- explicit GoASTNode(NodeKind kind) : m_kind(kind) {}
-
-private:
- const NodeKind m_kind;
-
- GoASTNode(const GoASTNode &) = delete;
- const GoASTNode &operator=(const GoASTNode &) = delete;
-};
-
-class GoASTDecl : public GoASTNode {
-public:
- template <typename R, typename V> R Visit(V *v) const;
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() >= eBadDecl && n->GetKind() <= eGenDecl;
- }
-
-protected:
- explicit GoASTDecl(NodeKind kind) : GoASTNode(kind) {}
-
-private:
- GoASTDecl(const GoASTDecl &) = delete;
- const GoASTDecl &operator=(const GoASTDecl &) = delete;
-};
-
-class GoASTExpr : public GoASTNode {
-public:
- template <typename R, typename V> R Visit(V *v) const;
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() >= eArrayType && n->GetKind() <= eUnaryExpr;
- }
-
-protected:
- explicit GoASTExpr(NodeKind kind) : GoASTNode(kind) {}
-
-private:
- GoASTExpr(const GoASTExpr &) = delete;
- const GoASTExpr &operator=(const GoASTExpr &) = delete;
-};
-
-class GoASTSpec : public GoASTNode {
-public:
- template <typename R, typename V> R Visit(V *v) const;
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() >= eImportSpec && n->GetKind() <= eValueSpec;
- }
-
-protected:
- explicit GoASTSpec(NodeKind kind) : GoASTNode(kind) {}
-
-private:
- GoASTSpec(const GoASTSpec &) = delete;
- const GoASTSpec &operator=(const GoASTSpec &) = delete;
-};
-
-class GoASTStmt : public GoASTNode {
-public:
- template <typename R, typename V> R Visit(V *v) const;
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() >= eAssignStmt && n->GetKind() <= eTypeSwitchStmt;
- }
-
-protected:
- explicit GoASTStmt(NodeKind kind) : GoASTNode(kind) {}
-
-private:
- GoASTStmt(const GoASTStmt &) = delete;
- const GoASTStmt &operator=(const GoASTStmt &) = delete;
-};
-
-class GoASTArrayType : public GoASTExpr {
-public:
- GoASTArrayType(GoASTExpr *len, GoASTExpr *elt)
- : GoASTExpr(eArrayType), m_len_up(len), m_elt_up(elt) {}
- ~GoASTArrayType() override = default;
-
- const char *GetKindName() const override { return "ArrayType"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eArrayType; }
-
- const GoASTExpr *GetLen() const { return m_len_up.get(); }
- void SetLen(GoASTExpr *len) { m_len_up.reset(len); }
-
- const GoASTExpr *GetElt() const { return m_elt_up.get(); }
- void SetElt(GoASTExpr *elt) { m_elt_up.reset(elt); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_len_up;
- std::unique_ptr<GoASTExpr> m_elt_up;
-
- GoASTArrayType(const GoASTArrayType &) = delete;
- const GoASTArrayType &operator=(const GoASTArrayType &) = delete;
-};
-
-class GoASTAssignStmt : public GoASTStmt {
-public:
- explicit GoASTAssignStmt(bool define)
- : GoASTStmt(eAssignStmt), m_define(define) {}
- ~GoASTAssignStmt() override = default;
-
- const char *GetKindName() const override { return "AssignStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eAssignStmt;
- }
-
- size_t NumLhs() const { return m_lhs.size(); }
- const GoASTExpr *GetLhs(int i) const { return m_lhs[i].get(); }
- void AddLhs(GoASTExpr *lhs) {
- m_lhs.push_back(std::unique_ptr<GoASTExpr>(lhs));
- }
-
- size_t NumRhs() const { return m_rhs.size(); }
- const GoASTExpr *GetRhs(int i) const { return m_rhs[i].get(); }
- void AddRhs(GoASTExpr *rhs) {
- m_rhs.push_back(std::unique_ptr<GoASTExpr>(rhs));
- }
-
- bool GetDefine() const { return m_define; }
- void SetDefine(bool define) { m_define = define; }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTExpr>> m_lhs;
- std::vector<std::unique_ptr<GoASTExpr>> m_rhs;
- bool m_define;
-
- GoASTAssignStmt(const GoASTAssignStmt &) = delete;
- const GoASTAssignStmt &operator=(const GoASTAssignStmt &) = delete;
-};
-
-class GoASTBadDecl : public GoASTDecl {
-public:
- GoASTBadDecl() : GoASTDecl(eBadDecl) {}
- ~GoASTBadDecl() override = default;
-
- const char *GetKindName() const override { return "BadDecl"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eBadDecl; }
-
- GoASTBadDecl(const GoASTBadDecl &) = delete;
- const GoASTBadDecl &operator=(const GoASTBadDecl &) = delete;
-};
-
-class GoASTBadExpr : public GoASTExpr {
-public:
- GoASTBadExpr() : GoASTExpr(eBadExpr) {}
- ~GoASTBadExpr() override = default;
-
- const char *GetKindName() const override { return "BadExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eBadExpr; }
-
- GoASTBadExpr(const GoASTBadExpr &) = delete;
- const GoASTBadExpr &operator=(const GoASTBadExpr &) = delete;
-};
-
-class GoASTBadStmt : public GoASTStmt {
-public:
- GoASTBadStmt() : GoASTStmt(eBadStmt) {}
- ~GoASTBadStmt() override = default;
-
- const char *GetKindName() const override { return "BadStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eBadStmt; }
-
- GoASTBadStmt(const GoASTBadStmt &) = delete;
- const GoASTBadStmt &operator=(const GoASTBadStmt &) = delete;
-};
-
-class GoASTBasicLit : public GoASTExpr {
-public:
- explicit GoASTBasicLit(Token value) : GoASTExpr(eBasicLit), m_value(value) {}
- ~GoASTBasicLit() override = default;
-
- const char *GetKindName() const override { return "BasicLit"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eBasicLit; }
-
- Token GetValue() const { return m_value; }
- void SetValue(Token value) { m_value = value; }
-
-private:
- friend class GoASTNode;
- Token m_value;
-
- GoASTBasicLit(const GoASTBasicLit &) = delete;
- const GoASTBasicLit &operator=(const GoASTBasicLit &) = delete;
-};
-
-class GoASTBinaryExpr : public GoASTExpr {
-public:
- GoASTBinaryExpr(GoASTExpr *x, GoASTExpr *y, TokenType op)
- : GoASTExpr(eBinaryExpr), m_x_up(x), m_y_up(y), m_op(op) {}
- ~GoASTBinaryExpr() override = default;
-
- const char *GetKindName() const override { return "BinaryExpr"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eBinaryExpr;
- }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- const GoASTExpr *GetY() const { return m_y_up.get(); }
- void SetY(GoASTExpr *y) { m_y_up.reset(y); }
-
- TokenType GetOp() const { return m_op; }
- void SetOp(TokenType op) { m_op = op; }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
- std::unique_ptr<GoASTExpr> m_y_up;
- TokenType m_op;
-
- GoASTBinaryExpr(const GoASTBinaryExpr &) = delete;
- const GoASTBinaryExpr &operator=(const GoASTBinaryExpr &) = delete;
-};
-
-class GoASTBlockStmt : public GoASTStmt {
-public:
- GoASTBlockStmt() : GoASTStmt(eBlockStmt) {}
- ~GoASTBlockStmt() override = default;
-
- const char *GetKindName() const override { return "BlockStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eBlockStmt; }
-
- size_t NumList() const { return m_list.size(); }
- const GoASTStmt *GetList(int i) const { return m_list[i].get(); }
- void AddList(GoASTStmt *list) {
- m_list.push_back(std::unique_ptr<GoASTStmt>(list));
- }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTStmt>> m_list;
-
- GoASTBlockStmt(const GoASTBlockStmt &) = delete;
- const GoASTBlockStmt &operator=(const GoASTBlockStmt &) = delete;
-};
-
-class GoASTIdent : public GoASTExpr {
-public:
- explicit GoASTIdent(Token name) : GoASTExpr(eIdent), m_name(name) {}
- ~GoASTIdent() override = default;
-
- const char *GetKindName() const override { return "Ident"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eIdent; }
-
- Token GetName() const { return m_name; }
- void SetName(Token name) { m_name = name; }
-
-private:
- friend class GoASTNode;
- Token m_name;
-
- GoASTIdent(const GoASTIdent &) = delete;
- const GoASTIdent &operator=(const GoASTIdent &) = delete;
-};
-
-class GoASTBranchStmt : public GoASTStmt {
-public:
- GoASTBranchStmt(GoASTIdent *label, TokenType tok)
- : GoASTStmt(eBranchStmt), m_label_up(label), m_tok(tok) {}
- ~GoASTBranchStmt() override = default;
-
- const char *GetKindName() const override { return "BranchStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eBranchStmt;
- }
-
- const GoASTIdent *GetLabel() const { return m_label_up.get(); }
- void SetLabel(GoASTIdent *label) { m_label_up.reset(label); }
-
- TokenType GetTok() const { return m_tok; }
- void SetTok(TokenType tok) { m_tok = tok; }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTIdent> m_label_up;
- TokenType m_tok;
-
- GoASTBranchStmt(const GoASTBranchStmt &) = delete;
- const GoASTBranchStmt &operator=(const GoASTBranchStmt &) = delete;
-};
-
-class GoASTCallExpr : public GoASTExpr {
-public:
- explicit GoASTCallExpr(bool ellipsis)
- : GoASTExpr(eCallExpr), m_ellipsis(ellipsis) {}
- ~GoASTCallExpr() override = default;
-
- const char *GetKindName() const override { return "CallExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eCallExpr; }
-
- const GoASTExpr *GetFun() const { return m_fun_up.get(); }
- void SetFun(GoASTExpr *fun) { m_fun_up.reset(fun); }
-
- size_t NumArgs() const { return m_args.size(); }
- const GoASTExpr *GetArgs(int i) const { return m_args[i].get(); }
- void AddArgs(GoASTExpr *args) {
- m_args.push_back(std::unique_ptr<GoASTExpr>(args));
- }
-
- bool GetEllipsis() const { return m_ellipsis; }
- void SetEllipsis(bool ellipsis) { m_ellipsis = ellipsis; }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_fun_up;
- std::vector<std::unique_ptr<GoASTExpr>> m_args;
- bool m_ellipsis;
-
- GoASTCallExpr(const GoASTCallExpr &) = delete;
- const GoASTCallExpr &operator=(const GoASTCallExpr &) = delete;
-};
-
-class GoASTCaseClause : public GoASTStmt {
-public:
- GoASTCaseClause() : GoASTStmt(eCaseClause) {}
- ~GoASTCaseClause() override = default;
-
- const char *GetKindName() const override { return "CaseClause"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eCaseClause;
- }
-
- size_t NumList() const { return m_list.size(); }
- const GoASTExpr *GetList(int i) const { return m_list[i].get(); }
- void AddList(GoASTExpr *list) {
- m_list.push_back(std::unique_ptr<GoASTExpr>(list));
- }
-
- size_t NumBody() const { return m_body.size(); }
- const GoASTStmt *GetBody(int i) const { return m_body[i].get(); }
- void AddBody(GoASTStmt *body) {
- m_body.push_back(std::unique_ptr<GoASTStmt>(body));
- }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTExpr>> m_list;
- std::vector<std::unique_ptr<GoASTStmt>> m_body;
-
- GoASTCaseClause(const GoASTCaseClause &) = delete;
- const GoASTCaseClause &operator=(const GoASTCaseClause &) = delete;
-};
-
-class GoASTChanType : public GoASTExpr {
-public:
- GoASTChanType(ChanDir dir, GoASTExpr *value)
- : GoASTExpr(eChanType), m_dir(dir), m_value_up(value) {}
- ~GoASTChanType() override = default;
-
- const char *GetKindName() const override { return "ChanType"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eChanType; }
-
- ChanDir GetDir() const { return m_dir; }
- void SetDir(ChanDir dir) { m_dir = dir; }
-
- const GoASTExpr *GetValue() const { return m_value_up.get(); }
- void SetValue(GoASTExpr *value) { m_value_up.reset(value); }
-
-private:
- friend class GoASTNode;
- ChanDir m_dir;
- std::unique_ptr<GoASTExpr> m_value_up;
-
- GoASTChanType(const GoASTChanType &) = delete;
- const GoASTChanType &operator=(const GoASTChanType &) = delete;
-};
-
-class GoASTCommClause : public GoASTStmt {
-public:
- GoASTCommClause() : GoASTStmt(eCommClause) {}
- ~GoASTCommClause() override = default;
-
- const char *GetKindName() const override { return "CommClause"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eCommClause;
- }
-
- const GoASTStmt *GetComm() const { return m_comm_up.get(); }
- void SetComm(GoASTStmt *comm) { m_comm_up.reset(comm); }
-
- size_t NumBody() const { return m_body.size(); }
- const GoASTStmt *GetBody(int i) const { return m_body[i].get(); }
- void AddBody(GoASTStmt *body) {
- m_body.push_back(std::unique_ptr<GoASTStmt>(body));
- }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTStmt> m_comm_up;
- std::vector<std::unique_ptr<GoASTStmt>> m_body;
-
- GoASTCommClause(const GoASTCommClause &) = delete;
- const GoASTCommClause &operator=(const GoASTCommClause &) = delete;
-};
-
-class GoASTCompositeLit : public GoASTExpr {
-public:
- GoASTCompositeLit() : GoASTExpr(eCompositeLit) {}
- ~GoASTCompositeLit() override = default;
-
- const char *GetKindName() const override { return "CompositeLit"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eCompositeLit;
- }
-
- const GoASTExpr *GetType() const { return m_type_up.get(); }
- void SetType(GoASTExpr *type) { m_type_up.reset(type); }
-
- size_t NumElts() const { return m_elts.size(); }
- const GoASTExpr *GetElts(int i) const { return m_elts[i].get(); }
- void AddElts(GoASTExpr *elts) {
- m_elts.push_back(std::unique_ptr<GoASTExpr>(elts));
- }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_type_up;
- std::vector<std::unique_ptr<GoASTExpr>> m_elts;
-
- GoASTCompositeLit(const GoASTCompositeLit &) = delete;
- const GoASTCompositeLit &operator=(const GoASTCompositeLit &) = delete;
-};
-
-class GoASTDeclStmt : public GoASTStmt {
-public:
- explicit GoASTDeclStmt(GoASTDecl *decl)
- : GoASTStmt(eDeclStmt), m_decl_up(decl) {}
- ~GoASTDeclStmt() override = default;
-
- const char *GetKindName() const override { return "DeclStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eDeclStmt; }
-
- const GoASTDecl *GetDecl() const { return m_decl_up.get(); }
- void SetDecl(GoASTDecl *decl) { m_decl_up.reset(decl); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTDecl> m_decl_up;
-
- GoASTDeclStmt(const GoASTDeclStmt &) = delete;
- const GoASTDeclStmt &operator=(const GoASTDeclStmt &) = delete;
-};
-
-class GoASTDeferStmt : public GoASTStmt {
-public:
- explicit GoASTDeferStmt(GoASTCallExpr *call)
- : GoASTStmt(eDeferStmt), m_call_up(call) {}
- ~GoASTDeferStmt() override = default;
-
- const char *GetKindName() const override { return "DeferStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eDeferStmt; }
-
- const GoASTCallExpr *GetCall() const { return m_call_up.get(); }
- void SetCall(GoASTCallExpr *call) { m_call_up.reset(call); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTCallExpr> m_call_up;
-
- GoASTDeferStmt(const GoASTDeferStmt &) = delete;
- const GoASTDeferStmt &operator=(const GoASTDeferStmt &) = delete;
-};
-
-class GoASTEllipsis : public GoASTExpr {
-public:
- explicit GoASTEllipsis(GoASTExpr *elt)
- : GoASTExpr(eEllipsis), m_elt_up(elt) {}
- ~GoASTEllipsis() override = default;
-
- const char *GetKindName() const override { return "Ellipsis"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eEllipsis; }
-
- const GoASTExpr *GetElt() const { return m_elt_up.get(); }
- void SetElt(GoASTExpr *elt) { m_elt_up.reset(elt); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_elt_up;
-
- GoASTEllipsis(const GoASTEllipsis &) = delete;
- const GoASTEllipsis &operator=(const GoASTEllipsis &) = delete;
-};
-
-class GoASTEmptyStmt : public GoASTStmt {
-public:
- GoASTEmptyStmt() : GoASTStmt(eEmptyStmt) {}
- ~GoASTEmptyStmt() override = default;
-
- const char *GetKindName() const override { return "EmptyStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eEmptyStmt; }
-
- GoASTEmptyStmt(const GoASTEmptyStmt &) = delete;
- const GoASTEmptyStmt &operator=(const GoASTEmptyStmt &) = delete;
-};
-
-class GoASTExprStmt : public GoASTStmt {
-public:
- explicit GoASTExprStmt(GoASTExpr *x) : GoASTStmt(eExprStmt), m_x_up(x) {}
- ~GoASTExprStmt() override = default;
-
- const char *GetKindName() const override { return "ExprStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eExprStmt; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
-
- GoASTExprStmt(const GoASTExprStmt &) = delete;
- const GoASTExprStmt &operator=(const GoASTExprStmt &) = delete;
-};
-
-class GoASTField : public GoASTNode {
-public:
- GoASTField() : GoASTNode(eField) {}
- ~GoASTField() override = default;
-
- const char *GetKindName() const override { return "Field"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eField; }
-
- size_t NumNames() const { return m_names.size(); }
- const GoASTIdent *GetNames(int i) const { return m_names[i].get(); }
- void AddNames(GoASTIdent *names) {
- m_names.push_back(std::unique_ptr<GoASTIdent>(names));
- }
-
- const GoASTExpr *GetType() const { return m_type_up.get(); }
- void SetType(GoASTExpr *type) { m_type_up.reset(type); }
-
- const GoASTBasicLit *GetTag() const { return m_tag_up.get(); }
- void SetTag(GoASTBasicLit *tag) { m_tag_up.reset(tag); }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTIdent>> m_names;
- std::unique_ptr<GoASTExpr> m_type_up;
- std::unique_ptr<GoASTBasicLit> m_tag_up;
-
- GoASTField(const GoASTField &) = delete;
- const GoASTField &operator=(const GoASTField &) = delete;
-};
-
-class GoASTFieldList : public GoASTNode {
-public:
- GoASTFieldList() : GoASTNode(eFieldList) {}
- ~GoASTFieldList() override = default;
-
- const char *GetKindName() const override { return "FieldList"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eFieldList; }
-
- size_t NumList() const { return m_list.size(); }
- const GoASTField *GetList(int i) const { return m_list[i].get(); }
- void AddList(GoASTField *list) {
- m_list.push_back(std::unique_ptr<GoASTField>(list));
- }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTField>> m_list;
-
- GoASTFieldList(const GoASTFieldList &) = delete;
- const GoASTFieldList &operator=(const GoASTFieldList &) = delete;
-};
-
-class GoASTForStmt : public GoASTStmt {
-public:
- GoASTForStmt(GoASTStmt *init, GoASTExpr *cond, GoASTStmt *post,
- GoASTBlockStmt *body)
- : GoASTStmt(eForStmt), m_init_up(init), m_cond_up(cond), m_post_up(post),
- m_body_up(body) {}
- ~GoASTForStmt() override = default;
-
- const char *GetKindName() const override { return "ForStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eForStmt; }
-
- const GoASTStmt *GetInit() const { return m_init_up.get(); }
- void SetInit(GoASTStmt *init) { m_init_up.reset(init); }
-
- const GoASTExpr *GetCond() const { return m_cond_up.get(); }
- void SetCond(GoASTExpr *cond) { m_cond_up.reset(cond); }
-
- const GoASTStmt *GetPost() const { return m_post_up.get(); }
- void SetPost(GoASTStmt *post) { m_post_up.reset(post); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTStmt> m_init_up;
- std::unique_ptr<GoASTExpr> m_cond_up;
- std::unique_ptr<GoASTStmt> m_post_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTForStmt(const GoASTForStmt &) = delete;
- const GoASTForStmt &operator=(const GoASTForStmt &) = delete;
-};
-
-class GoASTFuncType : public GoASTExpr {
-public:
- GoASTFuncType(GoASTFieldList *params, GoASTFieldList *results)
- : GoASTExpr(eFuncType), m_params_up(params), m_results_up(results) {}
- ~GoASTFuncType() override = default;
-
- const char *GetKindName() const override { return "FuncType"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eFuncType; }
-
- const GoASTFieldList *GetParams() const { return m_params_up.get(); }
- void SetParams(GoASTFieldList *params) { m_params_up.reset(params); }
-
- const GoASTFieldList *GetResults() const { return m_results_up.get(); }
- void SetResults(GoASTFieldList *results) { m_results_up.reset(results); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTFieldList> m_params_up;
- std::unique_ptr<GoASTFieldList> m_results_up;
-
- GoASTFuncType(const GoASTFuncType &) = delete;
- const GoASTFuncType &operator=(const GoASTFuncType &) = delete;
-};
-
-class GoASTFuncDecl : public GoASTDecl {
-public:
- GoASTFuncDecl(GoASTFieldList *recv, GoASTIdent *name, GoASTFuncType *type,
- GoASTBlockStmt *body)
- : GoASTDecl(eFuncDecl), m_recv_up(recv), m_name_up(name), m_type_up(type),
- m_body_up(body) {}
- ~GoASTFuncDecl() override = default;
-
- const char *GetKindName() const override { return "FuncDecl"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eFuncDecl; }
-
- const GoASTFieldList *GetRecv() const { return m_recv_up.get(); }
- void SetRecv(GoASTFieldList *recv) { m_recv_up.reset(recv); }
-
- const GoASTIdent *GetName() const { return m_name_up.get(); }
- void SetName(GoASTIdent *name) { m_name_up.reset(name); }
-
- const GoASTFuncType *GetType() const { return m_type_up.get(); }
- void SetType(GoASTFuncType *type) { m_type_up.reset(type); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTFieldList> m_recv_up;
- std::unique_ptr<GoASTIdent> m_name_up;
- std::unique_ptr<GoASTFuncType> m_type_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTFuncDecl(const GoASTFuncDecl &) = delete;
- const GoASTFuncDecl &operator=(const GoASTFuncDecl &) = delete;
-};
-
-class GoASTFuncLit : public GoASTExpr {
-public:
- GoASTFuncLit(GoASTFuncType *type, GoASTBlockStmt *body)
- : GoASTExpr(eFuncLit), m_type_up(type), m_body_up(body) {}
- ~GoASTFuncLit() override = default;
-
- const char *GetKindName() const override { return "FuncLit"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eFuncLit; }
-
- const GoASTFuncType *GetType() const { return m_type_up.get(); }
- void SetType(GoASTFuncType *type) { m_type_up.reset(type); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTFuncType> m_type_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTFuncLit(const GoASTFuncLit &) = delete;
- const GoASTFuncLit &operator=(const GoASTFuncLit &) = delete;
-};
-
-class GoASTGenDecl : public GoASTDecl {
-public:
- explicit GoASTGenDecl(TokenType tok) : GoASTDecl(eGenDecl), m_tok(tok) {}
- ~GoASTGenDecl() override = default;
-
- const char *GetKindName() const override { return "GenDecl"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eGenDecl; }
-
- TokenType GetTok() const { return m_tok; }
- void SetTok(TokenType tok) { m_tok = tok; }
-
- size_t NumSpecs() const { return m_specs.size(); }
- const GoASTSpec *GetSpecs(int i) const { return m_specs[i].get(); }
- void AddSpecs(GoASTSpec *specs) {
- m_specs.push_back(std::unique_ptr<GoASTSpec>(specs));
- }
-
-private:
- friend class GoASTNode;
- TokenType m_tok;
- std::vector<std::unique_ptr<GoASTSpec>> m_specs;
-
- GoASTGenDecl(const GoASTGenDecl &) = delete;
- const GoASTGenDecl &operator=(const GoASTGenDecl &) = delete;
-};
-
-class GoASTGoStmt : public GoASTStmt {
-public:
- explicit GoASTGoStmt(GoASTCallExpr *call)
- : GoASTStmt(eGoStmt), m_call_up(call) {}
- ~GoASTGoStmt() override = default;
-
- const char *GetKindName() const override { return "GoStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eGoStmt; }
-
- const GoASTCallExpr *GetCall() const { return m_call_up.get(); }
- void SetCall(GoASTCallExpr *call) { m_call_up.reset(call); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTCallExpr> m_call_up;
-
- GoASTGoStmt(const GoASTGoStmt &) = delete;
- const GoASTGoStmt &operator=(const GoASTGoStmt &) = delete;
-};
-
-class GoASTIfStmt : public GoASTStmt {
-public:
- GoASTIfStmt(GoASTStmt *init, GoASTExpr *cond, GoASTBlockStmt *body,
- GoASTStmt *els)
- : GoASTStmt(eIfStmt), m_init_up(init), m_cond_up(cond), m_body_up(body),
- m_els_up(els) {}
- ~GoASTIfStmt() override = default;
-
- const char *GetKindName() const override { return "IfStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eIfStmt; }
-
- const GoASTStmt *GetInit() const { return m_init_up.get(); }
- void SetInit(GoASTStmt *init) { m_init_up.reset(init); }
-
- const GoASTExpr *GetCond() const { return m_cond_up.get(); }
- void SetCond(GoASTExpr *cond) { m_cond_up.reset(cond); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
- const GoASTStmt *GetEls() const { return m_els_up.get(); }
- void SetEls(GoASTStmt *els) { m_els_up.reset(els); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTStmt> m_init_up;
- std::unique_ptr<GoASTExpr> m_cond_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
- std::unique_ptr<GoASTStmt> m_els_up;
-
- GoASTIfStmt(const GoASTIfStmt &) = delete;
- const GoASTIfStmt &operator=(const GoASTIfStmt &) = delete;
-};
-
-class GoASTImportSpec : public GoASTSpec {
-public:
- GoASTImportSpec(GoASTIdent *name, GoASTBasicLit *path)
- : GoASTSpec(eImportSpec), m_name_up(name), m_path_up(path) {}
- ~GoASTImportSpec() override = default;
-
- const char *GetKindName() const override { return "ImportSpec"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eImportSpec;
- }
-
- const GoASTIdent *GetName() const { return m_name_up.get(); }
- void SetName(GoASTIdent *name) { m_name_up.reset(name); }
-
- const GoASTBasicLit *GetPath() const { return m_path_up.get(); }
- void SetPath(GoASTBasicLit *path) { m_path_up.reset(path); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTIdent> m_name_up;
- std::unique_ptr<GoASTBasicLit> m_path_up;
-
- GoASTImportSpec(const GoASTImportSpec &) = delete;
- const GoASTImportSpec &operator=(const GoASTImportSpec &) = delete;
-};
-
-class GoASTIncDecStmt : public GoASTStmt {
-public:
- GoASTIncDecStmt(GoASTExpr *x, TokenType tok)
- : GoASTStmt(eIncDecStmt), m_x_up(x), m_tok(tok) {}
- ~GoASTIncDecStmt() override = default;
-
- const char *GetKindName() const override { return "IncDecStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eIncDecStmt;
- }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- TokenType GetTok() const { return m_tok; }
- void SetTok(TokenType tok) { m_tok = tok; }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
- TokenType m_tok;
-
- GoASTIncDecStmt(const GoASTIncDecStmt &) = delete;
- const GoASTIncDecStmt &operator=(const GoASTIncDecStmt &) = delete;
-};
-
-class GoASTIndexExpr : public GoASTExpr {
-public:
- GoASTIndexExpr(GoASTExpr *x, GoASTExpr *index)
- : GoASTExpr(eIndexExpr), m_x_up(x), m_index_up(index) {}
- ~GoASTIndexExpr() override = default;
-
- const char *GetKindName() const override { return "IndexExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eIndexExpr; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- const GoASTExpr *GetIndex() const { return m_index_up.get(); }
- void SetIndex(GoASTExpr *index) { m_index_up.reset(index); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
- std::unique_ptr<GoASTExpr> m_index_up;
-
- GoASTIndexExpr(const GoASTIndexExpr &) = delete;
- const GoASTIndexExpr &operator=(const GoASTIndexExpr &) = delete;
-};
-
-class GoASTInterfaceType : public GoASTExpr {
-public:
- explicit GoASTInterfaceType(GoASTFieldList *methods)
- : GoASTExpr(eInterfaceType), m_methods_up(methods) {}
- ~GoASTInterfaceType() override = default;
-
- const char *GetKindName() const override { return "InterfaceType"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eInterfaceType;
- }
-
- const GoASTFieldList *GetMethods() const { return m_methods_up.get(); }
- void SetMethods(GoASTFieldList *methods) { m_methods_up.reset(methods); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTFieldList> m_methods_up;
-
- GoASTInterfaceType(const GoASTInterfaceType &) = delete;
- const GoASTInterfaceType &operator=(const GoASTInterfaceType &) = delete;
-};
-
-class GoASTKeyValueExpr : public GoASTExpr {
-public:
- GoASTKeyValueExpr(GoASTExpr *key, GoASTExpr *value)
- : GoASTExpr(eKeyValueExpr), m_key_up(key), m_value_up(value) {}
- ~GoASTKeyValueExpr() override = default;
-
- const char *GetKindName() const override { return "KeyValueExpr"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eKeyValueExpr;
- }
-
- const GoASTExpr *GetKey() const { return m_key_up.get(); }
- void SetKey(GoASTExpr *key) { m_key_up.reset(key); }
-
- const GoASTExpr *GetValue() const { return m_value_up.get(); }
- void SetValue(GoASTExpr *value) { m_value_up.reset(value); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_key_up;
- std::unique_ptr<GoASTExpr> m_value_up;
-
- GoASTKeyValueExpr(const GoASTKeyValueExpr &) = delete;
- const GoASTKeyValueExpr &operator=(const GoASTKeyValueExpr &) = delete;
-};
-
-class GoASTLabeledStmt : public GoASTStmt {
-public:
- GoASTLabeledStmt(GoASTIdent *label, GoASTStmt *stmt)
- : GoASTStmt(eLabeledStmt), m_label_up(label), m_stmt_up(stmt) {}
- ~GoASTLabeledStmt() override = default;
-
- const char *GetKindName() const override { return "LabeledStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eLabeledStmt;
- }
-
- const GoASTIdent *GetLabel() const { return m_label_up.get(); }
- void SetLabel(GoASTIdent *label) { m_label_up.reset(label); }
-
- const GoASTStmt *GetStmt() const { return m_stmt_up.get(); }
- void SetStmt(GoASTStmt *stmt) { m_stmt_up.reset(stmt); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTIdent> m_label_up;
- std::unique_ptr<GoASTStmt> m_stmt_up;
-
- GoASTLabeledStmt(const GoASTLabeledStmt &) = delete;
- const GoASTLabeledStmt &operator=(const GoASTLabeledStmt &) = delete;
-};
-
-class GoASTMapType : public GoASTExpr {
-public:
- GoASTMapType(GoASTExpr *key, GoASTExpr *value)
- : GoASTExpr(eMapType), m_key_up(key), m_value_up(value) {}
- ~GoASTMapType() override = default;
-
- const char *GetKindName() const override { return "MapType"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eMapType; }
-
- const GoASTExpr *GetKey() const { return m_key_up.get(); }
- void SetKey(GoASTExpr *key) { m_key_up.reset(key); }
-
- const GoASTExpr *GetValue() const { return m_value_up.get(); }
- void SetValue(GoASTExpr *value) { m_value_up.reset(value); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_key_up;
- std::unique_ptr<GoASTExpr> m_value_up;
-
- GoASTMapType(const GoASTMapType &) = delete;
- const GoASTMapType &operator=(const GoASTMapType &) = delete;
-};
-
-class GoASTParenExpr : public GoASTExpr {
-public:
- explicit GoASTParenExpr(GoASTExpr *x) : GoASTExpr(eParenExpr), m_x_up(x) {}
- ~GoASTParenExpr() override = default;
-
- const char *GetKindName() const override { return "ParenExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eParenExpr; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
-
- GoASTParenExpr(const GoASTParenExpr &) = delete;
- const GoASTParenExpr &operator=(const GoASTParenExpr &) = delete;
-};
-
-class GoASTRangeStmt : public GoASTStmt {
-public:
- GoASTRangeStmt(GoASTExpr *key, GoASTExpr *value, bool define, GoASTExpr *x,
- GoASTBlockStmt *body)
- : GoASTStmt(eRangeStmt), m_key_up(key), m_value_up(value),
- m_define(define), m_x_up(x), m_body_up(body) {}
- ~GoASTRangeStmt() override = default;
-
- const char *GetKindName() const override { return "RangeStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eRangeStmt; }
-
- const GoASTExpr *GetKey() const { return m_key_up.get(); }
- void SetKey(GoASTExpr *key) { m_key_up.reset(key); }
-
- const GoASTExpr *GetValue() const { return m_value_up.get(); }
- void SetValue(GoASTExpr *value) { m_value_up.reset(value); }
-
- bool GetDefine() const { return m_define; }
- void SetDefine(bool define) { m_define = define; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_key_up;
- std::unique_ptr<GoASTExpr> m_value_up;
- bool m_define;
- std::unique_ptr<GoASTExpr> m_x_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTRangeStmt(const GoASTRangeStmt &) = delete;
- const GoASTRangeStmt &operator=(const GoASTRangeStmt &) = delete;
-};
-
-class GoASTReturnStmt : public GoASTStmt {
-public:
- GoASTReturnStmt() : GoASTStmt(eReturnStmt) {}
- ~GoASTReturnStmt() override = default;
-
- const char *GetKindName() const override { return "ReturnStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eReturnStmt;
- }
-
- size_t NumResults() const { return m_results.size(); }
- const GoASTExpr *GetResults(int i) const { return m_results[i].get(); }
- void AddResults(GoASTExpr *results) {
- m_results.push_back(std::unique_ptr<GoASTExpr>(results));
- }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTExpr>> m_results;
-
- GoASTReturnStmt(const GoASTReturnStmt &) = delete;
- const GoASTReturnStmt &operator=(const GoASTReturnStmt &) = delete;
-};
-
-class GoASTSelectStmt : public GoASTStmt {
-public:
- explicit GoASTSelectStmt(GoASTBlockStmt *body)
- : GoASTStmt(eSelectStmt), m_body_up(body) {}
- ~GoASTSelectStmt() override = default;
-
- const char *GetKindName() const override { return "SelectStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eSelectStmt;
- }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTSelectStmt(const GoASTSelectStmt &) = delete;
- const GoASTSelectStmt &operator=(const GoASTSelectStmt &) = delete;
-};
-
-class GoASTSelectorExpr : public GoASTExpr {
-public:
- GoASTSelectorExpr(GoASTExpr *x, GoASTIdent *sel)
- : GoASTExpr(eSelectorExpr), m_x_up(x), m_sel_up(sel) {}
- ~GoASTSelectorExpr() override = default;
-
- const char *GetKindName() const override { return "SelectorExpr"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eSelectorExpr;
- }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- const GoASTIdent *GetSel() const { return m_sel_up.get(); }
- void SetSel(GoASTIdent *sel) { m_sel_up.reset(sel); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
- std::unique_ptr<GoASTIdent> m_sel_up;
-
- GoASTSelectorExpr(const GoASTSelectorExpr &) = delete;
- const GoASTSelectorExpr &operator=(const GoASTSelectorExpr &) = delete;
-};
-
-class GoASTSendStmt : public GoASTStmt {
-public:
- GoASTSendStmt(GoASTExpr *chan, GoASTExpr *value)
- : GoASTStmt(eSendStmt), m_chan_up(chan), m_value_up(value) {}
- ~GoASTSendStmt() override = default;
-
- const char *GetKindName() const override { return "SendStmt"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eSendStmt; }
-
- const GoASTExpr *GetChan() const { return m_chan_up.get(); }
- void SetChan(GoASTExpr *chan) { m_chan_up.reset(chan); }
-
- const GoASTExpr *GetValue() const { return m_value_up.get(); }
- void SetValue(GoASTExpr *value) { m_value_up.reset(value); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_chan_up;
- std::unique_ptr<GoASTExpr> m_value_up;
-
- GoASTSendStmt(const GoASTSendStmt &) = delete;
- const GoASTSendStmt &operator=(const GoASTSendStmt &) = delete;
-};
-
-class GoASTSliceExpr : public GoASTExpr {
-public:
- GoASTSliceExpr(GoASTExpr *x, GoASTExpr *low, GoASTExpr *high, GoASTExpr *max,
- bool slice3)
- : GoASTExpr(eSliceExpr), m_x_up(x), m_low_up(low), m_high_up(high),
- m_max_up(max), m_slice3(slice3) {}
- ~GoASTSliceExpr() override = default;
-
- const char *GetKindName() const override { return "SliceExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eSliceExpr; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- const GoASTExpr *GetLow() const { return m_low_up.get(); }
- void SetLow(GoASTExpr *low) { m_low_up.reset(low); }
-
- const GoASTExpr *GetHigh() const { return m_high_up.get(); }
- void SetHigh(GoASTExpr *high) { m_high_up.reset(high); }
-
- const GoASTExpr *GetMax() const { return m_max_up.get(); }
- void SetMax(GoASTExpr *max) { m_max_up.reset(max); }
-
- bool GetSlice3() const { return m_slice3; }
- void SetSlice3(bool slice3) { m_slice3 = slice3; }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
- std::unique_ptr<GoASTExpr> m_low_up;
- std::unique_ptr<GoASTExpr> m_high_up;
- std::unique_ptr<GoASTExpr> m_max_up;
- bool m_slice3;
-
- GoASTSliceExpr(const GoASTSliceExpr &) = delete;
- const GoASTSliceExpr &operator=(const GoASTSliceExpr &) = delete;
-};
-
-class GoASTStarExpr : public GoASTExpr {
-public:
- explicit GoASTStarExpr(GoASTExpr *x) : GoASTExpr(eStarExpr), m_x_up(x) {}
- ~GoASTStarExpr() override = default;
-
- const char *GetKindName() const override { return "StarExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eStarExpr; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
-
- GoASTStarExpr(const GoASTStarExpr &) = delete;
- const GoASTStarExpr &operator=(const GoASTStarExpr &) = delete;
-};
-
-class GoASTStructType : public GoASTExpr {
-public:
- explicit GoASTStructType(GoASTFieldList *fields)
- : GoASTExpr(eStructType), m_fields_up(fields) {}
- ~GoASTStructType() override = default;
-
- const char *GetKindName() const override { return "StructType"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eStructType;
- }
-
- const GoASTFieldList *GetFields() const { return m_fields_up.get(); }
- void SetFields(GoASTFieldList *fields) { m_fields_up.reset(fields); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTFieldList> m_fields_up;
-
- GoASTStructType(const GoASTStructType &) = delete;
- const GoASTStructType &operator=(const GoASTStructType &) = delete;
-};
-
-class GoASTSwitchStmt : public GoASTStmt {
-public:
- GoASTSwitchStmt(GoASTStmt *init, GoASTExpr *tag, GoASTBlockStmt *body)
- : GoASTStmt(eSwitchStmt), m_init_up(init), m_tag_up(tag),
- m_body_up(body) {}
- ~GoASTSwitchStmt() override = default;
-
- const char *GetKindName() const override { return "SwitchStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eSwitchStmt;
- }
-
- const GoASTStmt *GetInit() const { return m_init_up.get(); }
- void SetInit(GoASTStmt *init) { m_init_up.reset(init); }
-
- const GoASTExpr *GetTag() const { return m_tag_up.get(); }
- void SetTag(GoASTExpr *tag) { m_tag_up.reset(tag); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTStmt> m_init_up;
- std::unique_ptr<GoASTExpr> m_tag_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTSwitchStmt(const GoASTSwitchStmt &) = delete;
- const GoASTSwitchStmt &operator=(const GoASTSwitchStmt &) = delete;
-};
-
-class GoASTTypeAssertExpr : public GoASTExpr {
-public:
- GoASTTypeAssertExpr(GoASTExpr *x, GoASTExpr *type)
- : GoASTExpr(eTypeAssertExpr), m_x_up(x), m_type_up(type) {}
- ~GoASTTypeAssertExpr() override = default;
-
- const char *GetKindName() const override { return "TypeAssertExpr"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eTypeAssertExpr;
- }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
- const GoASTExpr *GetType() const { return m_type_up.get(); }
- void SetType(GoASTExpr *type) { m_type_up.reset(type); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTExpr> m_x_up;
- std::unique_ptr<GoASTExpr> m_type_up;
-
- GoASTTypeAssertExpr(const GoASTTypeAssertExpr &) = delete;
- const GoASTTypeAssertExpr &operator=(const GoASTTypeAssertExpr &) = delete;
-};
-
-class GoASTTypeSpec : public GoASTSpec {
-public:
- GoASTTypeSpec(GoASTIdent *name, GoASTExpr *type)
- : GoASTSpec(eTypeSpec), m_name_up(name), m_type_up(type) {}
- ~GoASTTypeSpec() override = default;
-
- const char *GetKindName() const override { return "TypeSpec"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eTypeSpec; }
-
- const GoASTIdent *GetName() const { return m_name_up.get(); }
- void SetName(GoASTIdent *name) { m_name_up.reset(name); }
-
- const GoASTExpr *GetType() const { return m_type_up.get(); }
- void SetType(GoASTExpr *type) { m_type_up.reset(type); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTIdent> m_name_up;
- std::unique_ptr<GoASTExpr> m_type_up;
-
- GoASTTypeSpec(const GoASTTypeSpec &) = delete;
- const GoASTTypeSpec &operator=(const GoASTTypeSpec &) = delete;
-};
-
-class GoASTTypeSwitchStmt : public GoASTStmt {
-public:
- GoASTTypeSwitchStmt(GoASTStmt *init, GoASTStmt *assign, GoASTBlockStmt *body)
- : GoASTStmt(eTypeSwitchStmt), m_init_up(init), m_assign_up(assign),
- m_body_up(body) {}
- ~GoASTTypeSwitchStmt() override = default;
-
- const char *GetKindName() const override { return "TypeSwitchStmt"; }
-
- static bool classof(const GoASTNode *n) {
- return n->GetKind() == eTypeSwitchStmt;
- }
-
- const GoASTStmt *GetInit() const { return m_init_up.get(); }
- void SetInit(GoASTStmt *init) { m_init_up.reset(init); }
-
- const GoASTStmt *GetAssign() const { return m_assign_up.get(); }
- void SetAssign(GoASTStmt *assign) { m_assign_up.reset(assign); }
-
- const GoASTBlockStmt *GetBody() const { return m_body_up.get(); }
- void SetBody(GoASTBlockStmt *body) { m_body_up.reset(body); }
-
-private:
- friend class GoASTNode;
- std::unique_ptr<GoASTStmt> m_init_up;
- std::unique_ptr<GoASTStmt> m_assign_up;
- std::unique_ptr<GoASTBlockStmt> m_body_up;
-
- GoASTTypeSwitchStmt(const GoASTTypeSwitchStmt &) = delete;
- const GoASTTypeSwitchStmt &operator=(const GoASTTypeSwitchStmt &) = delete;
-};
-
-class GoASTUnaryExpr : public GoASTExpr {
-public:
- GoASTUnaryExpr(TokenType op, GoASTExpr *x)
- : GoASTExpr(eUnaryExpr), m_op(op), m_x_up(x) {}
- ~GoASTUnaryExpr() override = default;
-
- const char *GetKindName() const override { return "UnaryExpr"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eUnaryExpr; }
-
- TokenType GetOp() const { return m_op; }
- void SetOp(TokenType op) { m_op = op; }
-
- const GoASTExpr *GetX() const { return m_x_up.get(); }
- void SetX(GoASTExpr *x) { m_x_up.reset(x); }
-
-private:
- friend class GoASTNode;
- TokenType m_op;
- std::unique_ptr<GoASTExpr> m_x_up;
-
- GoASTUnaryExpr(const GoASTUnaryExpr &) = delete;
- const GoASTUnaryExpr &operator=(const GoASTUnaryExpr &) = delete;
-};
-
-class GoASTValueSpec : public GoASTSpec {
-public:
- GoASTValueSpec() : GoASTSpec(eValueSpec) {}
- ~GoASTValueSpec() override = default;
-
- const char *GetKindName() const override { return "ValueSpec"; }
-
- static bool classof(const GoASTNode *n) { return n->GetKind() == eValueSpec; }
-
- size_t NumNames() const { return m_names.size(); }
- const GoASTIdent *GetNames(int i) const { return m_names[i].get(); }
- void AddNames(GoASTIdent *names) {
- m_names.push_back(std::unique_ptr<GoASTIdent>(names));
- }
-
- const GoASTExpr *GetType() const { return m_type_up.get(); }
- void SetType(GoASTExpr *type) { m_type_up.reset(type); }
-
- size_t NumValues() const { return m_values.size(); }
- const GoASTExpr *GetValues(int i) const { return m_values[i].get(); }
- void AddValues(GoASTExpr *values) {
- m_values.push_back(std::unique_ptr<GoASTExpr>(values));
- }
-
-private:
- friend class GoASTNode;
- std::vector<std::unique_ptr<GoASTIdent>> m_names;
- std::unique_ptr<GoASTExpr> m_type_up;
- std::vector<std::unique_ptr<GoASTExpr>> m_values;
-
- GoASTValueSpec(const GoASTValueSpec &) = delete;
- const GoASTValueSpec &operator=(const GoASTValueSpec &) = delete;
-};
-
-template <typename R, typename V> R GoASTDecl::Visit(V *v) const {
- switch (GetKind()) {
- case eBadDecl:
- return v->VisitBadDecl(llvm::cast<const GoASTBadDecl>(this));
- case eFuncDecl:
- return v->VisitFuncDecl(llvm::cast<const GoASTFuncDecl>(this));
- case eGenDecl:
- return v->VisitGenDecl(llvm::cast<const GoASTGenDecl>(this));
- default:
- assert(false && "Invalid kind");
- }
-}
-
-template <typename R, typename V> R GoASTExpr::Visit(V *v) const {
- switch (GetKind()) {
- case eArrayType:
- return v->VisitArrayType(llvm::cast<const GoASTArrayType>(this));
- case eBadExpr:
- return v->VisitBadExpr(llvm::cast<const GoASTBadExpr>(this));
- case eBasicLit:
- return v->VisitBasicLit(llvm::cast<const GoASTBasicLit>(this));
- case eBinaryExpr:
- return v->VisitBinaryExpr(llvm::cast<const GoASTBinaryExpr>(this));
- case eIdent:
- return v->VisitIdent(llvm::cast<const GoASTIdent>(this));
- case eCallExpr:
- return v->VisitCallExpr(llvm::cast<const GoASTCallExpr>(this));
- case eChanType:
- return v->VisitChanType(llvm::cast<const GoASTChanType>(this));
- case eCompositeLit:
- return v->VisitCompositeLit(llvm::cast<const GoASTCompositeLit>(this));
- case eEllipsis:
- return v->VisitEllipsis(llvm::cast<const GoASTEllipsis>(this));
- case eFuncType:
- return v->VisitFuncType(llvm::cast<const GoASTFuncType>(this));
- case eFuncLit:
- return v->VisitFuncLit(llvm::cast<const GoASTFuncLit>(this));
- case eIndexExpr:
- return v->VisitIndexExpr(llvm::cast<const GoASTIndexExpr>(this));
- case eInterfaceType:
- return v->VisitInterfaceType(llvm::cast<const GoASTInterfaceType>(this));
- case eKeyValueExpr:
- return v->VisitKeyValueExpr(llvm::cast<const GoASTKeyValueExpr>(this));
- case eMapType:
- return v->VisitMapType(llvm::cast<const GoASTMapType>(this));
- case eParenExpr:
- return v->VisitParenExpr(llvm::cast<const GoASTParenExpr>(this));
- case eSelectorExpr:
- return v->VisitSelectorExpr(llvm::cast<const GoASTSelectorExpr>(this));
- case eSliceExpr:
- return v->VisitSliceExpr(llvm::cast<const GoASTSliceExpr>(this));
- case eStarExpr:
- return v->VisitStarExpr(llvm::cast<const GoASTStarExpr>(this));
- case eStructType:
- return v->VisitStructType(llvm::cast<const GoASTStructType>(this));
- case eTypeAssertExpr:
- return v->VisitTypeAssertExpr(llvm::cast<const GoASTTypeAssertExpr>(this));
- case eUnaryExpr:
- return v->VisitUnaryExpr(llvm::cast<const GoASTUnaryExpr>(this));
- default:
- assert(false && "Invalid kind");
- return R();
- }
-}
-
-template <typename R, typename V> R GoASTSpec::Visit(V *v) const {
- switch (GetKind()) {
- case eImportSpec:
- return v->VisitImportSpec(llvm::cast<const GoASTImportSpec>(this));
- case eTypeSpec:
- return v->VisitTypeSpec(llvm::cast<const GoASTTypeSpec>(this));
- case eValueSpec:
- return v->VisitValueSpec(llvm::cast<const GoASTValueSpec>(this));
- default:
- assert(false && "Invalid kind");
- }
-}
-
-template <typename R, typename V> R GoASTStmt::Visit(V *v) const {
- switch (GetKind()) {
- case eAssignStmt:
- return v->VisitAssignStmt(llvm::cast<const GoASTAssignStmt>(this));
- case eBadStmt:
- return v->VisitBadStmt(llvm::cast<const GoASTBadStmt>(this));
- case eBlockStmt:
- return v->VisitBlockStmt(llvm::cast<const GoASTBlockStmt>(this));
- case eBranchStmt:
- return v->VisitBranchStmt(llvm::cast<const GoASTBranchStmt>(this));
- case eCaseClause:
- return v->VisitCaseClause(llvm::cast<const GoASTCaseClause>(this));
- case eCommClause:
- return v->VisitCommClause(llvm::cast<const GoASTCommClause>(this));
- case eDeclStmt:
- return v->VisitDeclStmt(llvm::cast<const GoASTDeclStmt>(this));
- case eDeferStmt:
- return v->VisitDeferStmt(llvm::cast<const GoASTDeferStmt>(this));
- case eEmptyStmt:
- return v->VisitEmptyStmt(llvm::cast<const GoASTEmptyStmt>(this));
- case eExprStmt:
- return v->VisitExprStmt(llvm::cast<const GoASTExprStmt>(this));
- case eForStmt:
- return v->VisitForStmt(llvm::cast<const GoASTForStmt>(this));
- case eGoStmt:
- return v->VisitGoStmt(llvm::cast<const GoASTGoStmt>(this));
- case eIfStmt:
- return v->VisitIfStmt(llvm::cast<const GoASTIfStmt>(this));
- case eIncDecStmt:
- return v->VisitIncDecStmt(llvm::cast<const GoASTIncDecStmt>(this));
- case eLabeledStmt:
- return v->VisitLabeledStmt(llvm::cast<const GoASTLabeledStmt>(this));
- case eRangeStmt:
- return v->VisitRangeStmt(llvm::cast<const GoASTRangeStmt>(this));
- case eReturnStmt:
- return v->VisitReturnStmt(llvm::cast<const GoASTReturnStmt>(this));
- case eSelectStmt:
- return v->VisitSelectStmt(llvm::cast<const GoASTSelectStmt>(this));
- case eSendStmt:
- return v->VisitSendStmt(llvm::cast<const GoASTSendStmt>(this));
- case eSwitchStmt:
- return v->VisitSwitchStmt(llvm::cast<const GoASTSwitchStmt>(this));
- case eTypeSwitchStmt:
- return v->VisitTypeSwitchStmt(llvm::cast<const GoASTTypeSwitchStmt>(this));
- default:
- assert(false && "Invalid kind");
- }
-}
-
-template <typename V> void GoASTNode::WalkChildren(V &v) {
- switch (m_kind) {
-
- case eArrayType: {
- GoASTArrayType *n = llvm::cast<GoASTArrayType>(this);
- (void)n;
- v(n->m_len_up.get());
- v(n->m_elt_up.get());
- return;
- }
- case eAssignStmt: {
- GoASTAssignStmt *n = llvm::cast<GoASTAssignStmt>(this);
- (void)n;
- for (auto &e : n->m_lhs) {
- v(e.get());
- }
- for (auto &e : n->m_rhs) {
- v(e.get());
- }
- return;
- }
- case eBasicLit: {
- GoASTBasicLit *n = llvm::cast<GoASTBasicLit>(this);
- (void)n;
- return;
- }
- case eBinaryExpr: {
- GoASTBinaryExpr *n = llvm::cast<GoASTBinaryExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- v(n->m_y_up.get());
- return;
- }
- case eBlockStmt: {
- GoASTBlockStmt *n = llvm::cast<GoASTBlockStmt>(this);
- (void)n;
- for (auto &e : n->m_list) {
- v(e.get());
- }
- return;
- }
- case eIdent: {
- GoASTIdent *n = llvm::cast<GoASTIdent>(this);
- (void)n;
- return;
- }
- case eBranchStmt: {
- GoASTBranchStmt *n = llvm::cast<GoASTBranchStmt>(this);
- (void)n;
- v(n->m_label_up.get());
- return;
- }
- case eCallExpr: {
- GoASTCallExpr *n = llvm::cast<GoASTCallExpr>(this);
- (void)n;
- v(n->m_fun_up.get());
- for (auto &e : n->m_args) {
- v(e.get());
- }
- return;
- }
- case eCaseClause: {
- GoASTCaseClause *n = llvm::cast<GoASTCaseClause>(this);
- (void)n;
- for (auto &e : n->m_list) {
- v(e.get());
- }
- for (auto &e : n->m_body) {
- v(e.get());
- }
- return;
- }
- case eChanType: {
- GoASTChanType *n = llvm::cast<GoASTChanType>(this);
- (void)n;
- v(n->m_value_up.get());
- return;
- }
- case eCommClause: {
- GoASTCommClause *n = llvm::cast<GoASTCommClause>(this);
- (void)n;
- v(n->m_comm_up.get());
- for (auto &e : n->m_body) {
- v(e.get());
- }
- return;
- }
- case eCompositeLit: {
- GoASTCompositeLit *n = llvm::cast<GoASTCompositeLit>(this);
- (void)n;
- v(n->m_type_up.get());
- for (auto &e : n->m_elts) {
- v(e.get());
- }
- return;
- }
- case eDeclStmt: {
- GoASTDeclStmt *n = llvm::cast<GoASTDeclStmt>(this);
- (void)n;
- v(n->m_decl_up.get());
- return;
- }
- case eDeferStmt: {
- GoASTDeferStmt *n = llvm::cast<GoASTDeferStmt>(this);
- (void)n;
- v(n->m_call_up.get());
- return;
- }
- case eEllipsis: {
- GoASTEllipsis *n = llvm::cast<GoASTEllipsis>(this);
- (void)n;
- v(n->m_elt_up.get());
- return;
- }
- case eExprStmt: {
- GoASTExprStmt *n = llvm::cast<GoASTExprStmt>(this);
- (void)n;
- v(n->m_x_up.get());
- return;
- }
- case eField: {
- GoASTField *n = llvm::cast<GoASTField>(this);
- (void)n;
- for (auto &e : n->m_names) {
- v(e.get());
- }
- v(n->m_type_up.get());
- v(n->m_tag_up.get());
- return;
- }
- case eFieldList: {
- GoASTFieldList *n = llvm::cast<GoASTFieldList>(this);
- (void)n;
- for (auto &e : n->m_list) {
- v(e.get());
- }
- return;
- }
- case eForStmt: {
- GoASTForStmt *n = llvm::cast<GoASTForStmt>(this);
- (void)n;
- v(n->m_init_up.get());
- v(n->m_cond_up.get());
- v(n->m_post_up.get());
- v(n->m_body_up.get());
- return;
- }
- case eFuncType: {
- GoASTFuncType *n = llvm::cast<GoASTFuncType>(this);
- (void)n;
- v(n->m_params_up.get());
- v(n->m_results_up.get());
- return;
- }
- case eFuncDecl: {
- GoASTFuncDecl *n = llvm::cast<GoASTFuncDecl>(this);
- (void)n;
- v(n->m_recv_up.get());
- v(n->m_name_up.get());
- v(n->m_type_up.get());
- v(n->m_body_up.get());
- return;
- }
- case eFuncLit: {
- GoASTFuncLit *n = llvm::cast<GoASTFuncLit>(this);
- (void)n;
- v(n->m_type_up.get());
- v(n->m_body_up.get());
- return;
- }
- case eGenDecl: {
- GoASTGenDecl *n = llvm::cast<GoASTGenDecl>(this);
- (void)n;
- for (auto &e : n->m_specs) {
- v(e.get());
- }
- return;
- }
- case eGoStmt: {
- GoASTGoStmt *n = llvm::cast<GoASTGoStmt>(this);
- (void)n;
- v(n->m_call_up.get());
- return;
- }
- case eIfStmt: {
- GoASTIfStmt *n = llvm::cast<GoASTIfStmt>(this);
- (void)n;
- v(n->m_init_up.get());
- v(n->m_cond_up.get());
- v(n->m_body_up.get());
- v(n->m_els_up.get());
- return;
- }
- case eImportSpec: {
- GoASTImportSpec *n = llvm::cast<GoASTImportSpec>(this);
- (void)n;
- v(n->m_name_up.get());
- v(n->m_path_up.get());
- return;
- }
- case eIncDecStmt: {
- GoASTIncDecStmt *n = llvm::cast<GoASTIncDecStmt>(this);
- (void)n;
- v(n->m_x_up.get());
- return;
- }
- case eIndexExpr: {
- GoASTIndexExpr *n = llvm::cast<GoASTIndexExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- v(n->m_index_up.get());
- return;
- }
- case eInterfaceType: {
- GoASTInterfaceType *n = llvm::cast<GoASTInterfaceType>(this);
- (void)n;
- v(n->m_methods_up.get());
- return;
- }
- case eKeyValueExpr: {
- GoASTKeyValueExpr *n = llvm::cast<GoASTKeyValueExpr>(this);
- (void)n;
- v(n->m_key_up.get());
- v(n->m_value_up.get());
- return;
- }
- case eLabeledStmt: {
- GoASTLabeledStmt *n = llvm::cast<GoASTLabeledStmt>(this);
- (void)n;
- v(n->m_label_up.get());
- v(n->m_stmt_up.get());
- return;
- }
- case eMapType: {
- GoASTMapType *n = llvm::cast<GoASTMapType>(this);
- (void)n;
- v(n->m_key_up.get());
- v(n->m_value_up.get());
- return;
- }
- case eParenExpr: {
- GoASTParenExpr *n = llvm::cast<GoASTParenExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- return;
- }
- case eRangeStmt: {
- GoASTRangeStmt *n = llvm::cast<GoASTRangeStmt>(this);
- (void)n;
- v(n->m_key_up.get());
- v(n->m_value_up.get());
- v(n->m_x_up.get());
- v(n->m_body_up.get());
- return;
- }
- case eReturnStmt: {
- GoASTReturnStmt *n = llvm::cast<GoASTReturnStmt>(this);
- (void)n;
- for (auto &e : n->m_results) {
- v(e.get());
- }
- return;
- }
- case eSelectStmt: {
- GoASTSelectStmt *n = llvm::cast<GoASTSelectStmt>(this);
- (void)n;
- v(n->m_body_up.get());
- return;
- }
- case eSelectorExpr: {
- GoASTSelectorExpr *n = llvm::cast<GoASTSelectorExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- v(n->m_sel_up.get());
- return;
- }
- case eSendStmt: {
- GoASTSendStmt *n = llvm::cast<GoASTSendStmt>(this);
- (void)n;
- v(n->m_chan_up.get());
- v(n->m_value_up.get());
- return;
- }
- case eSliceExpr: {
- GoASTSliceExpr *n = llvm::cast<GoASTSliceExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- v(n->m_low_up.get());
- v(n->m_high_up.get());
- v(n->m_max_up.get());
- return;
- }
- case eStarExpr: {
- GoASTStarExpr *n = llvm::cast<GoASTStarExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- return;
- }
- case eStructType: {
- GoASTStructType *n = llvm::cast<GoASTStructType>(this);
- (void)n;
- v(n->m_fields_up.get());
- return;
- }
- case eSwitchStmt: {
- GoASTSwitchStmt *n = llvm::cast<GoASTSwitchStmt>(this);
- (void)n;
- v(n->m_init_up.get());
- v(n->m_tag_up.get());
- v(n->m_body_up.get());
- return;
- }
- case eTypeAssertExpr: {
- GoASTTypeAssertExpr *n = llvm::cast<GoASTTypeAssertExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- v(n->m_type_up.get());
- return;
- }
- case eTypeSpec: {
- GoASTTypeSpec *n = llvm::cast<GoASTTypeSpec>(this);
- (void)n;
- v(n->m_name_up.get());
- v(n->m_type_up.get());
- return;
- }
- case eTypeSwitchStmt: {
- GoASTTypeSwitchStmt *n = llvm::cast<GoASTTypeSwitchStmt>(this);
- (void)n;
- v(n->m_init_up.get());
- v(n->m_assign_up.get());
- v(n->m_body_up.get());
- return;
- }
- case eUnaryExpr: {
- GoASTUnaryExpr *n = llvm::cast<GoASTUnaryExpr>(this);
- (void)n;
- v(n->m_x_up.get());
- return;
- }
- case eValueSpec: {
- GoASTValueSpec *n = llvm::cast<GoASTValueSpec>(this);
- (void)n;
- for (auto &e : n->m_names) {
- v(e.get());
- }
- v(n->m_type_up.get());
- for (auto &e : n->m_values) {
- v(e.get());
- }
- return;
- }
-
- case eEmptyStmt:
- case eBadDecl:
- case eBadExpr:
- case eBadStmt:
- break;
- }
-}
-
-} // namespace lldb_private
-
-#endif
diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.cpp b/source/Plugins/ExpressionParser/Go/GoLexer.cpp
deleted file mode 100644
index 63e267eaadc2..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoLexer.cpp
+++ /dev/null
@@ -1,350 +0,0 @@
-//===-- GoLexer.cpp ---------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <string.h>
-
-#include "GoLexer.h"
-
-using namespace lldb_private;
-
-llvm::StringMap<GoLexer::TokenType> *GoLexer::m_keywords;
-
-GoLexer::GoLexer(const char *src)
- : m_src(src), m_end(src + strlen(src)), m_last_token(TOK_INVALID, "") {}
-
-bool GoLexer::SkipWhitespace() {
- bool saw_newline = false;
- for (; m_src < m_end; ++m_src) {
- if (*m_src == '\n')
- saw_newline = true;
- if (*m_src == '/' && !SkipComment())
- return saw_newline;
- else if (!IsWhitespace(*m_src))
- return saw_newline;
- }
- return saw_newline;
-}
-
-bool GoLexer::SkipComment() {
- if (m_src[0] == '/' && m_src[1] == '/') {
- for (const char *c = m_src + 2; c < m_end; ++c) {
- if (*c == '\n') {
- m_src = c - 1;
- return true;
- }
- }
- return true;
- } else if (m_src[0] == '/' && m_src[1] == '*') {
- for (const char *c = m_src + 2; c < m_end; ++c) {
- if (c[0] == '*' && c[1] == '/') {
- m_src = c + 1;
- return true;
- }
- }
- }
- return false;
-}
-
-const GoLexer::Token &GoLexer::Lex() {
- bool newline = SkipWhitespace();
- const char *start = m_src;
- m_last_token.m_type = InternalLex(newline);
- m_last_token.m_value = llvm::StringRef(start, m_src - start);
- return m_last_token;
-}
-
-GoLexer::TokenType GoLexer::InternalLex(bool newline) {
- if (m_src >= m_end) {
- return TOK_EOF;
- }
- if (newline) {
- switch (m_last_token.m_type) {
- case TOK_IDENTIFIER:
- case LIT_FLOAT:
- case LIT_IMAGINARY:
- case LIT_INTEGER:
- case LIT_RUNE:
- case LIT_STRING:
- case KEYWORD_BREAK:
- case KEYWORD_CONTINUE:
- case KEYWORD_FALLTHROUGH:
- case KEYWORD_RETURN:
- case OP_PLUS_PLUS:
- case OP_MINUS_MINUS:
- case OP_RPAREN:
- case OP_RBRACK:
- case OP_RBRACE:
- return OP_SEMICOLON;
- default:
- break;
- }
- }
- char c = *m_src;
- switch (c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- return DoNumber();
- case '+':
- case '-':
- case '*':
- case '/':
- case '%':
- case '&':
- case '|':
- case '^':
- case '<':
- case '>':
- case '!':
- case ':':
- case ';':
- case '(':
- case ')':
- case '[':
- case ']':
- case '{':
- case '}':
- case ',':
- case '=':
- return DoOperator();
- case '.':
- if (IsDecimal(m_src[1]))
- return DoNumber();
- return DoOperator();
- case '$':
- // For lldb persistent vars.
- return DoIdent();
- case '"':
- case '`':
- return DoString();
- case '\'':
- return DoRune();
- default:
- break;
- }
- if (IsLetterOrDigit(c))
- return DoIdent();
- ++m_src;
- return TOK_INVALID;
-}
-
-GoLexer::TokenType GoLexer::DoOperator() {
- TokenType t = TOK_INVALID;
- if (m_end - m_src > 2) {
- t = LookupKeyword(llvm::StringRef(m_src, 3));
- if (t != TOK_INVALID)
- m_src += 3;
- }
- if (t == TOK_INVALID && m_end - m_src > 1) {
- t = LookupKeyword(llvm::StringRef(m_src, 2));
- if (t != TOK_INVALID)
- m_src += 2;
- }
- if (t == TOK_INVALID) {
- t = LookupKeyword(llvm::StringRef(m_src, 1));
- ++m_src;
- }
- return t;
-}
-
-GoLexer::TokenType GoLexer::DoIdent() {
- const char *start = m_src++;
- while (m_src < m_end && IsLetterOrDigit(*m_src)) {
- ++m_src;
- }
- TokenType kw = LookupKeyword(llvm::StringRef(start, m_src - start));
- if (kw != TOK_INVALID)
- return kw;
- return TOK_IDENTIFIER;
-}
-
-GoLexer::TokenType GoLexer::DoNumber() {
- if (m_src[0] == '0' && (m_src[1] == 'x' || m_src[1] == 'X')) {
- m_src += 2;
- while (IsHexChar(*m_src))
- ++m_src;
- return LIT_INTEGER;
- }
- bool dot_ok = true;
- bool e_ok = true;
- while (true) {
- while (IsDecimal(*m_src))
- ++m_src;
- switch (*m_src) {
- case 'i':
- ++m_src;
- return LIT_IMAGINARY;
- case '.':
- if (!dot_ok)
- return LIT_FLOAT;
- ++m_src;
- dot_ok = false;
- break;
- case 'e':
- case 'E':
- if (!e_ok)
- return LIT_FLOAT;
- dot_ok = e_ok = false;
- ++m_src;
- if (*m_src == '+' || *m_src == '-')
- ++m_src;
- break;
- default:
- if (dot_ok)
- return LIT_INTEGER;
- return LIT_FLOAT;
- }
- }
-}
-
-GoLexer::TokenType GoLexer::DoRune() {
- while (++m_src < m_end) {
- switch (*m_src) {
- case '\'':
- ++m_src;
- return LIT_RUNE;
- case '\n':
- return TOK_INVALID;
- case '\\':
- if (m_src[1] == '\n')
- return TOK_INVALID;
- ++m_src;
- }
- }
- return TOK_INVALID;
-}
-
-GoLexer::TokenType GoLexer::DoString() {
- if (*m_src == '`') {
- while (++m_src < m_end) {
- if (*m_src == '`') {
- ++m_src;
- return LIT_STRING;
- }
- }
- return TOK_INVALID;
- }
- while (++m_src < m_end) {
- switch (*m_src) {
- case '"':
- ++m_src;
- return LIT_STRING;
- case '\n':
- return TOK_INVALID;
- case '\\':
- if (m_src[1] == '\n')
- return TOK_INVALID;
- ++m_src;
- }
- }
- return TOK_INVALID;
-}
-
-GoLexer::TokenType GoLexer::LookupKeyword(llvm::StringRef id) {
- if (m_keywords == nullptr)
- m_keywords = InitKeywords();
- const auto &it = m_keywords->find(id);
- if (it == m_keywords->end())
- return TOK_INVALID;
- return it->second;
-}
-
-llvm::StringRef GoLexer::LookupToken(TokenType t) {
- if (m_keywords == nullptr)
- m_keywords = InitKeywords();
- for (const auto &e : *m_keywords) {
- if (e.getValue() == t)
- return e.getKey();
- }
- return "";
-}
-
-llvm::StringMap<GoLexer::TokenType> *GoLexer::InitKeywords() {
- auto &result = *new llvm::StringMap<TokenType>(128);
- result["break"] = KEYWORD_BREAK;
- result["default"] = KEYWORD_DEFAULT;
- result["func"] = KEYWORD_FUNC;
- result["interface"] = KEYWORD_INTERFACE;
- result["select"] = KEYWORD_SELECT;
- result["case"] = KEYWORD_CASE;
- result["defer"] = KEYWORD_DEFER;
- result["go"] = KEYWORD_GO;
- result["map"] = KEYWORD_MAP;
- result["struct"] = KEYWORD_STRUCT;
- result["chan"] = KEYWORD_CHAN;
- result["else"] = KEYWORD_ELSE;
- result["goto"] = KEYWORD_GOTO;
- result["package"] = KEYWORD_PACKAGE;
- result["switch"] = KEYWORD_SWITCH;
- result["const"] = KEYWORD_CONST;
- result["fallthrough"] = KEYWORD_FALLTHROUGH;
- result["if"] = KEYWORD_IF;
- result["range"] = KEYWORD_RANGE;
- result["type"] = KEYWORD_TYPE;
- result["continue"] = KEYWORD_CONTINUE;
- result["for"] = KEYWORD_FOR;
- result["import"] = KEYWORD_IMPORT;
- result["return"] = KEYWORD_RETURN;
- result["var"] = KEYWORD_VAR;
- result["+"] = OP_PLUS;
- result["-"] = OP_MINUS;
- result["*"] = OP_STAR;
- result["/"] = OP_SLASH;
- result["%"] = OP_PERCENT;
- result["&"] = OP_AMP;
- result["|"] = OP_PIPE;
- result["^"] = OP_CARET;
- result["<<"] = OP_LSHIFT;
- result[">>"] = OP_RSHIFT;
- result["&^"] = OP_AMP_CARET;
- result["+="] = OP_PLUS_EQ;
- result["-="] = OP_MINUS_EQ;
- result["*="] = OP_STAR_EQ;
- result["/="] = OP_SLASH_EQ;
- result["%="] = OP_PERCENT_EQ;
- result["&="] = OP_AMP_EQ;
- result["|="] = OP_PIPE_EQ;
- result["^="] = OP_CARET_EQ;
- result["<<="] = OP_LSHIFT_EQ;
- result[">>="] = OP_RSHIFT_EQ;
- result["&^="] = OP_AMP_CARET_EQ;
- result["&&"] = OP_AMP_AMP;
- result["||"] = OP_PIPE_PIPE;
- result["<-"] = OP_LT_MINUS;
- result["++"] = OP_PLUS_PLUS;
- result["--"] = OP_MINUS_MINUS;
- result["=="] = OP_EQ_EQ;
- result["<"] = OP_LT;
- result[">"] = OP_GT;
- result["="] = OP_EQ;
- result["!"] = OP_BANG;
- result["!="] = OP_BANG_EQ;
- result["<="] = OP_LT_EQ;
- result[">="] = OP_GT_EQ;
- result[":="] = OP_COLON_EQ;
- result["..."] = OP_DOTS;
- result["("] = OP_LPAREN;
- result["["] = OP_LBRACK;
- result["{"] = OP_LBRACE;
- result[","] = OP_COMMA;
- result["."] = OP_DOT;
- result[")"] = OP_RPAREN;
- result["]"] = OP_RBRACK;
- result["}"] = OP_RBRACE;
- result[";"] = OP_SEMICOLON;
- result[":"] = OP_COLON;
- return &result;
-}
diff --git a/source/Plugins/ExpressionParser/Go/GoLexer.h b/source/Plugins/ExpressionParser/Go/GoLexer.h
deleted file mode 100644
index f0b5b336fbe9..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoLexer.h
+++ /dev/null
@@ -1,181 +0,0 @@
-//===-- GoLexer.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_GoLexer_h
-#define liblldb_GoLexer_h
-
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace lldb_private {
-
-class GoLexer {
-public:
- explicit GoLexer(const char *src);
-
- enum TokenType {
- TOK_EOF,
- TOK_INVALID,
- TOK_IDENTIFIER,
- LIT_INTEGER,
- LIT_FLOAT,
- LIT_IMAGINARY,
- LIT_RUNE,
- LIT_STRING,
- KEYWORD_BREAK,
- KEYWORD_DEFAULT,
- KEYWORD_FUNC,
- KEYWORD_INTERFACE,
- KEYWORD_SELECT,
- KEYWORD_CASE,
- KEYWORD_DEFER,
- KEYWORD_GO,
- KEYWORD_MAP,
- KEYWORD_STRUCT,
- KEYWORD_CHAN,
- KEYWORD_ELSE,
- KEYWORD_GOTO,
- KEYWORD_PACKAGE,
- KEYWORD_SWITCH,
- KEYWORD_CONST,
- KEYWORD_FALLTHROUGH,
- KEYWORD_IF,
- KEYWORD_RANGE,
- KEYWORD_TYPE,
- KEYWORD_CONTINUE,
- KEYWORD_FOR,
- KEYWORD_IMPORT,
- KEYWORD_RETURN,
- KEYWORD_VAR,
- OP_PLUS,
- OP_MINUS,
- OP_STAR,
- OP_SLASH,
- OP_PERCENT,
- OP_AMP,
- OP_PIPE,
- OP_CARET,
- OP_LSHIFT,
- OP_RSHIFT,
- OP_AMP_CARET,
- OP_PLUS_EQ,
- OP_MINUS_EQ,
- OP_STAR_EQ,
- OP_SLASH_EQ,
- OP_PERCENT_EQ,
- OP_AMP_EQ,
- OP_PIPE_EQ,
- OP_CARET_EQ,
- OP_LSHIFT_EQ,
- OP_RSHIFT_EQ,
- OP_AMP_CARET_EQ,
- OP_AMP_AMP,
- OP_PIPE_PIPE,
- OP_LT_MINUS,
- OP_PLUS_PLUS,
- OP_MINUS_MINUS,
- OP_EQ_EQ,
- OP_LT,
- OP_GT,
- OP_EQ,
- OP_BANG,
- OP_BANG_EQ,
- OP_LT_EQ,
- OP_GT_EQ,
- OP_COLON_EQ,
- OP_DOTS,
- OP_LPAREN,
- OP_LBRACK,
- OP_LBRACE,
- OP_COMMA,
- OP_DOT,
- OP_RPAREN,
- OP_RBRACK,
- OP_RBRACE,
- OP_SEMICOLON,
- OP_COLON,
- };
-
- struct Token {
- explicit Token(TokenType t, llvm::StringRef text)
- : m_type(t), m_value(text) {}
- TokenType m_type;
- llvm::StringRef m_value;
- };
-
- const Token &Lex();
-
- size_t BytesRemaining() const { return m_end - m_src; }
- llvm::StringRef GetString(int len) const {
- return llvm::StringRef(m_src, len);
- }
-
- static TokenType LookupKeyword(llvm::StringRef id);
- static llvm::StringRef LookupToken(TokenType t);
-
-private:
- bool IsDecimal(char c) { return c >= '0' && c <= '9'; }
- bool IsHexChar(char c) {
- if (c >= '0' && c <= '9')
- return true;
- if (c >= 'A' && c <= 'F')
- return true;
- if (c >= 'a' && c <= 'f')
- return true;
- return false;
- }
- bool IsLetterOrDigit(char c) {
- if (c >= 'a' && c <= 'z')
- return true;
- if (c >= 'A' && c <= 'Z')
- return true;
- if (c == '_')
- return true;
- if (c >= '0' && c <= '9')
- return true;
- // Treat all non-ascii chars as letters for simplicity.
- return 0 != (c & 0x80);
- }
- bool IsWhitespace(char c) {
- switch (c) {
- case ' ':
- case '\t':
- case '\r':
- return true;
- }
- return false;
- }
-
- bool SkipWhitespace();
- bool SkipComment();
-
- TokenType InternalLex(bool newline);
-
- TokenType DoOperator();
-
- TokenType DoIdent();
-
- TokenType DoNumber();
-
- TokenType DoRune();
-
- TokenType DoString();
-
- static llvm::StringMap<TokenType> *InitKeywords();
-
- static llvm::StringMap<TokenType> *m_keywords;
-
- const char *m_src;
- const char *m_end;
- Token m_last_token;
-};
-
-} // namespace lldb_private
-
-#endif
diff --git a/source/Plugins/ExpressionParser/Go/GoParser.cpp b/source/Plugins/ExpressionParser/Go/GoParser.cpp
deleted file mode 100644
index 9c845d02bca0..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoParser.cpp
+++ /dev/null
@@ -1,886 +0,0 @@
-//===-- GoParser.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 "GoParser.h"
-
-#include "Plugins/ExpressionParser/Go/GoAST.h"
-#include "lldb/Utility/Status.h"
-#include "llvm/ADT/SmallString.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-namespace {
-llvm::StringRef DescribeToken(GoLexer::TokenType t) {
- switch (t) {
- case GoLexer::TOK_EOF:
- return "<eof>";
- case GoLexer::TOK_IDENTIFIER:
- return "identifier";
- case GoLexer::LIT_FLOAT:
- return "float";
- case GoLexer::LIT_IMAGINARY:
- return "imaginary";
- case GoLexer::LIT_INTEGER:
- return "integer";
- case GoLexer::LIT_RUNE:
- return "rune";
- case GoLexer::LIT_STRING:
- return "string";
- default:
- return GoLexer::LookupToken(t);
- }
-}
-} // namespace
-
-class GoParser::Rule {
-public:
- Rule(llvm::StringRef name, GoParser *p)
- : m_name(name), m_parser(p), m_pos(p->m_pos) {}
-
- std::nullptr_t error() {
- if (!m_parser->m_failed) {
- // Set m_error in case this is the top level.
- if (m_parser->m_last_tok == GoLexer::TOK_INVALID)
- m_parser->m_error = m_parser->m_last;
- else
- m_parser->m_error = DescribeToken(m_parser->m_last_tok);
- // And set m_last in case it isn't.
- m_parser->m_last = m_name;
- m_parser->m_last_tok = GoLexer::TOK_INVALID;
- m_parser->m_pos = m_pos;
- }
- return nullptr;
- }
-
-private:
- llvm::StringRef m_name;
- GoParser *m_parser;
- size_t m_pos;
-};
-
-GoParser::GoParser(const char *src)
- : m_lexer(src), m_pos(0), m_last_tok(GoLexer::TOK_INVALID),
- m_failed(false) {}
-
-GoASTStmt *GoParser::Statement() {
- Rule r("Statement", this);
- GoLexer::TokenType t = peek();
- GoASTStmt *ret = nullptr;
- switch (t) {
- case GoLexer::TOK_EOF:
- case GoLexer::OP_SEMICOLON:
- case GoLexer::OP_RPAREN:
- case GoLexer::OP_RBRACE:
- case GoLexer::TOK_INVALID:
- return EmptyStmt();
- case GoLexer::OP_LBRACE:
- return Block();
-
- /* TODO:
-case GoLexer::KEYWORD_GO:
- return GoStmt();
-case GoLexer::KEYWORD_RETURN:
- return ReturnStmt();
-case GoLexer::KEYWORD_BREAK:
-case GoLexer::KEYWORD_CONTINUE:
-case GoLexer::KEYWORD_GOTO:
-case GoLexer::KEYWORD_FALLTHROUGH:
- return BranchStmt();
-case GoLexer::KEYWORD_IF:
- return IfStmt();
-case GoLexer::KEYWORD_SWITCH:
- return SwitchStmt();
-case GoLexer::KEYWORD_SELECT:
- return SelectStmt();
-case GoLexer::KEYWORD_FOR:
- return ForStmt();
-case GoLexer::KEYWORD_DEFER:
- return DeferStmt();
-case GoLexer::KEYWORD_CONST:
-case GoLexer::KEYWORD_TYPE:
-case GoLexer::KEYWORD_VAR:
- return DeclStmt();
-case GoLexer::TOK_IDENTIFIER:
- if ((ret = LabeledStmt()) ||
- (ret = ShortVarDecl()))
- {
- return ret;
- }
-*/
- default:
- break;
- }
- GoASTExpr *expr = Expression();
- if (expr == nullptr)
- return r.error();
- if (/*(ret = SendStmt(expr)) ||*/
- (ret = IncDecStmt(expr)) || (ret = Assignment(expr)) ||
- (ret = ExpressionStmt(expr))) {
- return ret;
- }
- delete expr;
- return r.error();
-}
-
-GoASTStmt *GoParser::ExpressionStmt(GoASTExpr *e) {
- if (Semicolon())
- return new GoASTExprStmt(e);
- return nullptr;
-}
-
-GoASTStmt *GoParser::IncDecStmt(GoASTExpr *e) {
- Rule r("IncDecStmt", this);
- if (match(GoLexer::OP_PLUS_PLUS))
- return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_PLUS_PLUS)
- : r.error();
- if (match(GoLexer::OP_MINUS_MINUS))
- return Semicolon() ? new GoASTIncDecStmt(e, GoLexer::OP_MINUS_MINUS)
- : r.error();
- return nullptr;
-}
-
-GoASTStmt *GoParser::Assignment(lldb_private::GoASTExpr *e) {
- Rule r("Assignment", this);
- std::vector<std::unique_ptr<GoASTExpr>> lhs;
- for (GoASTExpr *l = MoreExpressionList(); l; l = MoreExpressionList())
- lhs.push_back(std::unique_ptr<GoASTExpr>(l));
- switch (peek()) {
- case GoLexer::OP_EQ:
- case GoLexer::OP_PLUS_EQ:
- case GoLexer::OP_MINUS_EQ:
- case GoLexer::OP_PIPE_EQ:
- case GoLexer::OP_CARET_EQ:
- case GoLexer::OP_STAR_EQ:
- case GoLexer::OP_SLASH_EQ:
- case GoLexer::OP_PERCENT_EQ:
- case GoLexer::OP_LSHIFT_EQ:
- case GoLexer::OP_RSHIFT_EQ:
- case GoLexer::OP_AMP_EQ:
- case GoLexer::OP_AMP_CARET_EQ:
- break;
- default:
- return r.error();
- }
- // We don't want to own e until we know this is an assignment.
- std::unique_ptr<GoASTAssignStmt> stmt(new GoASTAssignStmt(false));
- stmt->AddLhs(e);
- for (auto &l : lhs)
- stmt->AddLhs(l.release());
- for (GoASTExpr *r = Expression(); r; r = MoreExpressionList())
- stmt->AddRhs(r);
- if (!Semicolon() || stmt->NumRhs() == 0)
- return new GoASTBadStmt;
- return stmt.release();
-}
-
-GoASTStmt *GoParser::EmptyStmt() {
- if (match(GoLexer::TOK_EOF))
- return nullptr;
- if (Semicolon())
- return new GoASTEmptyStmt;
- return nullptr;
-}
-
-GoASTStmt *GoParser::GoStmt() {
- if (match(GoLexer::KEYWORD_GO)) {
- if (GoASTCallExpr *e =
- llvm::dyn_cast_or_null<GoASTCallExpr>(Expression())) {
- return FinishStmt(new GoASTGoStmt(e));
- }
- m_last = "call expression";
- m_failed = true;
- return new GoASTBadStmt();
- }
- return nullptr;
-}
-
-GoASTStmt *GoParser::ReturnStmt() {
- if (match(GoLexer::KEYWORD_RETURN)) {
- std::unique_ptr<GoASTReturnStmt> r(new GoASTReturnStmt());
- for (GoASTExpr *e = Expression(); e; e = MoreExpressionList())
- r->AddResults(e);
- return FinishStmt(r.release());
- }
- return nullptr;
-}
-
-GoASTStmt *GoParser::BranchStmt() {
- GoLexer::Token *tok;
- if ((tok = match(GoLexer::KEYWORD_BREAK)) ||
- (tok = match(GoLexer::KEYWORD_CONTINUE)) ||
- (tok = match(GoLexer::KEYWORD_GOTO))) {
- auto *e = Identifier();
- if (tok->m_type == GoLexer::KEYWORD_GOTO && !e)
- return syntaxerror();
- return FinishStmt(new GoASTBranchStmt(e, tok->m_type));
- }
- if ((tok = match(GoLexer::KEYWORD_FALLTHROUGH)))
- return FinishStmt(new GoASTBranchStmt(nullptr, tok->m_type));
-
- return nullptr;
-}
-
-GoASTIdent *GoParser::Identifier() {
- if (auto *tok = match(GoLexer::TOK_IDENTIFIER))
- return new GoASTIdent(*tok);
- return nullptr;
-}
-
-GoASTExpr *GoParser::MoreExpressionList() {
- if (match(GoLexer::OP_COMMA)) {
- auto *e = Expression();
- if (!e)
- return syntaxerror();
- return e;
- }
- return nullptr;
-}
-
-GoASTIdent *GoParser::MoreIdentifierList() {
- if (match(GoLexer::OP_COMMA)) {
- auto *i = Identifier();
- if (!i)
- return syntaxerror();
- return i;
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::Expression() {
- Rule r("Expression", this);
- if (GoASTExpr *ret = OrExpr())
- return ret;
- return r.error();
-}
-
-GoASTExpr *GoParser::UnaryExpr() {
- switch (peek()) {
- case GoLexer::OP_PLUS:
- case GoLexer::OP_MINUS:
- case GoLexer::OP_BANG:
- case GoLexer::OP_CARET:
- case GoLexer::OP_STAR:
- case GoLexer::OP_AMP:
- case GoLexer::OP_LT_MINUS: {
- const GoLexer::Token t = next();
- if (GoASTExpr *e = UnaryExpr()) {
- if (t.m_type == GoLexer::OP_STAR)
- return new GoASTStarExpr(e);
- else
- return new GoASTUnaryExpr(t.m_type, e);
- }
- return syntaxerror();
- }
- default:
- return PrimaryExpr();
- }
-}
-
-GoASTExpr *GoParser::OrExpr() {
- std::unique_ptr<GoASTExpr> l(AndExpr());
- if (l) {
- while (match(GoLexer::OP_PIPE_PIPE)) {
- GoASTExpr *r = AndExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_PIPE_PIPE));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::AndExpr() {
- std::unique_ptr<GoASTExpr> l(RelExpr());
- if (l) {
- while (match(GoLexer::OP_AMP_AMP)) {
- GoASTExpr *r = RelExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, GoLexer::OP_AMP_AMP));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::RelExpr() {
- std::unique_ptr<GoASTExpr> l(AddExpr());
- if (l) {
- for (GoLexer::Token *t;
- (t = match(GoLexer::OP_EQ_EQ)) || (t = match(GoLexer::OP_BANG_EQ)) ||
- (t = match(GoLexer::OP_LT)) || (t = match(GoLexer::OP_LT_EQ)) ||
- (t = match(GoLexer::OP_GT)) || (t = match(GoLexer::OP_GT_EQ));) {
- GoLexer::TokenType op = t->m_type;
- GoASTExpr *r = AddExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, op));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::AddExpr() {
- std::unique_ptr<GoASTExpr> l(MulExpr());
- if (l) {
- for (GoLexer::Token *t;
- (t = match(GoLexer::OP_PLUS)) || (t = match(GoLexer::OP_MINUS)) ||
- (t = match(GoLexer::OP_PIPE)) || (t = match(GoLexer::OP_CARET));) {
- GoLexer::TokenType op = t->m_type;
- GoASTExpr *r = MulExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, op));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::MulExpr() {
- std::unique_ptr<GoASTExpr> l(UnaryExpr());
- if (l) {
- for (GoLexer::Token *t;
- (t = match(GoLexer::OP_STAR)) || (t = match(GoLexer::OP_SLASH)) ||
- (t = match(GoLexer::OP_PERCENT)) || (t = match(GoLexer::OP_LSHIFT)) ||
- (t = match(GoLexer::OP_RSHIFT)) || (t = match(GoLexer::OP_AMP)) ||
- (t = match(GoLexer::OP_AMP_CARET));) {
- GoLexer::TokenType op = t->m_type;
- GoASTExpr *r = UnaryExpr();
- if (r)
- l.reset(new GoASTBinaryExpr(l.release(), r, op));
- else
- return syntaxerror();
- }
- return l.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::PrimaryExpr() {
- GoASTExpr *l;
- GoASTExpr *r;
- (l = Conversion()) || (l = Operand());
- if (!l)
- return nullptr;
- while ((r = Selector(l)) || (r = IndexOrSlice(l)) || (r = TypeAssertion(l)) ||
- (r = Arguments(l))) {
- l = r;
- }
- return l;
-}
-
-GoASTExpr *GoParser::Operand() {
- GoLexer::Token *lit;
- if ((lit = match(GoLexer::LIT_INTEGER)) ||
- (lit = match(GoLexer::LIT_FLOAT)) ||
- (lit = match(GoLexer::LIT_IMAGINARY)) ||
- (lit = match(GoLexer::LIT_RUNE)) || (lit = match(GoLexer::LIT_STRING)))
- return new GoASTBasicLit(*lit);
- if (match(GoLexer::OP_LPAREN)) {
- GoASTExpr *e;
- if (!((e = Expression()) && match(GoLexer::OP_RPAREN)))
- return syntaxerror();
- return e;
- }
- // MethodExpr should be handled by Selector
- if (GoASTExpr *e = CompositeLit())
- return e;
- if (GoASTExpr *n = Name())
- return n;
- return FunctionLit();
-}
-
-GoASTExpr *GoParser::FunctionLit() {
- if (!match(GoLexer::KEYWORD_FUNC))
- return nullptr;
- auto *sig = Signature();
- if (!sig)
- return syntaxerror();
- auto *body = Block();
- if (!body) {
- delete sig;
- return syntaxerror();
- }
- return new GoASTFuncLit(sig, body);
-}
-
-GoASTBlockStmt *GoParser::Block() {
- if (!match(GoLexer::OP_LBRACE))
- return nullptr;
- std::unique_ptr<GoASTBlockStmt> block(new GoASTBlockStmt);
- for (auto *s = Statement(); s; s = Statement())
- block->AddList(s);
- if (!match(GoLexer::OP_RBRACE))
- return syntaxerror();
- return block.release();
-}
-
-GoASTExpr *GoParser::CompositeLit() {
- Rule r("CompositeLit", this);
- GoASTExpr *type;
- (type = StructType()) || (type = ArrayOrSliceType(true)) ||
- (type = MapType()) || (type = Name());
- if (!type)
- return r.error();
- GoASTCompositeLit *lit = LiteralValue();
- if (!lit) {
- delete type;
- return r.error();
- }
- lit->SetType(type);
- return lit;
-}
-
-GoASTCompositeLit *GoParser::LiteralValue() {
- if (!match(GoLexer::OP_LBRACE))
- return nullptr;
- std::unique_ptr<GoASTCompositeLit> lit(new GoASTCompositeLit);
- for (GoASTExpr *e = Element(); e; e = Element()) {
- lit->AddElts(e);
- if (!match(GoLexer::OP_COMMA))
- break;
- }
- if (!mustMatch(GoLexer::OP_RBRACE))
- return nullptr;
- return lit.release();
-}
-
-GoASTExpr *GoParser::Element() {
- GoASTExpr *key;
- if (!((key = Expression()) || (key = LiteralValue())))
- return nullptr;
- if (!match(GoLexer::OP_COLON))
- return key;
- GoASTExpr *value;
- if ((value = Expression()) || (value = LiteralValue()))
- return new GoASTKeyValueExpr(key, value);
- delete key;
- return syntaxerror();
-}
-
-GoASTExpr *GoParser::Selector(GoASTExpr *e) {
- Rule r("Selector", this);
- if (match(GoLexer::OP_DOT)) {
- if (auto *name = Identifier())
- return new GoASTSelectorExpr(e, name);
- }
- return r.error();
-}
-
-GoASTExpr *GoParser::IndexOrSlice(GoASTExpr *e) {
- Rule r("IndexOrSlice", this);
- if (match(GoLexer::OP_LBRACK)) {
- std::unique_ptr<GoASTExpr> i1(Expression()), i2, i3;
- bool slice = false;
- if (match(GoLexer::OP_COLON)) {
- slice = true;
- i2.reset(Expression());
- if (i2 && match(GoLexer::OP_COLON)) {
- i3.reset(Expression());
- if (!i3)
- return syntaxerror();
- }
- }
- if (!(slice || i1))
- return syntaxerror();
- if (!mustMatch(GoLexer::OP_RBRACK))
- return nullptr;
- if (slice) {
- bool slice3 = i3.get();
- return new GoASTSliceExpr(e, i1.release(), i2.release(), i3.release(),
- slice3);
- }
- return new GoASTIndexExpr(e, i1.release());
- }
- return r.error();
-}
-
-GoASTExpr *GoParser::TypeAssertion(GoASTExpr *e) {
- Rule r("TypeAssertion", this);
- if (match(GoLexer::OP_DOT) && match(GoLexer::OP_LPAREN)) {
- if (auto *t = Type()) {
- if (!mustMatch(GoLexer::OP_RPAREN))
- return nullptr;
- return new GoASTTypeAssertExpr(e, t);
- }
- return syntaxerror();
- }
- return r.error();
-}
-
-GoASTExpr *GoParser::Arguments(GoASTExpr *e) {
- if (match(GoLexer::OP_LPAREN)) {
- std::unique_ptr<GoASTCallExpr> call(new GoASTCallExpr(false));
- GoASTExpr *arg;
- // ( ExpressionList | Type [ "," ExpressionList ] )
- for ((arg = Expression()) || (arg = Type()); arg;
- arg = MoreExpressionList()) {
- call->AddArgs(arg);
- }
- if (match(GoLexer::OP_DOTS))
- call->SetEllipsis(true);
-
- // Eat trailing comma
- match(GoLexer::OP_COMMA);
-
- if (!mustMatch(GoLexer::OP_RPAREN))
- return nullptr;
- call->SetFun(e);
- return call.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::Conversion() {
- Rule r("Conversion", this);
- if (GoASTExpr *t = Type2()) {
- std::unique_ptr<GoASTExpr> owner(t);
- if (match(GoLexer::OP_LPAREN)) {
- GoASTExpr *v = Expression();
- if (!v)
- return syntaxerror();
- match(GoLexer::OP_COMMA);
- if (!mustMatch(GoLexer::OP_RPAREN))
- return r.error();
- GoASTCallExpr *call = new GoASTCallExpr(false);
- call->SetFun(t);
- owner.release();
- call->AddArgs(v);
- return call;
- }
- }
- return r.error();
-}
-
-GoASTExpr *GoParser::Type2() {
- switch (peek()) {
- case GoLexer::OP_LBRACK:
- return ArrayOrSliceType(false);
- case GoLexer::KEYWORD_STRUCT:
- return StructType();
- case GoLexer::KEYWORD_FUNC:
- return FunctionType();
- case GoLexer::KEYWORD_INTERFACE:
- return InterfaceType();
- case GoLexer::KEYWORD_MAP:
- return MapType();
- case GoLexer::KEYWORD_CHAN:
- return ChanType2();
- default:
- return nullptr;
- }
-}
-
-GoASTExpr *GoParser::ArrayOrSliceType(bool allowEllipsis) {
- Rule r("ArrayType", this);
- if (match(GoLexer::OP_LBRACK)) {
- std::unique_ptr<GoASTExpr> len;
- if (allowEllipsis && match(GoLexer::OP_DOTS)) {
- len.reset(new GoASTEllipsis(nullptr));
- } else {
- len.reset(Expression());
- }
-
- if (!match(GoLexer::OP_RBRACK))
- return r.error();
- GoASTExpr *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTArrayType(len.release(), elem);
- }
- return r.error();
-}
-
-GoASTExpr *GoParser::StructType() {
- if (!(match(GoLexer::KEYWORD_STRUCT) && mustMatch(GoLexer::OP_LBRACE)))
- return nullptr;
- std::unique_ptr<GoASTFieldList> fields(new GoASTFieldList);
- while (auto *field = FieldDecl())
- fields->AddList(field);
- if (!mustMatch(GoLexer::OP_RBRACE))
- return nullptr;
- return new GoASTStructType(fields.release());
-}
-
-GoASTField *GoParser::FieldDecl() {
- std::unique_ptr<GoASTField> f(new GoASTField);
- GoASTExpr *t = FieldNamesAndType(f.get());
- if (!t)
- t = AnonymousFieldType();
- if (!t)
- return nullptr;
-
- if (auto *tok = match(GoLexer::LIT_STRING))
- f->SetTag(new GoASTBasicLit(*tok));
- if (!Semicolon())
- return syntaxerror();
- return f.release();
-}
-
-GoASTExpr *GoParser::FieldNamesAndType(GoASTField *field) {
- Rule r("FieldNames", this);
- for (auto *id = Identifier(); id; id = MoreIdentifierList())
- field->AddNames(id);
- if (m_failed)
- return nullptr;
- GoASTExpr *t = Type();
- if (t)
- return t;
- return r.error();
-}
-
-GoASTExpr *GoParser::AnonymousFieldType() {
- bool pointer = match(GoLexer::OP_STAR);
- GoASTExpr *t = Type();
- if (!t)
- return nullptr;
- if (pointer)
- return new GoASTStarExpr(t);
- return t;
-}
-
-GoASTExpr *GoParser::FunctionType() {
- if (!match(GoLexer::KEYWORD_FUNC))
- return nullptr;
- return Signature();
-}
-
-GoASTFuncType *GoParser::Signature() {
- auto *params = Params();
- if (!params)
- return syntaxerror();
- auto *result = Params();
- if (!result) {
- if (auto *t = Type()) {
- result = new GoASTFieldList;
- auto *f = new GoASTField;
- f->SetType(t);
- result->AddList(f);
- }
- }
- return new GoASTFuncType(params, result);
-}
-
-GoASTFieldList *GoParser::Params() {
- if (!match(GoLexer::OP_LPAREN))
- return nullptr;
- std::unique_ptr<GoASTFieldList> l(new GoASTFieldList);
- while (GoASTField *p = ParamDecl()) {
- l->AddList(p);
- if (!match(GoLexer::OP_COMMA))
- break;
- }
- if (!mustMatch(GoLexer::OP_RPAREN))
- return nullptr;
- return l.release();
-}
-
-GoASTField *GoParser::ParamDecl() {
- std::unique_ptr<GoASTField> field(new GoASTField);
- GoASTIdent *id = Identifier();
- if (id) {
- // Try `IdentifierList [ "..." ] Type`.
- // If that fails, backtrack and try `[ "..." ] Type`.
- Rule r("NamedParam", this);
- for (; id; id = MoreIdentifierList())
- field->AddNames(id);
- GoASTExpr *t = ParamType();
- if (t) {
- field->SetType(t);
- return field.release();
- }
- field.reset(new GoASTField);
- r.error();
- }
- GoASTExpr *t = ParamType();
- if (t) {
- field->SetType(t);
- return field.release();
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::ParamType() {
- bool dots = match(GoLexer::OP_DOTS);
- GoASTExpr *t = Type();
- if (!dots)
- return t;
- if (!t)
- return syntaxerror();
- return new GoASTEllipsis(t);
-}
-
-GoASTExpr *GoParser::InterfaceType() {
- if (!match(GoLexer::KEYWORD_INTERFACE) || !mustMatch(GoLexer::OP_LBRACE))
- return nullptr;
- std::unique_ptr<GoASTFieldList> methods(new GoASTFieldList);
- while (true) {
- Rule r("MethodSpec", this);
- // ( identifier Signature | TypeName ) ;
- std::unique_ptr<GoASTIdent> id(Identifier());
- if (!id)
- break;
- GoASTExpr *type = Signature();
- if (!type) {
- r.error();
- id.reset();
- type = Name();
- }
- if (!Semicolon())
- return syntaxerror();
- auto *f = new GoASTField;
- if (id)
- f->AddNames(id.release());
- f->SetType(type);
- methods->AddList(f);
- }
- if (!mustMatch(GoLexer::OP_RBRACE))
- return nullptr;
- return new GoASTInterfaceType(methods.release());
-}
-
-GoASTExpr *GoParser::MapType() {
- if (!(match(GoLexer::KEYWORD_MAP) && mustMatch(GoLexer::OP_LBRACK)))
- return nullptr;
- std::unique_ptr<GoASTExpr> key(Type());
- if (!key)
- return syntaxerror();
- if (!mustMatch(GoLexer::OP_RBRACK))
- return nullptr;
- auto *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTMapType(key.release(), elem);
-}
-
-GoASTExpr *GoParser::ChanType() {
- Rule r("chan", this);
- if (match(GoLexer::OP_LT_MINUS)) {
- if (match(GoLexer::KEYWORD_CHAN)) {
- auto *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTChanType(GoASTNode::eChanRecv, elem);
- }
- return r.error();
- }
- return ChanType2();
-}
-
-GoASTExpr *GoParser::ChanType2() {
- if (!match(GoLexer::KEYWORD_CHAN))
- return nullptr;
- auto dir = GoASTNode::eChanBidir;
- if (match(GoLexer::OP_LT_MINUS))
- dir = GoASTNode::eChanSend;
- auto *elem = Type();
- if (!elem)
- return syntaxerror();
- return new GoASTChanType(dir, elem);
-}
-
-GoASTExpr *GoParser::Type() {
- if (GoASTExpr *t = Type2())
- return t;
- if (GoASTExpr *t = Name())
- return t;
- if (GoASTExpr *t = ChanType())
- return t;
- if (match(GoLexer::OP_STAR)) {
- GoASTExpr *t = Type();
- if (!t)
- return syntaxerror();
- return new GoASTStarExpr(t);
- }
- if (match(GoLexer::OP_LPAREN)) {
- std::unique_ptr<GoASTExpr> t(Type());
- if (!t || !match(GoLexer::OP_RPAREN))
- return syntaxerror();
- return t.release();
- }
- return nullptr;
-}
-
-bool GoParser::Semicolon() {
- if (match(GoLexer::OP_SEMICOLON))
- return true;
- switch (peek()) {
- case GoLexer::OP_RPAREN:
- case GoLexer::OP_RBRACE:
- case GoLexer::TOK_EOF:
- return true;
- default:
- return false;
- }
-}
-
-GoASTExpr *GoParser::Name() {
- if (auto *id = Identifier()) {
- if (GoASTExpr *qual = QualifiedIdent(id))
- return qual;
- return id;
- }
- return nullptr;
-}
-
-GoASTExpr *GoParser::QualifiedIdent(lldb_private::GoASTIdent *p) {
- Rule r("QualifiedIdent", this);
- llvm::SmallString<32> path(p->GetName().m_value);
- GoLexer::Token *next;
- bool have_slashes = false;
- // LLDB extension: support full/package/path.name
- while (match(GoLexer::OP_SLASH) && (next = match(GoLexer::TOK_IDENTIFIER))) {
- have_slashes = true;
- path.append("/");
- path.append(next->m_value);
- }
- if (match(GoLexer::OP_DOT)) {
- auto *name = Identifier();
- if (name) {
- if (have_slashes) {
- p->SetName(GoLexer::Token(GoLexer::TOK_IDENTIFIER, CopyString(path)));
- }
- return new GoASTSelectorExpr(p, name);
- }
- }
- return r.error();
-}
-
-llvm::StringRef GoParser::CopyString(llvm::StringRef s) {
- return m_strings.insert(std::make_pair(s, 'x')).first->getKey();
-}
-
-void GoParser::GetError(Status &error) {
- llvm::StringRef want;
- if (m_failed)
- want =
- m_last_tok == GoLexer::TOK_INVALID ? DescribeToken(m_last_tok) : m_last;
- else
- want = m_error;
- size_t len = m_lexer.BytesRemaining();
- if (len > 10)
- len = 10;
- llvm::StringRef got;
- if (len == 0)
- got = "<eof>";
- else
- got = m_lexer.GetString(len);
- error.SetErrorStringWithFormat("Syntax error: expected %s before '%s'.",
- want.str().c_str(), got.str().c_str());
-}
diff --git a/source/Plugins/ExpressionParser/Go/GoParser.h b/source/Plugins/ExpressionParser/Go/GoParser.h
deleted file mode 100644
index 9ed2ae2033bd..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoParser.h
+++ /dev/null
@@ -1,145 +0,0 @@
-//===-- GoParser.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_GoParser_h
-#define liblldb_GoParser_h
-
-#include "Plugins/ExpressionParser/Go/GoAST.h"
-#include "Plugins/ExpressionParser/Go/GoLexer.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-class GoParser {
-public:
- explicit GoParser(const char *src);
-
- GoASTStmt *Statement();
-
- GoASTStmt *GoStmt();
- GoASTStmt *ReturnStmt();
- GoASTStmt *BranchStmt();
- GoASTStmt *EmptyStmt();
- GoASTStmt *ExpressionStmt(GoASTExpr *e);
- GoASTStmt *IncDecStmt(GoASTExpr *e);
- GoASTStmt *Assignment(GoASTExpr *e);
- GoASTBlockStmt *Block();
-
- GoASTExpr *MoreExpressionList(); // ["," Expression]
- GoASTIdent *MoreIdentifierList(); // ["," Identifier]
-
- GoASTExpr *Expression();
- GoASTExpr *UnaryExpr();
- GoASTExpr *OrExpr();
- GoASTExpr *AndExpr();
- GoASTExpr *RelExpr();
- GoASTExpr *AddExpr();
- GoASTExpr *MulExpr();
- GoASTExpr *PrimaryExpr();
- GoASTExpr *Operand();
- GoASTExpr *Conversion();
-
- GoASTExpr *Selector(GoASTExpr *e);
- GoASTExpr *IndexOrSlice(GoASTExpr *e);
- GoASTExpr *TypeAssertion(GoASTExpr *e);
- GoASTExpr *Arguments(GoASTExpr *e);
-
- GoASTExpr *Type();
- GoASTExpr *Type2();
- GoASTExpr *ArrayOrSliceType(bool allowEllipsis);
- GoASTExpr *StructType();
- GoASTExpr *FunctionType();
- GoASTExpr *InterfaceType();
- GoASTExpr *MapType();
- GoASTExpr *ChanType();
- GoASTExpr *ChanType2();
-
- GoASTExpr *Name();
- GoASTExpr *QualifiedIdent(GoASTIdent *p);
- GoASTIdent *Identifier();
-
- GoASTField *FieldDecl();
- GoASTExpr *AnonymousFieldType();
- GoASTExpr *FieldNamesAndType(GoASTField *f);
-
- GoASTFieldList *Params();
- GoASTField *ParamDecl();
- GoASTExpr *ParamType();
- GoASTFuncType *Signature();
- GoASTExpr *CompositeLit();
- GoASTExpr *FunctionLit();
- GoASTExpr *Element();
- GoASTCompositeLit *LiteralValue();
-
- bool Failed() const { return m_failed; }
- bool AtEOF() const {
- return m_lexer.BytesRemaining() == 0 && m_pos == m_tokens.size();
- }
-
- void GetError(Status &error);
-
-private:
- class Rule;
- friend class Rule;
-
- std::nullptr_t syntaxerror() {
- m_failed = true;
- return nullptr;
- }
- GoLexer::Token &next() {
- if (m_pos >= m_tokens.size()) {
- if (m_pos != 0 && (m_tokens.back().m_type == GoLexer::TOK_EOF ||
- m_tokens.back().m_type == GoLexer::TOK_INVALID))
- return m_tokens.back();
- m_pos = m_tokens.size();
- m_tokens.push_back(m_lexer.Lex());
- }
- return m_tokens[m_pos++];
- }
- GoLexer::TokenType peek() {
- GoLexer::Token &tok = next();
- --m_pos;
- return tok.m_type;
- }
- GoLexer::Token *match(GoLexer::TokenType t) {
- GoLexer::Token &tok = next();
- if (tok.m_type == t)
- return &tok;
- --m_pos;
- m_last_tok = t;
- return nullptr;
- }
- GoLexer::Token *mustMatch(GoLexer::TokenType t) {
- GoLexer::Token *tok = match(t);
- if (tok)
- return tok;
- return syntaxerror();
- }
- bool Semicolon();
-
- GoASTStmt *FinishStmt(GoASTStmt *s) {
- if (!Semicolon())
- m_failed = true;
- return s;
- }
-
- llvm::StringRef CopyString(llvm::StringRef s);
-
- GoLexer m_lexer;
- std::vector<GoLexer::Token> m_tokens;
- size_t m_pos;
- llvm::StringRef m_error;
- llvm::StringRef m_last;
- GoLexer::TokenType m_last_tok;
- llvm::StringMap<uint8_t> m_strings;
- bool m_failed;
-};
-}
-
-#endif
diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp b/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
deleted file mode 100644
index 3a10a1dc767a..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoUserExpression.cpp
+++ /dev/null
@@ -1,668 +0,0 @@
-//===-- GoUserExpression.cpp ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-// C++ Includes
-#include <cstdlib>
-#include <memory>
-#include <string>
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "GoUserExpression.h"
-
-#include "lldb/Core/Module.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/ValueObjectConstResult.h"
-#include "lldb/Core/ValueObjectRegister.h"
-#include "lldb/Expression/DiagnosticManager.h"
-#include "lldb/Expression/ExpressionVariable.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/TypeList.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/StackFrame.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/ThreadPlan.h"
-#include "lldb/Target/ThreadPlanCallUserExpression.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/DataEncoder.h"
-#include "lldb/Utility/DataExtractor.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/StreamString.h"
-#include "lldb/lldb-private.h"
-
-#include "Plugins/ExpressionParser/Go/GoAST.h"
-#include "Plugins/ExpressionParser/Go/GoParser.h"
-
-using namespace lldb_private;
-using namespace lldb;
-
-class GoUserExpression::GoInterpreter {
-public:
- GoInterpreter(ExecutionContext &exe_ctx, const char *expr)
- : m_exe_ctx(exe_ctx), m_frame(exe_ctx.GetFrameSP()), m_parser(expr) {
- if (m_frame) {
- const SymbolContext &ctx =
- m_frame->GetSymbolContext(eSymbolContextFunction);
- ConstString fname = ctx.GetFunctionName();
- if (fname.GetLength() > 0) {
- size_t dot = fname.GetStringRef().find('.');
- if (dot != llvm::StringRef::npos)
- m_package = llvm::StringRef(fname.AsCString(), dot);
- }
- }
- }
-
- void set_use_dynamic(DynamicValueType use_dynamic) {
- m_use_dynamic = use_dynamic;
- }
-
- bool Parse();
- lldb::ValueObjectSP Evaluate(ExecutionContext &exe_ctx);
- lldb::ValueObjectSP EvaluateStatement(const GoASTStmt *s);
- lldb::ValueObjectSP EvaluateExpr(const GoASTExpr *e);
-
- ValueObjectSP VisitBadExpr(const GoASTBadExpr *e) {
- m_parser.GetError(m_error);
- return nullptr;
- }
-
- ValueObjectSP VisitParenExpr(const GoASTParenExpr *e);
- ValueObjectSP VisitIdent(const GoASTIdent *e);
- ValueObjectSP VisitStarExpr(const GoASTStarExpr *e);
- ValueObjectSP VisitSelectorExpr(const GoASTSelectorExpr *e);
- ValueObjectSP VisitBasicLit(const GoASTBasicLit *e);
- ValueObjectSP VisitIndexExpr(const GoASTIndexExpr *e);
- ValueObjectSP VisitUnaryExpr(const GoASTUnaryExpr *e);
- ValueObjectSP VisitCallExpr(const GoASTCallExpr *e);
-
- ValueObjectSP VisitTypeAssertExpr(const GoASTTypeAssertExpr *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitBinaryExpr(const GoASTBinaryExpr *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitArrayType(const GoASTArrayType *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitChanType(const GoASTChanType *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitCompositeLit(const GoASTCompositeLit *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitEllipsis(const GoASTEllipsis *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitFuncType(const GoASTFuncType *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitFuncLit(const GoASTFuncLit *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitInterfaceType(const GoASTInterfaceType *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitKeyValueExpr(const GoASTKeyValueExpr *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitMapType(const GoASTMapType *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitSliceExpr(const GoASTSliceExpr *e) {
- return NotImplemented(e);
- }
-
- ValueObjectSP VisitStructType(const GoASTStructType *e) {
- return NotImplemented(e);
- }
-
- CompilerType EvaluateType(const GoASTExpr *e);
-
- Status &error() { return m_error; }
-
-private:
- std::nullptr_t NotImplemented(const GoASTExpr *e) {
- m_error.SetErrorStringWithFormat("%s node not implemented",
- e->GetKindName());
- return nullptr;
- }
-
- ExecutionContext m_exe_ctx;
- lldb::StackFrameSP m_frame;
- GoParser m_parser;
- DynamicValueType m_use_dynamic;
- Status m_error;
- llvm::StringRef m_package;
- std::vector<std::unique_ptr<GoASTStmt>> m_statements;
-};
-
-VariableSP FindGlobalVariable(TargetSP target, llvm::Twine name) {
- ConstString fullname(name.str());
- VariableList variable_list;
- if (!target) {
- return nullptr;
- }
- const uint32_t match_count =
- target->GetImages().FindGlobalVariables(fullname, 1, variable_list);
- if (match_count == 1) {
- return variable_list.GetVariableAtIndex(0);
- }
- return nullptr;
-}
-
-CompilerType LookupType(TargetSP target, ConstString name) {
- if (!target)
- return CompilerType();
- SymbolContext sc;
- TypeList type_list;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- uint32_t num_matches = target->GetImages().FindTypes(
- sc, name, false, 2, searched_symbol_files, type_list);
- if (num_matches > 0) {
- return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
- }
- return CompilerType();
-}
-
-GoUserExpression::GoUserExpression(ExecutionContextScope &exe_scope,
- llvm::StringRef expr, llvm::StringRef prefix,
- lldb::LanguageType language,
- ResultType desired_type,
- const EvaluateExpressionOptions &options)
- : UserExpression(exe_scope, expr, prefix, language, desired_type, options) {
-}
-
-bool GoUserExpression::Parse(DiagnosticManager &diagnostic_manager,
- ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory,
- bool generate_debug_info) {
- InstallContext(exe_ctx);
- m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText()));
- if (m_interpreter->Parse())
- return true;
- const char *error_cstr = m_interpreter->error().AsCString();
- if (error_cstr && error_cstr[0])
- diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
- else
- diagnostic_manager.Printf(eDiagnosticSeverityError,
- "expression can't be interpreted or run");
- return false;
-}
-
-lldb::ExpressionResults
-GoUserExpression::DoExecute(DiagnosticManager &diagnostic_manager,
- ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions &options,
- lldb::UserExpressionSP &shared_ptr_to_me,
- lldb::ExpressionVariableSP &result) {
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS |
- LIBLLDB_LOG_STEP));
-
- lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
- lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
-
- Process *process = exe_ctx.GetProcessPtr();
- Target *target = exe_ctx.GetTargetPtr();
-
- if (target == nullptr || process == nullptr ||
- process->GetState() != lldb::eStateStopped) {
- if (execution_policy == eExecutionPolicyAlways) {
- if (log)
- log->Printf("== [GoUserExpression::Evaluate] Expression may not run, "
- "but is not constant ==");
-
- diagnostic_manager.PutString(eDiagnosticSeverityError,
- "expression needed to run but couldn't");
-
- return execution_results;
- }
- }
-
- m_interpreter->set_use_dynamic(options.GetUseDynamic());
- ValueObjectSP result_val_sp = m_interpreter->Evaluate(exe_ctx);
- Status err = m_interpreter->error();
- m_interpreter.reset();
-
- if (!result_val_sp) {
- const char *error_cstr = err.AsCString();
- if (error_cstr && error_cstr[0])
- diagnostic_manager.PutString(eDiagnosticSeverityError, error_cstr);
- else
- diagnostic_manager.PutString(eDiagnosticSeverityError,
- "expression can't be interpreted or run");
- return lldb::eExpressionDiscarded;
- }
- result.reset(new ExpressionVariable(ExpressionVariable::eKindGo));
- result->m_live_sp = result->m_frozen_sp = result_val_sp;
- result->m_flags |= ExpressionVariable::EVIsProgramReference;
- PersistentExpressionState *pv =
- target->GetPersistentExpressionStateForLanguage(eLanguageTypeGo);
- if (pv != nullptr) {
- result->SetName(pv->GetNextPersistentVariableName(
- *target, pv->GetPersistentVariablePrefix()));
- pv->AddVariable(result);
- }
- return lldb::eExpressionCompleted;
-}
-
-bool GoUserExpression::GoInterpreter::Parse() {
- for (std::unique_ptr<GoASTStmt> stmt(m_parser.Statement()); stmt;
- stmt.reset(m_parser.Statement())) {
- if (m_parser.Failed())
- break;
- m_statements.emplace_back(std::move(stmt));
- }
- if (m_parser.Failed() || !m_parser.AtEOF())
- m_parser.GetError(m_error);
-
- return m_error.Success();
-}
-
-ValueObjectSP
-GoUserExpression::GoInterpreter::Evaluate(ExecutionContext &exe_ctx) {
- m_exe_ctx = exe_ctx;
- ValueObjectSP result;
- for (const std::unique_ptr<GoASTStmt> &stmt : m_statements) {
- result = EvaluateStatement(stmt.get());
- if (m_error.Fail())
- return nullptr;
- }
- return result;
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::EvaluateStatement(
- const lldb_private::GoASTStmt *stmt) {
- ValueObjectSP result;
- switch (stmt->GetKind()) {
- case GoASTNode::eBlockStmt: {
- const GoASTBlockStmt *block = llvm::cast<GoASTBlockStmt>(stmt);
- for (size_t i = 0; i < block->NumList(); ++i)
- result = EvaluateStatement(block->GetList(i));
- break;
- }
- case GoASTNode::eBadStmt:
- m_parser.GetError(m_error);
- break;
- case GoASTNode::eExprStmt: {
- const GoASTExprStmt *expr = llvm::cast<GoASTExprStmt>(stmt);
- return EvaluateExpr(expr->GetX());
- }
- default:
- m_error.SetErrorStringWithFormat("%s node not supported",
- stmt->GetKindName());
- }
- return result;
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::EvaluateExpr(
- const lldb_private::GoASTExpr *e) {
- if (e)
- return e->Visit<ValueObjectSP>(this);
- return ValueObjectSP();
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::VisitParenExpr(
- const lldb_private::GoASTParenExpr *e) {
- return EvaluateExpr(e->GetX());
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::VisitIdent(const GoASTIdent *e) {
- ValueObjectSP val;
- if (m_frame) {
- VariableSP var_sp;
- std::string varname = e->GetName().m_value.str();
- if (varname.size() > 1 && varname[0] == '$') {
- RegisterContextSP reg_ctx_sp = m_frame->GetRegisterContext();
- const RegisterInfo *reg =
- reg_ctx_sp->GetRegisterInfoByName(varname.c_str() + 1);
- if (reg) {
- std::string type;
- switch (reg->encoding) {
- case lldb::eEncodingSint:
- type.append("int");
- break;
- case lldb::eEncodingUint:
- type.append("uint");
- break;
- case lldb::eEncodingIEEE754:
- type.append("float");
- break;
- default:
- m_error.SetErrorString("Invalid register encoding");
- return nullptr;
- }
- switch (reg->byte_size) {
- case 8:
- type.append("64");
- break;
- case 4:
- type.append("32");
- break;
- case 2:
- type.append("16");
- break;
- case 1:
- type.append("8");
- break;
- default:
- m_error.SetErrorString("Invalid register size");
- return nullptr;
- }
- ValueObjectSP regVal = ValueObjectRegister::Create(
- m_frame.get(), reg_ctx_sp, reg->kinds[eRegisterKindLLDB]);
- CompilerType goType =
- LookupType(m_frame->CalculateTarget(), ConstString(type));
- if (regVal) {
- regVal = regVal->Cast(goType);
- return regVal;
- }
- }
- m_error.SetErrorString("Invalid register name");
- return nullptr;
- }
- VariableListSP var_list_sp(m_frame->GetInScopeVariableList(false));
- if (var_list_sp) {
- var_sp = var_list_sp->FindVariable(ConstString(varname));
- if (var_sp)
- val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
- else {
- // When a variable is on the heap instead of the stack, go records a
- // variable '&x' instead of 'x'.
- var_sp = var_list_sp->FindVariable(ConstString("&" + varname));
- if (var_sp) {
- val = m_frame->GetValueObjectForFrameVariable(var_sp, m_use_dynamic);
- if (val)
- val = val->Dereference(m_error);
- if (m_error.Fail())
- return nullptr;
- }
- }
- }
- if (!val) {
- m_error.Clear();
- TargetSP target = m_frame->CalculateTarget();
- if (!target) {
- m_error.SetErrorString("No target");
- return nullptr;
- }
- var_sp =
- FindGlobalVariable(target, m_package + "." + e->GetName().m_value);
- if (var_sp)
- return m_frame->TrackGlobalVariable(var_sp, m_use_dynamic);
- }
- }
- if (!val)
- m_error.SetErrorStringWithFormat("Unknown variable %s",
- e->GetName().m_value.str().c_str());
- return val;
-}
-
-ValueObjectSP
-GoUserExpression::GoInterpreter::VisitStarExpr(const GoASTStarExpr *e) {
- ValueObjectSP target = EvaluateExpr(e->GetX());
- if (!target)
- return nullptr;
- return target->Dereference(m_error);
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::VisitSelectorExpr(
- const lldb_private::GoASTSelectorExpr *e) {
- ValueObjectSP target = EvaluateExpr(e->GetX());
- if (target) {
- if (target->GetCompilerType().IsPointerType()) {
- target = target->Dereference(m_error);
- if (m_error.Fail())
- return nullptr;
- }
- ConstString field(e->GetSel()->GetName().m_value);
- ValueObjectSP result = target->GetChildMemberWithName(field, true);
- if (!result)
- m_error.SetErrorStringWithFormat("Unknown child %s", field.AsCString());
- return result;
- }
- if (const GoASTIdent *package = llvm::dyn_cast<GoASTIdent>(e->GetX())) {
- if (VariableSP global = FindGlobalVariable(
- m_exe_ctx.GetTargetSP(), package->GetName().m_value + "." +
- e->GetSel()->GetName().m_value)) {
- if (m_frame) {
- m_error.Clear();
- return m_frame->GetValueObjectForFrameVariable(global, m_use_dynamic);
- }
- }
- }
- if (const GoASTBasicLit *packageLit =
- llvm::dyn_cast<GoASTBasicLit>(e->GetX())) {
- if (packageLit->GetValue().m_type == GoLexer::LIT_STRING) {
- std::string value = packageLit->GetValue().m_value.str();
- value = value.substr(1, value.size() - 2);
- if (VariableSP global = FindGlobalVariable(
- m_exe_ctx.GetTargetSP(),
- value + "." + e->GetSel()->GetName().m_value)) {
- if (m_frame) {
- m_error.Clear();
- return m_frame->TrackGlobalVariable(global, m_use_dynamic);
- }
- }
- }
- }
- // EvaluateExpr should have already set m_error.
- return target;
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::VisitBasicLit(
- const lldb_private::GoASTBasicLit *e) {
- std::string value = e->GetValue().m_value.str();
- if (e->GetValue().m_type != GoLexer::LIT_INTEGER) {
- m_error.SetErrorStringWithFormat("Unsupported literal %s", value.c_str());
- return nullptr;
- }
- errno = 0;
- int64_t intvalue = strtol(value.c_str(), nullptr, 0);
- if (errno != 0) {
- m_error.SetErrorToErrno();
- return nullptr;
- }
- DataBufferSP buf(new DataBufferHeap(sizeof(intvalue), 0));
- TargetSP target = m_exe_ctx.GetTargetSP();
- if (!target) {
- m_error.SetErrorString("No target");
- return nullptr;
- }
- ByteOrder order = target->GetArchitecture().GetByteOrder();
- uint8_t addr_size = target->GetArchitecture().GetAddressByteSize();
- DataEncoder enc(buf, order, addr_size);
- enc.PutU64(0, static_cast<uint64_t>(intvalue));
- DataExtractor data(buf, order, addr_size);
-
- CompilerType type = LookupType(target, ConstString("int64"));
- return ValueObject::CreateValueObjectFromData(llvm::StringRef(), data,
- m_exe_ctx, type);
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::VisitIndexExpr(
- const lldb_private::GoASTIndexExpr *e) {
- ValueObjectSP target = EvaluateExpr(e->GetX());
- if (!target)
- return nullptr;
- ValueObjectSP index = EvaluateExpr(e->GetIndex());
- if (!index)
- return nullptr;
- bool is_signed;
- if (!index->GetCompilerType().IsIntegerType(is_signed)) {
- m_error.SetErrorString("Unsupported index");
- return nullptr;
- }
- size_t idx;
- if (is_signed)
- idx = index->GetValueAsSigned(0);
- else
- idx = index->GetValueAsUnsigned(0);
- if (GoASTContext::IsGoSlice(target->GetCompilerType())) {
- target = target->GetStaticValue();
- ValueObjectSP cap =
- target->GetChildMemberWithName(ConstString("cap"), true);
- if (cap) {
- uint64_t capval = cap->GetValueAsUnsigned(0);
- if (idx >= capval) {
- m_error.SetErrorStringWithFormat("Invalid index %" PRIu64
- " , cap = %" PRIu64,
- uint64_t(idx), capval);
- return nullptr;
- }
- }
- target = target->GetChildMemberWithName(ConstString("array"), true);
- if (target && m_use_dynamic != eNoDynamicValues) {
- ValueObjectSP dynamic = target->GetDynamicValue(m_use_dynamic);
- if (dynamic)
- target = dynamic;
- }
- if (!target)
- return nullptr;
- return target->GetSyntheticArrayMember(idx, true);
- }
- return target->GetChildAtIndex(idx, true);
-}
-
-ValueObjectSP
-GoUserExpression::GoInterpreter::VisitUnaryExpr(const GoASTUnaryExpr *e) {
- ValueObjectSP x = EvaluateExpr(e->GetX());
- if (!x)
- return nullptr;
- switch (e->GetOp()) {
- case GoLexer::OP_AMP: {
- CompilerType type = x->GetCompilerType().GetPointerType();
- uint64_t address = x->GetAddressOf();
- return ValueObject::CreateValueObjectFromAddress(llvm::StringRef(), address,
- m_exe_ctx, type);
- }
- case GoLexer::OP_PLUS:
- return x;
- default:
- m_error.SetErrorStringWithFormat(
- "Operator %s not supported",
- GoLexer::LookupToken(e->GetOp()).str().c_str());
- return nullptr;
- }
-}
-
-CompilerType GoUserExpression::GoInterpreter::EvaluateType(const GoASTExpr *e) {
- TargetSP target = m_exe_ctx.GetTargetSP();
- if (auto *id = llvm::dyn_cast<GoASTIdent>(e)) {
- CompilerType result =
- LookupType(target, ConstString(id->GetName().m_value));
- if (result.IsValid())
- return result;
- std::string fullname = (m_package + "." + id->GetName().m_value).str();
- result = LookupType(target, ConstString(fullname));
- if (!result)
- m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
- return result;
- }
- if (auto *sel = llvm::dyn_cast<GoASTSelectorExpr>(e)) {
- std::string package;
- if (auto *pkg_node = llvm::dyn_cast<GoASTIdent>(sel->GetX())) {
- package = pkg_node->GetName().m_value.str();
- } else if (auto *str_node = llvm::dyn_cast<GoASTBasicLit>(sel->GetX())) {
- if (str_node->GetValue().m_type == GoLexer::LIT_STRING) {
- package = str_node->GetValue().m_value.substr(1).str();
- package.resize(package.length() - 1);
- }
- }
- if (package.empty()) {
- m_error.SetErrorStringWithFormat("Invalid %s in type expression",
- sel->GetX()->GetKindName());
- return CompilerType();
- }
- std::string fullname =
- (package + "." + sel->GetSel()->GetName().m_value).str();
- CompilerType result = LookupType(target, ConstString(fullname));
- if (!result)
- m_error.SetErrorStringWithFormat("Unknown type %s", fullname.c_str());
- return result;
- }
- if (auto *star = llvm::dyn_cast<GoASTStarExpr>(e)) {
- CompilerType elem = EvaluateType(star->GetX());
- return elem.GetPointerType();
- }
- if (auto *paren = llvm::dyn_cast<GoASTParenExpr>(e))
- return EvaluateType(paren->GetX());
- if (auto *array = llvm::dyn_cast<GoASTArrayType>(e)) {
- CompilerType elem = EvaluateType(array->GetElt());
- }
-
- m_error.SetErrorStringWithFormat("Invalid %s in type expression",
- e->GetKindName());
- return CompilerType();
-}
-
-ValueObjectSP GoUserExpression::GoInterpreter::VisitCallExpr(
- const lldb_private::GoASTCallExpr *e) {
- ValueObjectSP x = EvaluateExpr(e->GetFun());
- if (x || e->NumArgs() != 1) {
- m_error.SetErrorStringWithFormat("Code execution not supported");
- return nullptr;
- }
- m_error.Clear();
- CompilerType type = EvaluateType(e->GetFun());
- if (!type) {
- return nullptr;
- }
- ValueObjectSP value = EvaluateExpr(e->GetArgs(0));
- if (!value)
- return nullptr;
- // TODO: Handle special conversions
- return value->Cast(type);
-}
-
-GoPersistentExpressionState::GoPersistentExpressionState()
- : PersistentExpressionState(eKindGo) {}
-
-void GoPersistentExpressionState::RemovePersistentVariable(
- lldb::ExpressionVariableSP variable) {
- RemoveVariable(variable);
-
- const char *name = variable->GetName().AsCString();
-
- if (*(name++) != '$')
- return;
- if (*(name++) != 'g')
- return;
- if (*(name++) != 'o')
- return;
-
- if (strtoul(name, nullptr, 0) == m_next_persistent_variable_id - 1)
- m_next_persistent_variable_id--;
-}
diff --git a/source/Plugins/ExpressionParser/Go/GoUserExpression.h b/source/Plugins/ExpressionParser/Go/GoUserExpression.h
deleted file mode 100644
index e2839da9bfdd..000000000000
--- a/source/Plugins/ExpressionParser/Go/GoUserExpression.h
+++ /dev/null
@@ -1,94 +0,0 @@
-//===-- GoUserExpression.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_GoUserExpression_h_
-#define liblldb_GoUserExpression_h_
-
-// C Includes
-// C++ Includes
-#include <memory>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Expression/ExpressionVariable.h"
-#include "lldb/Expression/UserExpression.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-class GoParser;
-
-class GoPersistentExpressionState : public PersistentExpressionState {
-public:
- GoPersistentExpressionState();
-
- llvm::StringRef
- GetPersistentVariablePrefix(bool is_error) const override {
- return "$go";
- }
- void RemovePersistentVariable(lldb::ExpressionVariableSP variable) override;
-
- lldb::addr_t LookupSymbol(const ConstString &name) override {
- return LLDB_INVALID_ADDRESS;
- }
-
- static bool classof(const PersistentExpressionState *pv) {
- return pv->getKind() == PersistentExpressionState::eKindGo;
- }
-
-private:
- uint32_t m_next_persistent_variable_id; ///< The counter used by
- ///GetNextResultName().
-};
-
-//----------------------------------------------------------------------
-/// @class GoUserExpression GoUserExpression.h
-/// "lldb/Expression/GoUserExpression.h" Encapsulates a single expression for
-/// use with Go
-///
-/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. GoUserExpression encapsulates the
-/// objects needed to parse and interpret an expression.
-//----------------------------------------------------------------------
-class GoUserExpression : public UserExpression {
-public:
- GoUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
- llvm::StringRef prefix, lldb::LanguageType language,
- ResultType desired_type,
- const EvaluateExpressionOptions &options);
-
- bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- lldb_private::ExecutionPolicy execution_policy,
- bool keep_result_in_memory, bool generate_debug_info) override;
-
- bool CanInterpret() override { return true; }
- bool FinalizeJITExecution(
- DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- lldb::ExpressionVariableSP &result,
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override {
- return true;
- }
-
-protected:
- lldb::ExpressionResults
- DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions &options,
- lldb::UserExpressionSP &shared_ptr_to_me,
- lldb::ExpressionVariableSP &result) override;
-
-private:
- class GoInterpreter;
- std::unique_ptr<GoInterpreter> m_interpreter;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_GoUserExpression_h_
diff --git a/source/Plugins/ExpressionParser/Go/gen_go_ast.py b/source/Plugins/ExpressionParser/Go/gen_go_ast.py
deleted file mode 100644
index 3be0e5f506ee..000000000000
--- a/source/Plugins/ExpressionParser/Go/gen_go_ast.py
+++ /dev/null
@@ -1,464 +0,0 @@
-import StringIO
-
-
-def addNodes():
- addNode("ArrayType", "Expr", "len", "Expr", "elt", "Expr")
- addNode(
- "AssignStmt",
- "Stmt",
- "lhs",
- "[]Expr",
- "rhs",
- "[]Expr",
- "define",
- "bool")
- addNode("BadDecl", "Decl")
- addNode("BadExpr", "Expr")
- addNode("BadStmt", "Stmt")
- addNode("BasicLit", "Expr", "value", "Token")
- addNode("BinaryExpr", "Expr", "x", "Expr", "y", "Expr", "op", "TokenType")
- addNode("BlockStmt", "Stmt", "list", "[]Stmt")
- addNode("Ident", "Expr", "name", "Token")
- addNode("BranchStmt", "Stmt", "label", "Ident", "tok", "TokenType")
- addNode(
- "CallExpr",
- "Expr",
- "fun",
- "Expr",
- "args",
- "[]Expr",
- "ellipsis",
- "bool")
- addNode("CaseClause", "Stmt", "list", "[]Expr", "body", "[]Stmt")
- addNode("ChanType", "Expr", "dir", "ChanDir", "value", "Expr")
- addNode("CommClause", "Stmt", "comm", "Stmt", "body", "[]Stmt")
- addNode("CompositeLit", "Expr", "type", "Expr", "elts", "[]Expr")
- addNode("DeclStmt", "Stmt", "decl", "Decl")
- addNode("DeferStmt", "Stmt", "call", "CallExpr")
- addNode("Ellipsis", "Expr", "elt", "Expr")
- addNode("EmptyStmt", "Stmt")
- addNode("ExprStmt", "Stmt", "x", "Expr")
- addNode(
- "Field",
- "Node",
- "names",
- "[]Ident",
- "type",
- "Expr",
- "tag",
- "BasicLit")
- addNode("FieldList", "Node", "list", "[]Field")
- addNode(
- "ForStmt",
- "Stmt",
- "init",
- "Stmt",
- "cond",
- "Expr",
- "post",
- "Stmt",
- "body",
- "BlockStmt")
- addNode("FuncType", "Expr", "params", "FieldList", "results", "FieldList")
- addNode(
- "FuncDecl",
- "Decl",
- "recv",
- "FieldList",
- "name",
- "Ident",
- "type",
- "FuncType",
- "body",
- "BlockStmt")
- addNode("FuncLit", "Expr", "type", "FuncType", "body", "BlockStmt")
- addNode("GenDecl", "Decl", "tok", "TokenType", "specs", "[]Spec")
- addNode("GoStmt", "Stmt", "call", "CallExpr")
- addNode(
- "IfStmt",
- "Stmt",
- "init",
- "Stmt",
- "cond",
- "Expr",
- "body",
- "BlockStmt",
- "els",
- "Stmt")
- addNode("ImportSpec", "Spec", "name", "Ident", "path", "BasicLit")
- addNode("IncDecStmt", "Stmt", "x", "Expr", "tok", "TokenType")
- addNode("IndexExpr", "Expr", "x", "Expr", "index", "Expr")
- addNode("InterfaceType", "Expr", "methods", "FieldList")
- addNode("KeyValueExpr", "Expr", "key", "Expr", "value", "Expr")
- addNode("LabeledStmt", "Stmt", "label", "Ident", "stmt", "Stmt")
- addNode("MapType", "Expr", "key", "Expr", "value", "Expr")
- addNode("ParenExpr", "Expr", "x", "Expr")
- addNode(
- "RangeStmt",
- "Stmt",
- "key",
- "Expr",
- "value",
- "Expr",
- "define",
- "bool",
- "x",
- "Expr",
- "body",
- "BlockStmt")
- addNode("ReturnStmt", "Stmt", "results", "[]Expr")
- addNode("SelectStmt", "Stmt", "body", "BlockStmt")
- addNode("SelectorExpr", "Expr", "x", "Expr", "sel", "Ident")
- addNode("SendStmt", "Stmt", "chan", "Expr", "value", "Expr")
- addNode(
- "SliceExpr",
- "Expr",
- "x",
- "Expr",
- "low",
- "Expr",
- "high",
- "Expr",
- "max",
- "Expr",
- "slice3",
- "bool")
- addNode("StarExpr", "Expr", "x", "Expr")
- addNode("StructType", "Expr", "fields", "FieldList")
- addNode(
- "SwitchStmt",
- "Stmt",
- "init",
- "Stmt",
- "tag",
- "Expr",
- "body",
- "BlockStmt")
- addNode("TypeAssertExpr", "Expr", "x", "Expr", "type", "Expr")
- addNode("TypeSpec", "Spec", "name", "Ident", "type", "Expr")
- addNode(
- "TypeSwitchStmt",
- "Stmt",
- "init",
- "Stmt",
- "assign",
- "Stmt",
- "body",
- "BlockStmt")
- addNode("UnaryExpr", "Expr", "op", "TokenType", "x", "Expr")
- addNode(
- "ValueSpec",
- "Spec",
- "names",
- "[]Ident",
- "type",
- "Expr",
- "values",
- "[]Expr")
- addParent("Decl", "Node")
- addParent("Expr", "Node")
- addParent("Spec", "Node")
- addParent("Stmt", "Node")
-
-
-class Member(object):
-
- def __init__(self, name, typename):
- self.title = name.title()
- self.sname = name
- self.mname = 'm_' + name
- self.is_list = typename.startswith("[]")
- self.is_value = isValueType(typename)
- if self.is_value:
- self.argtype = typename
- self.mtype = typename
- elif self.is_list:
- self.argtype = 'GoAST' + typename[2:]
- self.mtype = 'std::vector<std::unique_ptr<%s> >' % self.argtype
- else:
- self.argtype = 'GoAST' + typename
- self.mtype = 'std::unique_ptr<%s>' % self.argtype
- self.mname = self.mname + '_up'
-
-
-kinds = {}
-parentClasses = StringIO.StringIO()
-childClasses = StringIO.StringIO()
-walker = StringIO.StringIO()
-
-
-def startClass(name, parent, out):
- out.write("""
-class GoAST%s : public GoAST%s
-{
- public:
-""" % (name, parent))
-
-
-def endClass(name, out):
- out.write("""
- %(name)s(const %(name)s &) = delete;
- const %(name)s &operator=(const %(name)s &) = delete;
-};
-""" % {'name': 'GoAST' + name})
-
-
-def addNode(name, parent, *children):
- startClass(name, parent, childClasses)
- l = kinds.setdefault(parent, [])
- l.append(name)
- children = createMembers(name, children)
- addConstructor(name, parent, children)
- childClasses.write("""
- const char *
- GetKindName() const override
- {
- return "%(name)s";
- }
-
- static bool
- classof(const GoASTNode *n)
- {
- return n->GetKind() == e%(name)s;
- }
- """ % {'name': name})
- addChildren(name, children)
- endClass(name, childClasses)
-
-
-def isValueType(typename):
- if typename[0].islower():
- return True
- if typename[0].isupper():
- return typename.startswith('Token') or typename == 'ChanDir'
- return False
-
-
-def createMembers(name, children):
- l = len(children)
- if (l % 2) != 0:
- raise Exception("Invalid children for %s: %s" % (name, children))
- return [Member(children[i], children[i + 1]) for i in xrange(0, l, 2)]
-
-
-def addConstructor(name, parent, children):
- for c in children:
- if c.is_list:
- children = [x for x in children if x.is_value]
- break
- childClasses.write(' ')
- if len(children) == 1:
- childClasses.write('explicit ')
- childClasses.write('GoAST%s(' % name)
- for i in xrange(len(children)):
- if i > 0:
- childClasses.write(', ')
-
- c = children[i]
- if c.is_value:
- childClasses.write(c.argtype)
- childClasses.write(' ')
- else:
- childClasses.write('%s *' % c.argtype)
- childClasses.write(c.sname)
- childClasses.write(') : GoAST%s(e%s)' % (parent, name))
- for c in children:
- childClasses.write(', ')
- childClasses.write('%(mname)s(%(sname)s)' % c.__dict__)
- childClasses.write(""" {}
- ~GoAST%s() override = default;
-""" % name)
-
-
-def addChildren(name, children):
- if len(children) == 0:
- return
- walker.write("""
- case e%(n)s:
- {
- GoAST%(n)s *n = llvm::cast<GoAST%(n)s>(this);
- (void)n;""" % {'n': name})
- for c in children:
- if c.is_list:
- childClasses.write("""
- size_t
- Num%(title)s() const
- {
- return %(mname)s.size();
- }
- const %(argtype)s *
- Get%(title)s(int i) const
- {
- return %(mname)s[i].get();
- }
- void
- Add%(title)s(%(argtype)s *%(sname)s)
- {
- %(mname)s.push_back(std::unique_ptr<%(argtype)s>(%(sname)s));
- }
-""" % c.__dict__)
- walker.write("""
- for (auto& e : n->%s) { v(e.get()); }""" % c.mname)
- else:
- const = ''
- get = ''
- set = ''
- t = c.argtype
- if isValueType(t):
- set = '%(mname)s = %(sname)s' % c.__dict__
- t = t + ' '
- else:
- t = t + ' *'
- const = 'const '
- get = '.get()'
- set = '%(mname)s.reset(%(sname)s)' % c.__dict__
- walker.write("""
- v(n->%s.get());""" % c.mname)
- childClasses.write("""
- %(const)s%(type)s
- Get%(title)s() const
- {
- return %(mname)s%(get)s;
- }
- void
- Set%(title)s(%(type)s%(sname)s)
- {
- %(set)s;
- }
-""" % {'const': const, 'title': c.title, 'sname': c.sname, 'get': get, 'set': set, 'type': t, 'mname': c.mname})
- childClasses.write('\n private:\n friend class GoASTNode;\n')
- walker.write("""
- return;
- }""")
- for c in children:
- childClasses.write(' %s %s;\n' % (c.mtype, c.mname))
-
-
-def addParent(name, parent):
- startClass(name, parent, parentClasses)
- l = kinds[name]
- minName = l[0]
- maxName = l[-1]
- parentClasses.write(""" template <typename R, typename V> R Visit(V *v) const;
-
- static bool
- classof(const GoASTNode *n)
- {
- return n->GetKind() >= e%s && n->GetKind() <= e%s;
- }
-
- protected:
- explicit GoAST%s(NodeKind kind) : GoASTNode(kind) { }
- private:
-""" % (minName, maxName, name))
- endClass(name, parentClasses)
-
-addNodes()
-
-print """//===-- GoAST.h -------------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// DO NOT EDIT.
-// Generated by gen_go_ast.py
-
-#ifndef liblldb_GoAST_h
-#define liblldb_GoAST_h
-
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-private.h"
-#include "llvm/Support/Casting.h"
-#include "Plugins/ExpressionParser/Go/GoLexer.h"
-
-namespace lldb_private
-{
-
-class GoASTNode
-{
- public:
- typedef GoLexer::TokenType TokenType;
- typedef GoLexer::Token Token;
- enum ChanDir
- {
- eChanBidir,
- eChanSend,
- eChanRecv,
- };
- enum NodeKind
- {"""
-for l in kinds.itervalues():
- for x in l:
- print " e%s," % x
-print """ };
-
- virtual ~GoASTNode() = default;
-
- NodeKind
- GetKind() const
- {
- return m_kind;
- }
-
- virtual const char *GetKindName() const = 0;
-
- template <typename V> void WalkChildren(V &v);
-
- protected:
- explicit GoASTNode(NodeKind kind) : m_kind(kind) { }
-
- private:
- const NodeKind m_kind;
-
- GoASTNode(const GoASTNode &) = delete;
- const GoASTNode &operator=(const GoASTNode &) = delete;
-};
-"""
-
-
-print parentClasses.getvalue()
-print childClasses.getvalue()
-
-for k, l in kinds.iteritems():
- if k == 'Node':
- continue
- print """
-template <typename R, typename V>
-R GoAST%s::Visit(V* v) const
-{
- switch(GetKind())
- {""" % k
- for subtype in l:
- print """ case e%(n)s:
- return v->Visit%(n)s(llvm::cast<const GoAST%(n)s>(this));""" % {'n': subtype}
-
- print """ default:
- assert(false && "Invalid kind");
- }
-}"""
-
-print """
-template <typename V>
-void GoASTNode::WalkChildren(V &v)
-{
- switch (m_kind)
- {
-"""
-print walker.getvalue()
-print"""
- case eEmptyStmt:
- case eBadDecl:
- case eBadExpr:
- case eBadStmt:
- break;
- }
-}
-
-} // namespace lldb_private
-
-#endif
-"""
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 86744520ad63..85bc4a61c9d4 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -26,8 +26,7 @@
#include "Utility/ARM_DWARF_Registers.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
- // and countTrailingZeros function
+#include "llvm/Support/MathExtras.h"
using namespace lldb;
using namespace lldb_private;
@@ -777,10 +776,7 @@ bool EmulateInstructionARM::WriteBits32UnknownToMemory(addr_t address) {
uint32_t random_data = rand();
const uint32_t addr_byte_size = GetAddressByteSize();
- if (!MemAWrite(context, address, random_data, addr_byte_size))
- return false;
-
- return true;
+ return MemAWrite(context, address, random_data, addr_byte_size);
}
// Write "bits (32) UNKNOWN" to register n. Helper function for many ARM
@@ -850,6 +846,7 @@ uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber() const {
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
case llvm::Triple::WatchOS:
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
is_apple = true;
break;
default:
@@ -3340,10 +3337,7 @@ bool EmulateInstructionARM::EmulateCMNImm(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteFlags(context, res.result, res.carry_out, res.overflow);
}
// Compare Negative (register) adds a register value and an optionally-shifted
@@ -3410,10 +3404,7 @@ bool EmulateInstructionARM::EmulateCMNReg(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteFlags(context, res.result, res.carry_out, res.overflow);
}
// Compare (immediate) subtracts an immediate value from a register value. It
@@ -3463,10 +3454,7 @@ bool EmulateInstructionARM::EmulateCMPImm(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteFlags(context, res.result, res.carry_out, res.overflow);
}
// Compare (register) subtracts an optionally-shifted register value from a
@@ -3542,10 +3530,7 @@ bool EmulateInstructionARM::EmulateCMPReg(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteFlags(context, res.result, res.carry_out, res.overflow);
}
// Arithmetic Shift Right (immediate) shifts a register value right by an
@@ -9245,11 +9230,8 @@ bool EmulateInstructionARM::EmulateRSBImm(const uint32_t opcode,
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// Reverse Subtract (register) subtracts a register value from an optionally-
@@ -9326,11 +9308,8 @@ bool EmulateInstructionARM::EmulateRSBReg(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// Reverse Subtract with Carry (immediate) subtracts a register value and the
@@ -9388,11 +9367,8 @@ bool EmulateInstructionARM::EmulateRSCImm(const uint32_t opcode,
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// Reverse Subtract with Carry (register) subtracts a register value and the
@@ -9460,11 +9436,8 @@ bool EmulateInstructionARM::EmulateRSCReg(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// Subtract with Carry (immediate) subtracts an immediate value and the value
@@ -9531,11 +9504,8 @@ bool EmulateInstructionARM::EmulateSBCImm(const uint32_t opcode,
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// Subtract with Carry (register) subtracts an optionally-shifted register
@@ -9620,11 +9590,8 @@ bool EmulateInstructionARM::EmulateSBCReg(const uint32_t opcode,
EmulateInstruction::Context context;
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// This instruction subtracts an immediate value from a register value, and
@@ -9713,11 +9680,8 @@ bool EmulateInstructionARM::EmulateSUBImmThumb(const uint32_t opcode,
context.type = EmulateInstruction::eContextImmediate;
context.SetNoArgs();
- if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
- res.carry_out, res.overflow))
- return false;
-
- return true;
+ return WriteCoreRegOptionalFlags(context, res.result, Rd, setflags,
+ res.carry_out, res.overflow);
}
// This instruction subtracts an immediate value from a register value, and
@@ -14153,11 +14117,8 @@ bool EmulateInstructionARM::BranchWritePC(const Context &context,
else
target = addr & 0xfffffffe;
- if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
- LLDB_REGNUM_GENERIC_PC, target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_PC, target);
}
// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by
@@ -14191,11 +14152,8 @@ bool EmulateInstructionARM::BXWritePC(Context &context, uint32_t addr) {
LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
return false;
}
- if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
- LLDB_REGNUM_GENERIC_PC, target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_PC, target);
}
// Dispatches to either BXWritePC or BranchWritePC based on architecture
@@ -14408,14 +14366,14 @@ bool EmulateInstructionARM::EvaluateInstruction(uint32_t evaluate_options) {
evaluate_options & eEmulateInstructionOptionIgnoreConditions;
bool success = false;
- if (m_opcode_cpsr == 0 || m_ignore_conditions == false) {
+ if (m_opcode_cpsr == 0 || !m_ignore_conditions) {
m_opcode_cpsr =
ReadRegisterUnsigned(eRegisterKindDWARF, dwarf_cpsr, 0, &success);
}
// Only return false if we are unable to read the CPSR if we care about
// conditions
- if (success == false && m_ignore_conditions == false)
+ if (!success && !m_ignore_conditions)
return false;
uint32_t orig_pc_value = 0;
diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
index d1032f56f31c..d770b3bdc52e 100644
--- a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
@@ -9,12 +9,12 @@
#include "EmulationStateARM.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Interpreter/OptionValueArray.h"
#include "lldb/Interpreter/OptionValueDictionary.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "Utility/ARM_DWARF_Registers.h"
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
index 2f484ab5ea97..661a651c56c2 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp
@@ -13,10 +13,10 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Stream.h"
#include "Plugins/Process/Utility/ARMDefines.h"
@@ -41,8 +41,7 @@
#include "Plugins/Process/Utility/RegisterInfos_arm64.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
- // and CountTrailingZeros_32 function
+#include "llvm/Support/MathExtras.h"
#include "Plugins/Process/Utility/InstructionUtils.h"
@@ -437,7 +436,7 @@ bool EmulateInstructionARM64::EvaluateInstruction(uint32_t evaluate_options) {
// Only return false if we are unable to read the CPSR if we care about
// conditions
- if (success == false && m_ignore_conditions == false)
+ if (!success && !m_ignore_conditions)
return false;
uint32_t orig_pc_value = 0;
@@ -547,11 +546,8 @@ bool EmulateInstructionARM64::BranchTo(const Context &context, uint32_t N,
} else
return false;
- if (!WriteRegisterUnsigned(context, eRegisterKindGeneric,
- LLDB_REGNUM_GENERIC_PC, addr))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindGeneric,
+ LLDB_REGNUM_GENERIC_PC, addr);
}
bool EmulateInstructionARM64::ConditionHolds(const uint32_t cond) {
@@ -1097,9 +1093,7 @@ bool EmulateInstructionARM64::EmulateB(const uint32_t opcode) {
return false;
}
- if (!BranchTo(context, 64, target))
- return false;
- return true;
+ return BranchTo(context, 64, target);
}
bool EmulateInstructionARM64::EmulateBcond(const uint32_t opcode) {
diff --git a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
index 253bb935bca7..1d1bd74d3f61 100644
--- a/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
+++ b/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.h
@@ -10,10 +10,6 @@
#ifndef EmulateInstructionARM64_h_
#define EmulateInstructionARM64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/ARMDefines.h"
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Interpreter/OptionValue.h"
diff --git a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
index b65747e12890..7fccb2311026 100644
--- a/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
+++ b/source/Plugins/Instruction/MIPS/EmulateInstructionMIPS.cpp
@@ -14,12 +14,12 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Stream.h"
#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -35,7 +35,7 @@
#include "llvm/ADT/STLExtras.h"
#include "Plugins/Process/Utility/InstructionUtils.h"
-#include "Plugins/Process/Utility/RegisterContext_mips.h" //mips32 has same registers nos as mips64
+#include "Plugins/Process/Utility/RegisterContext_mips.h"
using namespace lldb;
using namespace lldb_private;
@@ -220,10 +220,8 @@ EmulateInstructionMIPS::CreateInstance(const ArchSpec &arch,
}
bool EmulateInstructionMIPS::SetTargetTriple(const ArchSpec &arch) {
- if (arch.GetTriple().getArch() == llvm::Triple::mips ||
- arch.GetTriple().getArch() == llvm::Triple::mipsel)
- return true;
- return false;
+ return arch.GetTriple().getArch() == llvm::Triple::mips ||
+ arch.GetTriple().getArch() == llvm::Triple::mipsel;
}
const char *EmulateInstructionMIPS::GetRegisterName(unsigned reg_num,
@@ -1350,10 +1348,7 @@ bool EmulateInstructionMIPS::Emulate_LW(llvm::MCInst &insn) {
context.type = eContextPopRegisterOffStack;
context.SetAddress(address);
- if (!WriteRegister(context, &reg_info_src, data_src))
- return false;
-
- return true;
+ return WriteRegister(context, &reg_info_src, data_src);
}
return false;
@@ -1450,11 +1445,8 @@ bool EmulateInstructionMIPS::Emulate_LUI(llvm::MCInst &insn) {
context.SetImmediateSigned(imm);
context.type = eContextImmediate;
- if (WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips + rt,
- imm))
- return true;
-
- return false;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF,
+ dwarf_zero_mips + rt, imm);
}
bool EmulateInstructionMIPS::Emulate_ADDIUSP(llvm::MCInst &insn) {
@@ -1697,10 +1689,7 @@ bool EmulateInstructionMIPS::Emulate_LWSP(llvm::MCInst &insn) {
context.type = eContextPopRegisterOffStack;
context.SetAddress(base_address);
- if (!WriteRegister(context, &reg_info_src, data_src))
- return false;
-
- return true;
+ return WriteRegister(context, &reg_info_src, data_src);
}
return false;
@@ -1807,11 +1796,8 @@ bool EmulateInstructionMIPS::Emulate_JRADDIUSP(llvm::MCInst &insn) {
context.type = eContextAdjustStackPointer;
// update SP
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,
- result))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_sp_mips,
+ result);
}
static int IsAdd64bitOverflow(int32_t a, int32_t b) {
@@ -1864,11 +1850,8 @@ bool EmulateInstructionMIPS::Emulate_BXX_3ops(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
/*
@@ -1947,11 +1930,8 @@ bool EmulateInstructionMIPS::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(current_inst_size + offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
/*
@@ -2122,11 +2102,8 @@ bool EmulateInstructionMIPS::Emulate_BXX_2ops(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
/*
@@ -2189,11 +2166,8 @@ bool EmulateInstructionMIPS::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(current_inst_size + offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {
@@ -2214,11 +2188,8 @@ bool EmulateInstructionMIPS::Emulate_B16_MM(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(current_inst_size + offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
/*
@@ -2529,11 +2500,8 @@ bool EmulateInstructionMIPS::Emulate_BC(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
@@ -2556,10 +2524,7 @@ bool EmulateInstructionMIPS::Emulate_J(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips, pc);
}
bool EmulateInstructionMIPS::Emulate_JAL(llvm::MCInst &insn) {
@@ -2688,11 +2653,8 @@ bool EmulateInstructionMIPS::Emulate_JIC(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
@@ -2713,11 +2675,8 @@ bool EmulateInstructionMIPS::Emulate_JR(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- rs_val))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ rs_val);
}
/*
@@ -2758,11 +2717,8 @@ bool EmulateInstructionMIPS::Emulate_FP_branch(llvm::MCInst &insn) {
}
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {
@@ -2797,11 +2753,8 @@ bool EmulateInstructionMIPS::Emulate_BC1EQZ(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {
@@ -2836,11 +2789,8 @@ bool EmulateInstructionMIPS::Emulate_BC1NEZ(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
/*
@@ -2898,11 +2848,8 @@ bool EmulateInstructionMIPS::Emulate_3D_branch(llvm::MCInst &insn) {
}
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_BNZB(llvm::MCInst &insn) {
@@ -2993,11 +2940,8 @@ bool EmulateInstructionMIPS::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_BNZV(llvm::MCInst &insn) {
@@ -3039,11 +2983,8 @@ bool EmulateInstructionMIPS::Emulate_MSA_Branch_V(llvm::MCInst &insn,
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips,
+ target);
}
bool EmulateInstructionMIPS::Emulate_LDST_Imm(llvm::MCInst &insn) {
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index 5af12ad141aa..9d178dd97ddf 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -14,12 +14,12 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Opcode.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Stream.h"
#include "llvm-c/Disassembler.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -207,10 +207,8 @@ EmulateInstructionMIPS64::CreateInstance(const ArchSpec &arch,
}
bool EmulateInstructionMIPS64::SetTargetTriple(const ArchSpec &arch) {
- if (arch.GetTriple().getArch() == llvm::Triple::mips64 ||
- arch.GetTriple().getArch() == llvm::Triple::mips64el)
- return true;
- return false;
+ return arch.GetTriple().getArch() == llvm::Triple::mips64 ||
+ arch.GetTriple().getArch() == llvm::Triple::mips64el;
}
const char *EmulateInstructionMIPS64::GetRegisterName(unsigned reg_num,
@@ -1099,13 +1097,24 @@ bool EmulateInstructionMIPS64::Emulate_DADDiu(llvm::MCInst &insn) {
Context context;
/* read <src> register */
- const int64_t src_opd_val = ReadRegisterUnsigned(
+ const uint64_t src_opd_val = ReadRegisterUnsigned(
eRegisterKindDWARF, dwarf_zero_mips64 + src, 0, &success);
if (!success)
return false;
/* Check if this is daddiu sp, sp, imm16 */
if (dst == dwarf_sp_mips64) {
+ /*
+ * From the MIPS IV spec:
+ *
+ * The term “unsigned” in the instruction name is a misnomer; this
+ * operation is 64-bit modulo arithmetic that does not trap on overflow.
+ * It is appropriate for arithmetic which is not signed, such as address
+ * arithmetic, or integer arithmetic environments that ignore overflow,
+ * such as “C” language arithmetic.
+ *
+ * Assume 2's complement and rely on unsigned overflow here.
+ */
uint64_t result = src_opd_val + imm;
RegisterInfo reg_info_sp;
@@ -1229,10 +1238,7 @@ bool EmulateInstructionMIPS64::Emulate_LD(llvm::MCInst &insn) {
Context context;
context.type = eContextRegisterLoad;
- if (!WriteRegister(context, &reg_info_src, data_src))
- return false;
-
- return true;
+ return WriteRegister(context, &reg_info_src, data_src);
}
return false;
@@ -1251,11 +1257,8 @@ bool EmulateInstructionMIPS64::Emulate_LUI(llvm::MCInst &insn) {
context.SetImmediateSigned(imm);
context.type = eContextImmediate;
- if (WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_zero_mips64 + rt,
- imm))
- return true;
-
- return false;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF,
+ dwarf_zero_mips64 + rt, imm);
}
bool EmulateInstructionMIPS64::Emulate_DSUBU_DADDU(llvm::MCInst &insn) {
@@ -1383,11 +1386,8 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
/*
@@ -1622,11 +1622,8 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
@@ -1648,11 +1645,8 @@ bool EmulateInstructionMIPS64::Emulate_BC(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
static int IsAdd64bitOverflow(int64_t a, int64_t b) {
@@ -1736,11 +1730,8 @@ bool EmulateInstructionMIPS64::Emulate_BXX_3ops_C(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(current_inst_size + offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
/*
@@ -1803,11 +1794,8 @@ bool EmulateInstructionMIPS64::Emulate_BXX_2ops_C(llvm::MCInst &insn) {
context.type = eContextRelativeBranchImmediate;
context.SetImmediate(current_inst_size + offset);
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
@@ -1830,10 +1818,8 @@ bool EmulateInstructionMIPS64::Emulate_J(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64, pc))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ pc);
}
bool EmulateInstructionMIPS64::Emulate_JAL(llvm::MCInst &insn) {
@@ -1962,11 +1948,8 @@ bool EmulateInstructionMIPS64::Emulate_JIC(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
@@ -1987,11 +1970,8 @@ bool EmulateInstructionMIPS64::Emulate_JR(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- rs_val))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ rs_val);
}
/*
@@ -2041,11 +2021,8 @@ bool EmulateInstructionMIPS64::Emulate_FP_branch(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
@@ -2080,11 +2057,8 @@ bool EmulateInstructionMIPS64::Emulate_BC1EQZ(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
@@ -2119,11 +2093,8 @@ bool EmulateInstructionMIPS64::Emulate_BC1NEZ(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
/*
@@ -2182,11 +2153,8 @@ bool EmulateInstructionMIPS64::Emulate_3D_branch(llvm::MCInst &insn) {
Context context;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_BNZB(llvm::MCInst &insn) {
@@ -2277,11 +2245,8 @@ bool EmulateInstructionMIPS64::Emulate_MSA_Branch_DF(llvm::MCInst &insn,
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_BNZV(llvm::MCInst &insn) {
@@ -2323,11 +2288,8 @@ bool EmulateInstructionMIPS64::Emulate_MSA_Branch_V(llvm::MCInst &insn,
Context context;
context.type = eContextRelativeBranchImmediate;
- if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
- target))
- return false;
-
- return true;
+ return WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_pc_mips64,
+ target);
}
bool EmulateInstructionMIPS64::Emulate_LDST_Imm(llvm::MCInst &insn) {
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
index c2433d59830e..e9783633ac7d 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
@@ -10,10 +10,6 @@
#ifndef EmulateInstructionMIPS64_h_
#define EmulateInstructionMIPS64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Utility/Status.h"
diff --git a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
index be65de9a5063..e9a1da6dd394 100644
--- a/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
+++ b/source/Plugins/Instruction/PPC64/EmulateInstructionPPC64.h
@@ -10,10 +10,6 @@
#ifndef EmulateInstructionPPC64_h_
#define EmulateInstructionPPC64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Interpreter/OptionValue.h"
#include "lldb/Utility/Log.h"
diff --git a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.h b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.h
index e9af5a6cdc74..1439f86e586f 100644
--- a/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.h
+++ b/source/Plugins/InstrumentationRuntime/ASan/ASanRuntime.h
@@ -10,10 +10,6 @@
#ifndef liblldb_AddressSanitizerRuntime_h_
#define liblldb_AddressSanitizerRuntime_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h
index dc737d22a67a..e6482d394efa 100644
--- a/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h
+++ b/source/Plugins/InstrumentationRuntime/TSan/TSanRuntime.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ThreadSanitizerRuntime_h_
#define liblldb_ThreadSanitizerRuntime_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
index 7ef3aecdb89f..3040b8b39052 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include "llvm/Support/MathExtras.h"
@@ -59,10 +58,9 @@ template <typename ptr_t> struct jit_descriptor {
namespace {
-PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"enable-jit-breakpoint", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr, "Enable breakpoint on __jit_debug_register_code."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {}, "Enable breakpoint on __jit_debug_register_code."}};
enum { ePropertyEnableJITBreakpoint };
@@ -316,7 +314,7 @@ bool JITLoaderGDB::ReadJITDescriptorImpl(bool all_entries) {
char jit_name[64];
snprintf(jit_name, 64, "JIT(0x%" PRIx64 ")", symbolfile_addr);
module_sp = m_process->ReadModuleFromMemory(
- FileSpec(jit_name, false), symbolfile_addr, symbolfile_size);
+ FileSpec(jit_name), symbolfile_addr, symbolfile_size);
if (module_sp && module_sp->GetObjectFile()) {
// load the symbol table right away
diff --git a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
index 6269860825db..a22016601293 100644
--- a/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
+++ b/source/Plugins/JITLoader/GDB/JITLoaderGDB.h
@@ -10,12 +10,8 @@
#ifndef liblldb_JITLoaderGDB_h_
#define liblldb_JITLoaderGDB_h_
-// C Includes
-// C++ Includes
#include <map>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/JITLoader.h"
#include "lldb/Target/Process.h"
diff --git a/source/Plugins/Language/CMakeLists.txt b/source/Plugins/Language/CMakeLists.txt
index 4b92a8ef866b..7869074566d1 100644
--- a/source/Plugins/Language/CMakeLists.txt
+++ b/source/Plugins/Language/CMakeLists.txt
@@ -1,6 +1,4 @@
+add_subdirectory(ClangCommon)
add_subdirectory(CPlusPlus)
-add_subdirectory(Go)
-add_subdirectory(Java)
add_subdirectory(ObjC)
add_subdirectory(ObjCPlusPlus)
-add_subdirectory(OCaml)
diff --git a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
index 82b7ac1675fa..40200503a8a7 100644
--- a/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
+++ b/source/Plugins/Language/CPlusPlus/BlockPointer.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "BlockPointer.h"
#include "lldb/Core/ValueObject.h"
@@ -89,7 +85,7 @@ public:
size_t CalculateNumChildren() override {
const bool omit_empty_base_classes = false;
- return m_block_struct_type.GetNumChildren(omit_empty_base_classes);
+ return m_block_struct_type.GetNumChildren(omit_empty_base_classes, nullptr);
}
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
diff --git a/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index 180440a244a4..bc357aa52b84 100644
--- a/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -9,13 +9,16 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibCxxInitializerList.cpp
LibCxxList.cpp
LibCxxMap.cpp
+ LibCxxOptional.cpp
LibCxxQueue.cpp
LibCxxTuple.cpp
LibCxxUnorderedMap.cpp
+ LibCxxVariant.cpp
LibCxxVector.cpp
LibStdcpp.cpp
LibStdcppTuple.cpp
LibStdcppUniquePointer.cpp
+ MSVCUndecoratedNameParser.cpp
LINK_LIBS
lldbCore
@@ -24,6 +27,8 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
lldbSymbol
lldbTarget
lldbUtility
+ lldbPluginClangCommon
+
LINK_COMPONENTS
Support
)
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 2c63e6467d4c..982b286d0f05 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -9,20 +9,17 @@
#include "CPlusPlusLanguage.h"
-// C Includes
#include <cctype>
#include <cstring>
-// C++ Includes
#include <functional>
#include <memory>
#include <mutex>
#include <set>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
+#include "llvm/Demangle/ItaniumDemangle.h"
-// Project includes
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/DataFormatters/CXXFunctionPointer.h"
@@ -30,7 +27,6 @@
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/DataFormatters/VectorType.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/FastDemangle.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
@@ -39,7 +35,9 @@
#include "CxxStringTypes.h"
#include "LibCxx.h"
#include "LibCxxAtomic.h"
+#include "LibCxxVariant.h"
#include "LibStdcpp.h"
+#include "MSVCUndecoratedNameParser.h"
using namespace lldb;
using namespace lldb_private;
@@ -143,10 +141,7 @@ static bool IsTrivialBasename(const llvm::StringRef &basename) {
}
// We processed all characters. It is a vaild basename.
- if (idx == basename.size())
- return true;
-
- return false;
+ return idx == basename.size();
}
bool CPlusPlusLanguage::MethodName::TrySimplifiedParse() {
@@ -251,19 +246,23 @@ std::string CPlusPlusLanguage::MethodName::GetScopeQualifiedName() {
bool CPlusPlusLanguage::IsCPPMangledName(const char *name) {
// FIXME!! we should really run through all the known C++ Language plugins
// and ask each one if this is a C++ mangled name
-
+
if (name == nullptr)
return false;
-
- // MSVC style mangling
+
+ // MSVC style mangling
if (name[0] == '?')
return true;
-
+
return (name[0] != '\0' && name[0] == '_' && name[1] == 'Z');
}
bool CPlusPlusLanguage::ExtractContextAndIdentifier(
const char *name, llvm::StringRef &context, llvm::StringRef &identifier) {
+ if (MSVCUndecoratedNameParser::IsMSVCUndecoratedName(name))
+ return MSVCUndecoratedNameParser::ExtractContextAndIdentifier(name, context,
+ identifier);
+
CPlusPlusNameParser parser(name);
if (auto full_name = parser.ParseAsFullName()) {
identifier = full_name.getValue().basename;
@@ -273,53 +272,89 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier(
return false;
}
-/// Given a mangled function `mangled`, replace all the primitive function type
-/// arguments of `search` with type `replace`.
-static ConstString SubsPrimitiveParmItanium(llvm::StringRef mangled,
- llvm::StringRef search,
- llvm::StringRef replace) {
- Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
-
- const size_t max_len =
- mangled.size() + mangled.count(search) * replace.size() + 1;
-
- // Make a temporary buffer to fix up the mangled parameter types and copy the
- // original there
- std::string output_buf;
- output_buf.reserve(max_len);
- output_buf.insert(0, mangled.str());
- ptrdiff_t replaced_offset = 0;
-
- auto swap_parms_hook = [&](const char *parsee) {
- if (!parsee || !*parsee)
- return;
-
- // Check whether we've found a substitutee
- llvm::StringRef s(parsee);
- if (s.startswith(search)) {
- // account for the case where a replacement is of a different length to
- // the original
- replaced_offset += replace.size() - search.size();
-
- ptrdiff_t replace_idx = (mangled.size() - s.size()) + replaced_offset;
- output_buf.erase(replace_idx, search.size());
- output_buf.insert(replace_idx, replace.str());
+namespace {
+class NodeAllocator {
+ llvm::BumpPtrAllocator Alloc;
+
+public:
+ void reset() { Alloc.Reset(); }
+
+ template <typename T, typename... Args> T *makeNode(Args &&... args) {
+ return new (Alloc.Allocate(sizeof(T), alignof(T)))
+ T(std::forward<Args>(args)...);
+ }
+
+ void *allocateNodeArray(size_t sz) {
+ return Alloc.Allocate(sizeof(llvm::itanium_demangle::Node *) * sz,
+ alignof(llvm::itanium_demangle::Node *));
+ }
+};
+
+/// Given a mangled function `Mangled`, replace all the primitive function type
+/// arguments of `Search` with type `Replace`.
+class TypeSubstitutor
+ : public llvm::itanium_demangle::AbstractManglingParser<TypeSubstitutor,
+ NodeAllocator> {
+ /// Input character until which we have constructed the respective output
+ /// already
+ const char *Written;
+
+ llvm::StringRef Search;
+ llvm::StringRef Replace;
+ llvm::SmallString<128> Result;
+
+ /// Whether we have performed any substitutions.
+ bool Substituted;
+
+ void reset(llvm::StringRef Mangled, llvm::StringRef Search,
+ llvm::StringRef Replace) {
+ AbstractManglingParser::reset(Mangled.begin(), Mangled.end());
+ Written = Mangled.begin();
+ this->Search = Search;
+ this->Replace = Replace;
+ Result.clear();
+ Substituted = false;
+ }
+
+ void appendUnchangedInput() {
+ Result += llvm::StringRef(Written, First - Written);
+ Written = First;
+ }
+
+public:
+ TypeSubstitutor() : AbstractManglingParser(nullptr, nullptr) {}
+
+ ConstString substitute(llvm::StringRef Mangled, llvm::StringRef From,
+ llvm::StringRef To) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
+
+ reset(Mangled, From, To);
+ if (parse() == nullptr) {
+ LLDB_LOG(log, "Failed to substitute mangling in {0}", Mangled);
+ return ConstString();
}
- };
+ if (!Substituted)
+ return ConstString();
- // FastDemangle will call our hook for each instance of a primitive type,
- // allowing us to perform substitution
- char *const demangled =
- FastDemangle(mangled.str().c_str(), mangled.size(), swap_parms_hook);
+ // Append any trailing unmodified input.
+ appendUnchangedInput();
+ LLDB_LOG(log, "Substituted mangling {0} -> {1}", Mangled, Result);
+ return ConstString(Result);
+ }
- if (log)
- log->Printf("substituted mangling for %s:{%s} %s:{%s}\n",
- mangled.str().c_str(), demangled, output_buf.c_str(),
- FastDemangle(output_buf.c_str()));
- // FastDemangle malloc'd this string.
- free(demangled);
+ llvm::itanium_demangle::Node *parseType() {
+ if (llvm::StringRef(First, numLeft()).startswith(Search)) {
+ // We found a match. Append unmodified input up to this point.
+ appendUnchangedInput();
- return output_buf == mangled ? ConstString() : ConstString(output_buf);
+ // And then perform the replacement.
+ Result += Replace;
+ Written += Search.size();
+ Substituted = true;
+ }
+ return AbstractManglingParser::parseType();
+ }
+};
}
uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
@@ -348,23 +383,24 @@ uint32_t CPlusPlusLanguage::FindAlternateFunctionManglings(
alternates.insert(ConstString(fixed_scratch));
}
+ TypeSubstitutor TS;
// `char` is implementation defined as either `signed` or `unsigned`. As a
// result a char parameter has 3 possible manglings: 'c'-char, 'a'-signed
// char, 'h'-unsigned char. If we're looking for symbols with a signed char
// parameter, try finding matches which have the general case 'c'.
if (ConstString char_fixup =
- SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "a", "c"))
+ TS.substitute(mangled_name.GetStringRef(), "a", "c"))
alternates.insert(char_fixup);
// long long parameter mangling 'x', may actually just be a long 'l' argument
if (ConstString long_fixup =
- SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "x", "l"))
+ TS.substitute(mangled_name.GetStringRef(), "x", "l"))
alternates.insert(long_fixup);
// unsigned long long parameter mangling 'y', may actually just be unsigned
// long 'm' argument
if (ConstString ulong_fixup =
- SubsPrimitiveParmItanium(mangled_name.GetStringRef(), "y", "m"))
+ TS.substitute(mangled_name.GetStringRef(), "y", "m"))
alternates.insert(ulong_fixup);
return alternates.size() - start_size;
@@ -385,8 +421,17 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
#ifndef LLDB_DISABLE_PYTHON
lldb::TypeSummaryImplSP std_string_summary_sp(new CXXFunctionSummaryFormat(
- stl_summary_flags, lldb_private::formatters::LibcxxStringSummaryProvider,
+ stl_summary_flags,
+ lldb_private::formatters::LibcxxStringSummaryProviderASCII,
"std::string summary provider"));
+ lldb::TypeSummaryImplSP std_stringu16_summary_sp(new CXXFunctionSummaryFormat(
+ stl_summary_flags,
+ lldb_private::formatters::LibcxxStringSummaryProviderUTF16,
+ "std::u16string summary provider"));
+ lldb::TypeSummaryImplSP std_stringu32_summary_sp(new CXXFunctionSummaryFormat(
+ stl_summary_flags,
+ lldb_private::formatters::LibcxxStringSummaryProviderUTF32,
+ "std::u32string summary provider"));
lldb::TypeSummaryImplSP std_wstring_summary_sp(new CXXFunctionSummaryFormat(
stl_summary_flags, lldb_private::formatters::LibcxxWStringSummaryProvider,
"std::wstring summary provider"));
@@ -400,6 +445,16 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::__1::allocator<char> >"),
std_string_summary_sp);
cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString(
+ "std::__1::basic_string<char16_t, std::__1::char_traits<char16_t>, "
+ "std::__1::allocator<char16_t> >"),
+ std_stringu16_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
+ ConstString(
+ "std::__1::basic_string<char32_t, std::__1::char_traits<char32_t>, "
+ "std::__1::allocator<char32_t> >"),
+ std_stringu32_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(
ConstString("std::__ndk1::basic_string<char, "
"std::__ndk1::char_traits<char>, "
"std::__ndk1::allocator<char> >"),
@@ -493,6 +548,14 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libc++ std::tuple synthetic children",
ConstString("^std::__(ndk)?1::tuple<.*>(( )?&)?$"), stl_synth_flags,
true);
+ AddCXXSynthetic(cpp_category_sp, LibcxxOptionalFrontEndCreator,
+ "libc++ std::optional synthetic children",
+ ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
+ stl_synth_flags, true);
+ AddCXXSynthetic(cpp_category_sp, LibcxxVariantFrontEndCreator,
+ "libc++ std::variant synthetic children",
+ ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
+ stl_synth_flags, true);
AddCXXSynthetic(
cpp_category_sp,
lldb_private::formatters::LibcxxAtomicSyntheticFrontEndCreator,
@@ -519,6 +582,11 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
ConstString("^(std::__(ndk)?1::)weak_ptr<.+>(( )?&)?$"), stl_synth_flags,
true);
+ AddCXXSummary(
+ cpp_category_sp, lldb_private::formatters::LibcxxFunctionSummaryProvider,
+ "libc++ std::function summary provider",
+ ConstString("^std::__(ndk)?1::function<.+>$"), stl_summary_flags, true);
+
stl_summary_flags.SetDontShowChildren(false);
stl_summary_flags.SetSkipPointers(false);
AddCXXSummary(cpp_category_sp,
@@ -584,6 +652,16 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
cpp_category_sp, lldb_private::formatters::LibCxxAtomicSummaryProvider,
"libc++ std::atomic summary provider",
ConstString("^std::__(ndk)?1::atomic<.+>$"), stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxOptionalSummaryProvider,
+ "libc++ std::optional summary provider",
+ ConstString("^std::__(ndk)?1::optional<.+>(( )?&)?$"),
+ stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::LibcxxVariantSummaryProvider,
+ "libc++ std::variant summary provider",
+ ConstString("^std::__(ndk)?1::variant<.+>(( )?&)?$"),
+ stl_summary_flags, true);
stl_summary_flags.SetSkipPointers(true);
@@ -610,11 +688,6 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"std::map iterator synthetic children",
ConstString("^std::__(ndk)?1::__map_iterator<.+>$"), stl_synth_flags,
true);
-
- AddCXXSynthetic(
- cpp_category_sp, lldb_private::formatters::LibcxxFunctionFrontEndCreator,
- "std::function synthetic value provider",
- ConstString("^std::__(ndk)?1::function<.+>$"), stl_synth_flags, true);
#endif
}
@@ -1002,3 +1075,16 @@ CPlusPlusLanguage::GetHardcodedSynthetics() {
return g_formatters;
}
+
+bool CPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
+ const auto suffixes = {".cpp", ".cxx", ".c++", ".cc", ".c",
+ ".h", ".hh", ".hpp", ".hxx", ".h++"};
+ for (auto suffix : suffixes) {
+ if (file_path.endswith_lower(suffix))
+ return true;
+ }
+
+ // Check if we're in a STL path (where the files usually have no extension
+ // that we could check for.
+ return file_path.contains("/usr/include/c++/");
+}
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 7380ef321305..3c8ca96e81f6 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -10,15 +10,12 @@
#ifndef liblldb_CPlusPlusLanguage_h_
#define liblldb_CPlusPlusLanguage_h_
-// C Includes
-// C++ Includes
#include <set>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
+#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
@@ -26,6 +23,8 @@
namespace lldb_private {
class CPlusPlusLanguage : public Language {
+ ClangHighlighter m_highlighter;
+
public:
class MethodName {
public:
@@ -90,6 +89,10 @@ public:
HardcodedFormatters::HardcodedSyntheticFinder
GetHardcodedSynthetics() override;
+ bool IsSourceFile(llvm::StringRef file_path) const override;
+
+ const Highlighter *GetHighlighter() const override { return &m_highlighter; }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
index fe1d46f32c17..d46a53a7a704 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.h
@@ -10,16 +10,12 @@
#ifndef liblldb_CPlusPlusNameParser_h_
#define liblldb_CPlusPlusNameParser_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
index 0f6fb54e8384..24185b314466 100644
--- a/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
+++ b/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp
@@ -100,8 +100,11 @@ bool lldb_private::formatters::WCharStringSummaryProvider(
if (!wchar_compiler_type)
return false;
- const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
- nullptr); // Safe to pass NULL for exe_scope here
+ // Safe to pass nullptr for exe_scope here.
+ llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ const uint32_t wchar_size = *size;
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(valobj_addr);
@@ -194,8 +197,11 @@ bool lldb_private::formatters::WCharSummaryProvider(
if (!wchar_compiler_type)
return false;
- const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
- nullptr); // Safe to pass NULL for exe_scope here
+ // Safe to pass nullptr for exe_scope here.
+ llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ const uint32_t wchar_size = *size;
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
options.SetData(data);
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.cpp b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
index 95e02a473cd7..7e8c06bd4c75 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxx.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.cpp
@@ -9,10 +9,7 @@
#include "LibCxx.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "llvm/ADT/ScopeExit.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/ValueObject.h"
@@ -22,7 +19,9 @@
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/DataFormatters/VectorIterator.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ProcessStructReader.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
@@ -33,6 +32,76 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+bool lldb_private::formatters::LibcxxOptionalSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+ if (!valobj_sp)
+ return false;
+
+ // An optional either contains a value or not, the member __engaged_ is
+ // a bool flag, it is true if the optional has a value and false otherwise.
+ ValueObjectSP engaged_sp(
+ valobj_sp->GetChildMemberWithName(ConstString("__engaged_"), true));
+
+ if (!engaged_sp)
+ return false;
+
+ llvm::StringRef engaged_as_cstring(
+ engaged_sp->GetValueAsUnsigned(0) == 1 ? "true" : "false");
+
+ stream.Printf(" Has Value=%s ", engaged_as_cstring.data());
+
+ return true;
+}
+
+bool lldb_private::formatters::LibcxxFunctionSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+
+ if (!valobj_sp)
+ return false;
+
+ ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == nullptr)
+ return false;
+
+ CPPLanguageRuntime *cpp_runtime = process->GetCPPLanguageRuntime();
+
+ if (!cpp_runtime)
+ return false;
+
+ CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
+ cpp_runtime->FindLibCppStdFunctionCallableInfo(valobj_sp);
+
+ switch (callable_info.callable_case) {
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Invalid:
+ stream.Printf(" __f_ = %" PRIu64, callable_info.member__f_pointer_value);
+ return false;
+ break;
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::Lambda:
+ stream.Printf(
+ " Lambda in File %s at Line %u",
+ callable_info.callable_line_entry.file.GetFilename().GetCString(),
+ callable_info.callable_line_entry.line);
+ break;
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::CallableObject:
+ stream.Printf(
+ " Function in File %s at Line %u",
+ callable_info.callable_line_entry.file.GetFilename().GetCString(),
+ callable_info.callable_line_entry.line);
+ break;
+ case CPPLanguageRuntime::LibCppStdFunctionCallableCase::FreeOrMemberFunction:
+ stream.Printf(" Function = %s ",
+ callable_info.callable_symbol.GetName().GetCString());
+ break;
+ }
+
+ return true;
+}
+
bool lldb_private::formatters::LibcxxSmartPointerSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
@@ -120,9 +189,9 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
if (!valobj_sp)
return false;
-
+
static ConstString g___i_("__i_");
-
+
// this must be a ValueObject* because it is a child of the ValueObject we
// are producing children for it if were a ValueObjectSP, we would end up
// with a loop (iterator -> synthetic -> child -> parent == iterator) and
@@ -156,37 +225,53 @@ bool lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEnd::Update() {
m_pair_ptr = nullptr;
return false;
}
- CompilerType pair_type(__i_->GetCompilerType().GetTypeTemplateArgument(0));
- std::string name; uint64_t bit_offset_ptr; uint32_t bitfield_bit_size_ptr; bool is_bitfield_ptr;
- pair_type = pair_type.GetFieldAtIndex(0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
+ CompilerType pair_type(
+ __i_->GetCompilerType().GetTypeTemplateArgument(0));
+ std::string name;
+ uint64_t bit_offset_ptr;
+ uint32_t bitfield_bit_size_ptr;
+ bool is_bitfield_ptr;
+ pair_type = pair_type.GetFieldAtIndex(
+ 0, name, &bit_offset_ptr, &bitfield_bit_size_ptr, &is_bitfield_ptr);
if (!pair_type) {
m_pair_ptr = nullptr;
return false;
}
-
+
auto addr(m_pair_ptr->GetValueAsUnsigned(LLDB_INVALID_ADDRESS));
m_pair_ptr = nullptr;
- if (addr && addr!=LLDB_INVALID_ADDRESS) {
- ClangASTContext *ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
+ if (addr && addr != LLDB_INVALID_ADDRESS) {
+ ClangASTContext *ast_ctx =
+ llvm::dyn_cast_or_null<ClangASTContext>(pair_type.GetTypeSystem());
if (!ast_ctx)
return false;
- CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(ConstString(), {
- {"ptr0",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
- {"ptr1",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
- {"ptr2",ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
- {"cw",ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
- {"payload",pair_type}
- });
- DataBufferSP buffer_sp(new DataBufferHeap(tree_node_type.GetByteSize(nullptr),0));
+ CompilerType tree_node_type = ast_ctx->CreateStructForIdentifier(
+ ConstString(),
+ {{"ptr0",
+ ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+ {"ptr1",
+ ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+ {"ptr2",
+ ast_ctx->GetBasicType(lldb::eBasicTypeVoid).GetPointerType()},
+ {"cw", ast_ctx->GetBasicType(lldb::eBasicTypeBool)},
+ {"payload", pair_type}});
+ llvm::Optional<uint64_t> size = tree_node_type.GetByteSize(nullptr);
+ if (!size)
+ return false;
+ DataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
ProcessSP process_sp(target_sp->GetProcessSP());
Status error;
- process_sp->ReadMemory(addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), error);
+ process_sp->ReadMemory(addr, buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize(), error);
if (error.Fail())
return false;
- DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize());
- auto pair_sp = CreateValueObjectFromData("pair", extractor, valobj_sp->GetExecutionContextRef(), tree_node_type);
+ DataExtractor extractor(buffer_sp, process_sp->GetByteOrder(),
+ process_sp->GetAddressByteSize());
+ auto pair_sp = CreateValueObjectFromData(
+ "pair", extractor, valobj_sp->GetExecutionContextRef(),
+ tree_node_type);
if (pair_sp)
- m_pair_sp = pair_sp->GetChildAtIndex(4,true);
+ m_pair_sp = pair_sp->GetChildAtIndex(4, true);
}
}
}
@@ -491,6 +576,8 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
->GetScratchClangASTContext()
->GetBasicType(lldb::eBasicTypeWChar)
.GetByteSize(nullptr);
+ if (!wchar_t_size)
+ return false;
options.SetData(extractor);
options.SetStream(&stream);
@@ -499,7 +586,7 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
options.SetSourceSize(size);
options.SetBinaryZeroIsTerminator(false);
- switch (wchar_t_size) {
+ switch (*wchar_t_size) {
case 1:
StringPrinter::ReadBufferAndDumpToStream<
lldb_private::formatters::StringPrinter::StringElementType::UTF8>(
@@ -526,9 +613,10 @@ bool lldb_private::formatters::LibcxxWStringSummaryProvider(
return true;
}
-bool lldb_private::formatters::LibcxxStringSummaryProvider(
- ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &summary_options) {
+template <StringPrinter::StringElementType element_type>
+bool LibcxxStringSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options,
+ std::string prefix_token = "") {
uint64_t size = 0;
ValueObjectSP location_sp;
@@ -557,31 +645,37 @@ bool lldb_private::formatters::LibcxxStringSummaryProvider(
options.SetData(extractor);
options.SetStream(&stream);
- options.SetPrefixToken(nullptr);
+
+ if (prefix_token.empty())
+ options.SetPrefixToken(nullptr);
+ else
+ options.SetPrefixToken(prefix_token);
+
options.SetQuote('"');
options.SetSourceSize(size);
options.SetBinaryZeroIsTerminator(false);
- StringPrinter::ReadBufferAndDumpToStream<
- StringPrinter::StringElementType::ASCII>(options);
+ StringPrinter::ReadBufferAndDumpToStream<element_type>(options);
return true;
}
-class LibcxxFunctionFrontEnd : public SyntheticValueProviderFrontEnd {
-public:
- LibcxxFunctionFrontEnd(ValueObject &backend)
- : SyntheticValueProviderFrontEnd(backend) {}
+bool lldb_private::formatters::LibcxxStringSummaryProviderASCII(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return LibcxxStringSummaryProvider<StringPrinter::StringElementType::ASCII>(
+ valobj, stream, summary_options);
+}
- lldb::ValueObjectSP GetSyntheticValue() override {
- static ConstString g___f_("__f_");
- return m_backend.GetChildMemberWithName(g___f_, true);
- }
-};
+bool lldb_private::formatters::LibcxxStringSummaryProviderUTF16(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return LibcxxStringSummaryProvider<StringPrinter::StringElementType::UTF16>(
+ valobj, stream, summary_options, "u");
+}
-SyntheticChildrenFrontEnd *
-lldb_private::formatters::LibcxxFunctionFrontEndCreator(
- CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- if (valobj_sp)
- return new LibcxxFunctionFrontEnd(*valobj_sp);
- return nullptr;
+bool lldb_private::formatters::LibcxxStringSummaryProviderUTF32(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return LibcxxStringSummaryProvider<StringPrinter::StringElementType::UTF32>(
+ valobj, stream, summary_options, "U");
}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxx.h b/source/Plugins/Language/CPlusPlus/LibCxx.h
index 3f6e0d6e14d7..224a540eda04 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxx.h
+++ b/source/Plugins/Language/CPlusPlus/LibCxx.h
@@ -19,19 +19,35 @@
namespace lldb_private {
namespace formatters {
-bool LibcxxStringSummaryProvider(
+bool LibcxxStringSummaryProviderASCII(
ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options); // libc++ std::string
+ const TypeSummaryOptions &summary_options); // libc++ std::string
+
+bool LibcxxStringSummaryProviderUTF16(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options); // libc++ std::u16string
+
+bool LibcxxStringSummaryProviderUTF32(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options); // libc++ std::u32string
bool LibcxxWStringSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // libc++ std::wstring
+bool LibcxxOptionalSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::optional<>
+
bool LibcxxSmartPointerSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions
&options); // libc++ std::shared_ptr<> and std::weak_ptr<>
+bool LibcxxFunctionSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::function<>
+
SyntheticChildrenFrontEnd *
LibcxxVectorBoolSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
@@ -124,15 +140,20 @@ SyntheticChildrenFrontEnd *
LibcxxInitializerListSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
-SyntheticChildrenFrontEnd *LibcxxFunctionFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP);
-
SyntheticChildrenFrontEnd *LibcxxQueueFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
SyntheticChildrenFrontEnd *LibcxxTupleFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP);
+SyntheticChildrenFrontEnd *
+LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
+
+SyntheticChildrenFrontEnd *
+LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
+
} // namespace formatters
} // namespace lldb_private
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
index 0cdb0b26cf3b..489ac4d96072 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxBitset.cpp
@@ -79,17 +79,24 @@ ValueObjectSP BitsetFrontEnd::GetChildAtIndex(size_t idx) {
CompilerType type;
ValueObjectSP chunk;
// For small bitsets __first_ is not an array, but a plain size_t.
- if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr))
- chunk = m_first->GetChildAtIndex(
- idx / type.GetBitSize(ctx.GetBestExecutionContextScope()), true);
- else {
+ if (m_first->GetCompilerType().IsArrayType(&type, nullptr, nullptr)) {
+ llvm::Optional<uint64_t> bit_size =
+ type.GetBitSize(ctx.GetBestExecutionContextScope());
+ if (!bit_size || *bit_size == 0)
+ return {};
+ chunk = m_first->GetChildAtIndex(idx / *bit_size, true);
+ } else {
type = m_first->GetCompilerType();
chunk = m_first;
}
if (!type || !chunk)
- return ValueObjectSP();
+ return {};
- size_t chunk_idx = idx % type.GetBitSize(ctx.GetBestExecutionContextScope());
+ llvm::Optional<uint64_t> bit_size =
+ type.GetBitSize(ctx.GetBestExecutionContextScope());
+ if (!bit_size || *bit_size == 0)
+ return {};
+ size_t chunk_idx = idx % *bit_size;
uint8_t value = !!(chunk->GetValueAsUnsigned(0) & (uint64_t(1) << chunk_idx));
DataExtractor data(&value, sizeof(value), m_byte_order, m_byte_size);
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
index 5823f6f3e038..390483d02668 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxInitializerList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
@@ -98,12 +94,11 @@ bool lldb_private::formatters::LibcxxInitializerListSyntheticFrontEnd::
if (!m_element_type.IsValid())
return false;
- m_element_size = m_element_type.GetByteSize(nullptr);
-
- if (m_element_size > 0)
- m_start =
- m_backend.GetChildMemberWithName(g___begin_, true)
- .get(); // store raw pointers or end up with a circular dependency
+ if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
+ m_element_size = *size;
+ // Store raw pointers or end up with a circular dependency.
+ m_start = m_backend.GetChildMemberWithName(g___begin_, true).get();
+ }
return false;
}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
index 6066f14b18cc..81606b573cea 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
index 8f82bdcbfd59..429569d57928 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp
new file mode 100644
index 000000000000..762b824f262a
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxOptional.cpp
@@ -0,0 +1,85 @@
+//===-- LibCxxOptional.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxx.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+class OptionalFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ OptionalFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
+ Update();
+ }
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override {
+ return formatters::ExtractIndexFromString(name.GetCString());
+ }
+
+ bool MightHaveChildren() override { return true; }
+ bool Update() override;
+ size_t CalculateNumChildren() override { return m_size; }
+ ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+private:
+ size_t m_size = 0;
+ ValueObjectSP m_base_sp;
+};
+} // namespace
+
+bool OptionalFrontEnd::Update() {
+ ValueObjectSP engaged_sp(
+ m_backend.GetChildMemberWithName(ConstString("__engaged_"), true));
+
+ if (!engaged_sp)
+ return false;
+
+ // __engaged_ is a bool flag and is true if the optional contains a value.
+ // Converting it to unsigned gives us a size of 1 if it contains a value
+ // and 0 if not.
+ m_size = engaged_sp->GetValueAsUnsigned(0);
+
+ return false;
+}
+
+ValueObjectSP OptionalFrontEnd::GetChildAtIndex(size_t idx) {
+ if (idx >= m_size)
+ return ValueObjectSP();
+
+ // __val_ contains the underlying value of an optional if it has one.
+ // Currently because it is part of an anonymous union GetChildMemberWithName()
+ // does not peer through and find it unless we are at the parent itself.
+ // We can obtain the parent through __engaged_.
+ ValueObjectSP val_sp(
+ m_backend.GetChildMemberWithName(ConstString("__engaged_"), true)
+ ->GetParent()
+ ->GetChildAtIndex(0, true)
+ ->GetChildMemberWithName(ConstString("__val_"), true));
+
+ if (!val_sp)
+ return ValueObjectSP();
+
+ CompilerType holder_type = val_sp->GetCompilerType();
+
+ if (!holder_type)
+ return ValueObjectSP();
+
+ return val_sp->Clone(ConstString(llvm::formatv("Value").str()));
+}
+
+SyntheticChildrenFrontEnd *
+formatters::LibcxxOptionalFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp) {
+ if (valobj_sp)
+ return new OptionalFrontEnd(*valobj_sp);
+ return nullptr;
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
index 0f1c2537d651..51ae8cb3184c 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxUnorderedMap.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
new file mode 100644
index 000000000000..e874616c3251
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.cpp
@@ -0,0 +1,256 @@
+//===-- LibCxxVariant.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LibCxxVariant.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/ScopeExit.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// libc++ variant implementation contains two members that we care about both
+// are contained in the __impl member.
+// - __index which tells us which of the variadic template types is the active
+// type for the variant
+// - __data is a variadic union which recursively contains itself as member
+// which refers to the tailing variadic types.
+// - __head which refers to the leading non pack type
+// - __value refers to the actual value contained
+// - __tail which refers to the remaining pack types
+//
+// e.g. given std::variant<int,double,char> v1
+//
+// (lldb) frame var -R v1.__impl.__data
+//(... __union<... 0, int, double, char>) v1.__impl.__data = {
+// ...
+// __head = {
+// __value = ...
+// }
+// __tail = {
+// ...
+// __head = {
+// __value = ...
+// }
+// __tail = {
+// ...
+// __head = {
+// __value = ...
+// ...
+//
+// So given
+// - __index equal to 0 the active value is contained in
+//
+// __data.__head.__value
+//
+// - __index equal to 1 the active value is contained in
+//
+// __data.__tail.__head.__value
+//
+// - __index equal to 2 the active value is contained in
+//
+// __data.__tail.__tail.__head.__value
+//
+
+namespace {
+// libc++ std::variant index could have one of three states
+// 1) VALID, we can obtain it and its not variant_npos
+// 2) INVALID, we can't obtain it or it is not a type we expect
+// 3) NPOS, its value is variant_npos which means the variant has no value
+enum class LibcxxVariantIndexValidity { VALID, INVALID, NPOS };
+
+LibcxxVariantIndexValidity
+LibcxxVariantGetIndexValidity(ValueObjectSP &impl_sp) {
+ ValueObjectSP index_sp(
+ impl_sp->GetChildMemberWithName(ConstString("__index"), true));
+
+ if (!index_sp)
+ return LibcxxVariantIndexValidity::INVALID;
+
+ int64_t index_value = index_sp->GetValueAsSigned(0);
+
+ if (index_value == -1)
+ return LibcxxVariantIndexValidity::NPOS;
+
+ return LibcxxVariantIndexValidity::VALID;
+}
+
+llvm::Optional<uint64_t> LibcxxVariantIndexValue(ValueObjectSP &impl_sp) {
+ ValueObjectSP index_sp(
+ impl_sp->GetChildMemberWithName(ConstString("__index"), true));
+
+ if (!index_sp)
+ return {};
+
+ return {index_sp->GetValueAsUnsigned(0)};
+}
+
+ValueObjectSP LibcxxVariantGetNthHead(ValueObjectSP &impl_sp, uint64_t index) {
+ ValueObjectSP data_sp(
+ impl_sp->GetChildMemberWithName(ConstString("__data"), true));
+
+ if (!data_sp)
+ return ValueObjectSP{};
+
+ ValueObjectSP current_level = data_sp;
+ for (uint64_t n = index; n != 0; --n) {
+ ValueObjectSP tail_sp(
+ current_level->GetChildMemberWithName(ConstString("__tail"), true));
+
+ if (!tail_sp)
+ return ValueObjectSP{};
+
+ current_level = tail_sp;
+ }
+
+ return current_level->GetChildMemberWithName(ConstString("__head"), true);
+}
+} // namespace
+
+namespace lldb_private {
+namespace formatters {
+bool LibcxxVariantSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options) {
+ ValueObjectSP valobj_sp(valobj.GetNonSyntheticValue());
+ if (!valobj_sp)
+ return false;
+
+ ValueObjectSP impl_sp(
+ valobj_sp->GetChildMemberWithName(ConstString("__impl"), true));
+
+ if (!impl_sp)
+ return false;
+
+ LibcxxVariantIndexValidity validity = LibcxxVariantGetIndexValidity(impl_sp);
+
+ if (validity == LibcxxVariantIndexValidity::INVALID)
+ return false;
+
+ if (validity == LibcxxVariantIndexValidity::NPOS) {
+ stream.Printf(" No Value");
+ return true;
+ }
+
+ auto optional_index_value = LibcxxVariantIndexValue(impl_sp);
+
+ if (!optional_index_value)
+ return false;
+
+ uint64_t index_value = *optional_index_value;
+
+ ValueObjectSP nth_head = LibcxxVariantGetNthHead(impl_sp, index_value);
+
+ if (!nth_head)
+ return false;
+
+ CompilerType head_type = nth_head->GetCompilerType();
+
+ if (!head_type)
+ return false;
+
+ CompilerType template_type = head_type.GetTypeTemplateArgument(1);
+
+ if (!template_type)
+ return false;
+
+ stream.Printf(" Active Type = %s ", template_type.GetTypeName().GetCString());
+
+ return true;
+}
+} // namespace formatters
+} // namespace lldb_private
+
+namespace {
+class VariantFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ VariantFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {
+ Update();
+ }
+
+ size_t GetIndexOfChildWithName(const ConstString &name) override {
+ return formatters::ExtractIndexFromString(name.GetCString());
+ }
+
+ bool MightHaveChildren() override { return true; }
+ bool Update() override;
+ size_t CalculateNumChildren() override { return m_size; }
+ ValueObjectSP GetChildAtIndex(size_t idx) override;
+
+private:
+ size_t m_size = 0;
+ ValueObjectSP m_base_sp;
+};
+} // namespace
+
+bool VariantFrontEnd::Update() {
+ m_size = 0;
+ ValueObjectSP impl_sp(
+ m_backend.GetChildMemberWithName(ConstString("__impl"), true));
+ if (!impl_sp)
+ return false;
+
+ LibcxxVariantIndexValidity validity = LibcxxVariantGetIndexValidity(impl_sp);
+
+ if (validity == LibcxxVariantIndexValidity::INVALID)
+ return false;
+
+ if (validity == LibcxxVariantIndexValidity::NPOS)
+ return true;
+
+ m_size = 1;
+
+ return false;
+}
+
+ValueObjectSP VariantFrontEnd::GetChildAtIndex(size_t idx) {
+ if (idx >= m_size)
+ return ValueObjectSP();
+
+ ValueObjectSP impl_sp(
+ m_backend.GetChildMemberWithName(ConstString("__impl"), true));
+
+ auto optional_index_value = LibcxxVariantIndexValue(impl_sp);
+
+ if (!optional_index_value)
+ return ValueObjectSP();
+
+ uint64_t index_value = *optional_index_value;
+
+ ValueObjectSP nth_head = LibcxxVariantGetNthHead(impl_sp, index_value);
+
+ if (!nth_head)
+ return ValueObjectSP();
+
+ CompilerType head_type = nth_head->GetCompilerType();
+
+ if (!head_type)
+ return ValueObjectSP();
+
+ CompilerType template_type = head_type.GetTypeTemplateArgument(1);
+
+ if (!template_type)
+ return ValueObjectSP();
+
+ ValueObjectSP head_value(
+ nth_head->GetChildMemberWithName(ConstString("__value"), true));
+
+ if (!head_value)
+ return ValueObjectSP();
+
+ return head_value->Clone(ConstString(ConstString("Value").AsCString()));
+}
+
+SyntheticChildrenFrontEnd *
+formatters::LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp) {
+ if (valobj_sp)
+ return new VariantFrontEnd(*valobj_sp);
+ return nullptr;
+}
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVariant.h b/source/Plugins/Language/CPlusPlus/LibCxxVariant.h
new file mode 100644
index 000000000000..04834581963f
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVariant.h
@@ -0,0 +1,31 @@
+//===-- LibCxxVariant.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_LibCxxVariant_h_
+#define liblldb_LibCxxVariant_h_
+
+#include "lldb/Core/ValueObject.h"
+#include "lldb/DataFormatters/TypeSummary.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+#include "lldb/Utility/Stream.h"
+
+namespace lldb_private {
+namespace formatters {
+bool LibcxxVariantSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // libc++ std::variant<>
+
+SyntheticChildrenFrontEnd *LibcxxVariantFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP);
+
+} // namespace formatters
+} // namespace lldb_private
+
+#endif // liblldb_LibCxxVariant_h_
diff --git a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
index 711130639cd2..ed405c875174 100644
--- a/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibCxxVector.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LibCxx.h"
#include "lldb/Core/ValueObject.h"
@@ -149,14 +145,16 @@ bool lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update() {
if (!data_type_finder_sp)
return false;
m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
- m_element_size = m_element_type.GetByteSize(nullptr);
-
- if (m_element_size > 0) {
- // store raw pointers or end up with a circular dependency
- m_start =
- m_backend.GetChildMemberWithName(ConstString("__begin_"), true).get();
- m_finish =
- m_backend.GetChildMemberWithName(ConstString("__end_"), true).get();
+ if (llvm::Optional<uint64_t> size = m_element_type.GetByteSize(nullptr)) {
+ m_element_size = *size;
+
+ if (m_element_size > 0) {
+ // store raw pointers or end up with a circular dependency
+ m_start =
+ m_backend.GetChildMemberWithName(ConstString("__begin_"), true).get();
+ m_finish =
+ m_backend.GetChildMemberWithName(ConstString("__end_"), true).get();
+ }
}
return false;
}
@@ -196,27 +194,29 @@ lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEnd::GetChildAtIndex(
if (iter != end)
return iter->second;
if (idx >= m_count)
- return ValueObjectSP();
+ return {};
if (m_base_data_address == 0 || m_count == 0)
- return ValueObjectSP();
+ return {};
if (!m_bool_type)
- return ValueObjectSP();
+ return {};
size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
lldb::addr_t byte_location = m_base_data_address + byte_idx;
ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
if (!process_sp)
- return ValueObjectSP();
+ return {};
uint8_t byte = 0;
uint8_t mask = 0;
Status err;
size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
if (err.Fail() || bytes_read == 0)
- return ValueObjectSP();
+ return {};
mask = 1 << bit_index;
bool bit_set = ((byte & mask) != 0);
- DataBufferSP buffer_sp(
- new DataBufferHeap(m_bool_type.GetByteSize(nullptr), 0));
+ llvm::Optional<uint64_t> size = m_bool_type.GetByteSize(nullptr);
+ if (!size)
+ return {};
+ DataBufferSP buffer_sp(new DataBufferHeap(*size, 0));
if (bit_set && buffer_sp && buffer_sp->GetBytes()) {
// regardless of endianness, anything non-zero is true
*(buffer_sp->GetBytes()) = 1;
diff --git a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 3e2b7159f894..695371fc3992 100644
--- a/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -9,10 +9,6 @@
#include "LibStdcpp.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/StringPrinter.h"
@@ -301,8 +297,11 @@ bool lldb_private::formatters::LibStdcppWStringSummaryProvider(
if (!wchar_compiler_type)
return false;
- const uint32_t wchar_size = wchar_compiler_type.GetBitSize(
- nullptr); // Safe to pass NULL for exe_scope here
+ // Safe to pass nullptr for exe_scope here.
+ llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ const uint32_t wchar_size = *size;
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
Status error;
diff --git a/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp
new file mode 100644
index 000000000000..84f03e0e3016
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.cpp
@@ -0,0 +1,99 @@
+//===-- MSVCUndecoratedNameParser.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MSVCUndecoratedNameParser.h"
+
+#include <stack>
+
+MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) {
+ std::size_t last_base_start = 0;
+
+ std::stack<std::size_t> stack;
+ unsigned int open_angle_brackets = 0;
+ for (size_t i = 0; i < name.size(); i++) {
+ switch (name[i]) {
+ case '<':
+ // Do not treat `operator<' and `operator<<' as templates
+ // (sometimes they represented as `<' and `<<' in the name).
+ if (i == last_base_start ||
+ (i == last_base_start + 1 && name[last_base_start] == '<'))
+ break;
+
+ stack.push(i);
+ open_angle_brackets++;
+
+ break;
+ case '>':
+ if (!stack.empty() && name[stack.top()] == '<') {
+ open_angle_brackets--;
+ stack.pop();
+ }
+
+ break;
+ case '`':
+ stack.push(i);
+
+ break;
+ case '\'':
+ while (!stack.empty()) {
+ std::size_t top = stack.top();
+ if (name[top] == '<')
+ open_angle_brackets--;
+
+ stack.pop();
+
+ if (name[top] == '`')
+ break;
+ }
+
+ break;
+ case ':':
+ if (open_angle_brackets)
+ break;
+ if (i == 0 || name[i - 1] != ':')
+ break;
+
+ m_specifiers.emplace_back(name.take_front(i - 1),
+ name.slice(last_base_start, i - 1));
+
+ last_base_start = i + 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ m_specifiers.emplace_back(name, name.drop_front(last_base_start));
+}
+
+bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) {
+ return name.find('`') != llvm::StringRef::npos;
+}
+
+bool MSVCUndecoratedNameParser::ExtractContextAndIdentifier(
+ llvm::StringRef name, llvm::StringRef &context,
+ llvm::StringRef &identifier) {
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+ std::size_t count = specs.size();
+ identifier = count > 0 ? specs[count - 1].GetBaseName() : "";
+ context = count > 1 ? specs[count - 2].GetFullName() : "";
+
+ return count;
+}
+
+llvm::StringRef MSVCUndecoratedNameParser::DropScope(llvm::StringRef name) {
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+ if (specs.empty())
+ return "";
+
+ return specs[specs.size() - 1].GetBaseName();
+}
diff --git a/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h
new file mode 100644
index 000000000000..0c49100d8d49
--- /dev/null
+++ b/source/Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h
@@ -0,0 +1,51 @@
+//===-- MSVCUndecoratedNameParser.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_MSVCUndecoratedNameParser_h_
+#define liblldb_MSVCUndecoratedNameParser_h_
+
+#include <vector>
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+
+class MSVCUndecoratedNameSpecifier {
+public:
+ MSVCUndecoratedNameSpecifier(llvm::StringRef full_name,
+ llvm::StringRef base_name)
+ : m_full_name(full_name), m_base_name(base_name) {}
+
+ llvm::StringRef GetFullName() const { return m_full_name; }
+ llvm::StringRef GetBaseName() const { return m_base_name; }
+
+private:
+ llvm::StringRef m_full_name;
+ llvm::StringRef m_base_name;
+};
+
+class MSVCUndecoratedNameParser {
+public:
+ explicit MSVCUndecoratedNameParser(llvm::StringRef name);
+
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> GetSpecifiers() const {
+ return m_specifiers;
+ }
+
+ static bool IsMSVCUndecoratedName(llvm::StringRef name);
+ static bool ExtractContextAndIdentifier(llvm::StringRef name,
+ llvm::StringRef &context,
+ llvm::StringRef &identifier);
+
+ static llvm::StringRef DropScope(llvm::StringRef name);
+
+private:
+ std::vector<MSVCUndecoratedNameSpecifier> m_specifiers;
+};
+
+#endif
diff --git a/source/Plugins/Language/ClangCommon/CMakeLists.txt b/source/Plugins/Language/ClangCommon/CMakeLists.txt
new file mode 100644
index 000000000000..854320dd312e
--- /dev/null
+++ b/source/Plugins/Language/ClangCommon/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_lldb_library(lldbPluginClangCommon PLUGIN
+ ClangHighlighter.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+)
diff --git a/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp b/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
new file mode 100644
index 000000000000..1fe8482263eb
--- /dev/null
+++ b/source/Plugins/Language/ClangCommon/ClangHighlighter.cpp
@@ -0,0 +1,237 @@
+//===-- ClangHighlighter.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangHighlighter.h"
+
+#include "lldb/Target/Language.h"
+#include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/StreamString.h"
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Lexer.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+using namespace lldb_private;
+
+bool ClangHighlighter::isKeyword(llvm::StringRef token) const {
+ return keywords.find(token) != keywords.end();
+}
+
+ClangHighlighter::ClangHighlighter() {
+#define KEYWORD(X, N) keywords.insert(#X);
+#include "clang/Basic/TokenKinds.def"
+}
+
+/// Determines which style should be applied to the given token.
+/// \param highlighter
+/// The current highlighter that should use the style.
+/// \param token
+/// The current token.
+/// \param tok_str
+/// The string in the source code the token represents.
+/// \param options
+/// The style we use for coloring the source code.
+/// \param in_pp_directive
+/// If we are currently in a preprocessor directive. NOTE: This is
+/// passed by reference and will be updated if the current token starts
+/// or ends a preprocessor directive.
+/// \return
+/// The ColorStyle that should be applied to the token.
+static HighlightStyle::ColorStyle
+determineClangStyle(const ClangHighlighter &highlighter,
+ const clang::Token &token, llvm::StringRef tok_str,
+ const HighlightStyle &options, bool &in_pp_directive) {
+ using namespace clang;
+
+ if (token.is(tok::comment)) {
+ // If we were in a preprocessor directive before, we now left it.
+ in_pp_directive = false;
+ return options.comment;
+ } else if (in_pp_directive || token.getKind() == tok::hash) {
+ // Let's assume that the rest of the line is a PP directive.
+ in_pp_directive = true;
+ // Preprocessor directives are hard to match, so we have to hack this in.
+ return options.pp_directive;
+ } else if (tok::isStringLiteral(token.getKind()))
+ return options.string_literal;
+ else if (tok::isLiteral(token.getKind()))
+ return options.scalar_literal;
+ else if (highlighter.isKeyword(tok_str))
+ return options.keyword;
+ else
+ switch (token.getKind()) {
+ case tok::raw_identifier:
+ case tok::identifier:
+ return options.identifier;
+ case tok::l_brace:
+ case tok::r_brace:
+ return options.braces;
+ case tok::l_square:
+ case tok::r_square:
+ return options.square_brackets;
+ case tok::l_paren:
+ case tok::r_paren:
+ return options.parentheses;
+ case tok::comma:
+ return options.comma;
+ case tok::coloncolon:
+ case tok::colon:
+ return options.colon;
+
+ case tok::amp:
+ case tok::ampamp:
+ case tok::ampequal:
+ case tok::star:
+ case tok::starequal:
+ case tok::plus:
+ case tok::plusplus:
+ case tok::plusequal:
+ case tok::minus:
+ case tok::arrow:
+ case tok::minusminus:
+ case tok::minusequal:
+ case tok::tilde:
+ case tok::exclaim:
+ case tok::exclaimequal:
+ case tok::slash:
+ case tok::slashequal:
+ case tok::percent:
+ case tok::percentequal:
+ case tok::less:
+ case tok::lessless:
+ case tok::lessequal:
+ case tok::lesslessequal:
+ case tok::spaceship:
+ case tok::greater:
+ case tok::greatergreater:
+ case tok::greaterequal:
+ case tok::greatergreaterequal:
+ case tok::caret:
+ case tok::caretequal:
+ case tok::pipe:
+ case tok::pipepipe:
+ case tok::pipeequal:
+ case tok::question:
+ case tok::equal:
+ case tok::equalequal:
+ return options.operators;
+ default:
+ break;
+ }
+ return HighlightStyle::ColorStyle();
+}
+
+void ClangHighlighter::Highlight(const HighlightStyle &options,
+ llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines,
+ Stream &result) const {
+ using namespace clang;
+
+ FileSystemOptions file_opts;
+ FileManager file_mgr(file_opts);
+
+ unsigned line_number = previous_lines.count('\n') + 1U;
+
+ // Let's build the actual source code Clang needs and setup some utility
+ // objects.
+ std::string full_source = previous_lines.str() + line.str();
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> diag_ids(new DiagnosticIDs());
+ llvm::IntrusiveRefCntPtr<DiagnosticOptions> diags_opts(
+ new DiagnosticOptions());
+ DiagnosticsEngine diags(diag_ids, diags_opts);
+ clang::SourceManager SM(diags, file_mgr);
+ auto buf = llvm::MemoryBuffer::getMemBuffer(full_source);
+
+ FileID FID = SM.createFileID(clang::SourceManager::Unowned, buf.get());
+
+ // Let's just enable the latest ObjC and C++ which should get most tokens
+ // right.
+ LangOptions Opts;
+ Opts.ObjC = true;
+ // FIXME: This should probably set CPlusPlus, CPlusPlus11, ... too
+ Opts.CPlusPlus17 = true;
+ Opts.LineComment = true;
+
+ Lexer lex(FID, buf.get(), SM, Opts);
+ // The lexer should keep whitespace around.
+ lex.SetKeepWhitespaceMode(true);
+
+ // Keeps track if we have entered a PP directive.
+ bool in_pp_directive = false;
+
+ // True once we actually lexed the user provided line.
+ bool found_user_line = false;
+
+ // True if we already highlighted the token under the cursor, false otherwise.
+ bool highlighted_cursor = false;
+ Token token;
+ bool exit = false;
+ while (!exit) {
+ // Returns true if this is the last token we get from the lexer.
+ exit = lex.LexFromRawLexer(token);
+
+ bool invalid = false;
+ unsigned current_line_number =
+ SM.getSpellingLineNumber(token.getLocation(), &invalid);
+ if (current_line_number != line_number)
+ continue;
+ found_user_line = true;
+
+ // We don't need to print any tokens without a spelling line number.
+ if (invalid)
+ continue;
+
+ // Same as above but with the column number.
+ invalid = false;
+ unsigned start = SM.getSpellingColumnNumber(token.getLocation(), &invalid);
+ if (invalid)
+ continue;
+ // Column numbers start at 1, but indexes in our string start at 0.
+ --start;
+
+ // Annotations don't have a length, so let's skip them.
+ if (token.isAnnotation())
+ continue;
+
+ // Extract the token string from our source code.
+ llvm::StringRef tok_str = line.substr(start, token.getLength());
+
+ // If the token is just an empty string, we can skip all the work below.
+ if (tok_str.empty())
+ continue;
+
+ // If the cursor is inside this token, we have to apply the 'selected'
+ // highlight style before applying the actual token color.
+ llvm::StringRef to_print = tok_str;
+ StreamString storage;
+ auto end = start + token.getLength();
+ if (cursor_pos && end > *cursor_pos && !highlighted_cursor) {
+ highlighted_cursor = true;
+ options.selected.Apply(storage, tok_str);
+ to_print = storage.GetString();
+ }
+
+ // See how we are supposed to highlight this token.
+ HighlightStyle::ColorStyle color =
+ determineClangStyle(*this, token, tok_str, options, in_pp_directive);
+
+ color.Apply(result, to_print);
+ }
+
+ // If we went over the whole file but couldn't find our own file, then
+ // somehow our setup was wrong. When we're in release mode we just give the
+ // user the normal line and pretend we don't know how to highlight it. In
+ // debug mode we bail out with an assert as this should never happen.
+ if (!found_user_line) {
+ result << line;
+ assert(false && "We couldn't find the user line in the input file?");
+ }
+}
diff --git a/source/Plugins/Language/ClangCommon/ClangHighlighter.h b/source/Plugins/Language/ClangCommon/ClangHighlighter.h
new file mode 100644
index 000000000000..579c4315228f
--- /dev/null
+++ b/source/Plugins/Language/ClangCommon/ClangHighlighter.h
@@ -0,0 +1,38 @@
+//===-- ClangHighlighter.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_ClangHighlighter_h_
+#define liblldb_ClangHighlighter_h_
+
+#include "lldb/Utility/Stream.h"
+#include "llvm/ADT/StringSet.h"
+
+#include "lldb/Core/Highlighter.h"
+
+namespace lldb_private {
+
+class ClangHighlighter : public Highlighter {
+ llvm::StringSet<> keywords;
+
+public:
+ ClangHighlighter();
+ llvm::StringRef GetName() const override { return "clang"; }
+
+ void Highlight(const HighlightStyle &options, llvm::StringRef line,
+ llvm::Optional<size_t> cursor_pos,
+ llvm::StringRef previous_lines, Stream &s) const override;
+
+ /// Returns true if the given string represents a keywords in any Clang
+ /// supported language.
+ bool isKeyword(llvm::StringRef token) const;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangHighlighter_h_
diff --git a/source/Plugins/Language/Go/CMakeLists.txt b/source/Plugins/Language/Go/CMakeLists.txt
deleted file mode 100644
index 793e417a618a..000000000000
--- a/source/Plugins/Language/Go/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-add_lldb_library(lldbPluginGoLanguage PLUGIN
- GoLanguage.cpp
- GoFormatterFunctions.cpp
-
- LINK_LIBS
- clangAST
- lldbCore
- lldbDataFormatters
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
-)
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.cpp b/source/Plugins/Language/Go/GoFormatterFunctions.cpp
deleted file mode 100644
index aac75205c6ef..000000000000
--- a/source/Plugins/Language/Go/GoFormatterFunctions.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
-//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-#include <map>
-
-// Other libraries and framework includes
-// Project includes
-#include "GoFormatterFunctions.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/DataFormatters/StringPrinter.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-namespace {
-class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
-public:
- GoSliceSyntheticFrontEnd(ValueObject &valobj)
- : SyntheticChildrenFrontEnd(valobj) {
- Update();
- }
-
- ~GoSliceSyntheticFrontEnd() override = default;
-
- size_t CalculateNumChildren() override { return m_len; }
-
- lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
- if (idx < m_len) {
- ValueObjectSP &cached = m_children[idx];
- if (!cached) {
- StreamString idx_name;
- idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- lldb::addr_t object_at_idx = m_base_data_address;
- object_at_idx += idx * m_type.GetByteSize(nullptr);
- cached = CreateValueObjectFromAddress(
- idx_name.GetString(), object_at_idx,
- m_backend.GetExecutionContextRef(), m_type);
- }
- return cached;
- }
- return ValueObjectSP();
- }
-
- bool Update() override {
- size_t old_count = m_len;
-
- ConstString array_const_str("array");
- ValueObjectSP array_sp =
- m_backend.GetChildMemberWithName(array_const_str, true);
- if (!array_sp) {
- m_children.clear();
- return old_count == 0;
- }
- m_type = array_sp->GetCompilerType().GetPointeeType();
- m_base_data_address = array_sp->GetPointerValue();
-
- ConstString len_const_str("len");
- ValueObjectSP len_sp =
- m_backend.GetChildMemberWithName(len_const_str, true);
- if (len_sp) {
- m_len = len_sp->GetValueAsUnsigned(0);
- m_children.clear();
- }
-
- return old_count == m_len;
- }
-
- bool MightHaveChildren() override { return true; }
-
- size_t GetIndexOfChildWithName(const ConstString &name) override {
- return ExtractIndexFromString(name.AsCString());
- }
-
-private:
- CompilerType m_type;
- lldb::addr_t m_base_data_address;
- size_t m_len;
- std::map<size_t, lldb::ValueObjectSP> m_children;
-};
-
-} // anonymous namespace
-
-bool lldb_private::formatters::GoStringSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- if (valobj.IsPointerType()) {
- Status err;
- ValueObjectSP deref = valobj.Dereference(err);
- if (!err.Success())
- return false;
- return GoStringSummaryProvider(*deref, stream, opts);
- }
-
- ConstString str_name("str");
- ConstString len_name("len");
-
- ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true);
- ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true);
- if (!data_sp || !len_sp)
- return false;
- bool success;
- lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success);
-
- if (!success)
- return false;
-
- uint64_t length = len_sp->GetValueAsUnsigned(0);
- if (length == 0) {
- stream.Printf("\"\"");
- return true;
- }
-
- StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(valobj_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetSourceSize(length);
- options.SetNeedsZeroTermination(false);
- options.SetLanguage(eLanguageTypeGo);
-
- if (!StringPrinter::ReadStringAndDumpToStream<
- StringPrinter::StringElementType::UTF8>(options)) {
- stream.Printf("Summary Unavailable");
- return true;
- }
-
- return true;
-}
-
-SyntheticChildrenFrontEnd *
-lldb_private::formatters::GoSliceSyntheticFrontEndCreator(
- CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- if (!valobj_sp)
- return nullptr;
-
- lldb::ProcessSP process_sp(valobj_sp->GetProcessSP());
- if (!process_sp)
- return nullptr;
- return new GoSliceSyntheticFrontEnd(*valobj_sp);
-}
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.h b/source/Plugins/Language/Go/GoFormatterFunctions.h
deleted file mode 100644
index 1bf1892d6669..000000000000
--- a/source/Plugins/Language/Go/GoFormatterFunctions.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===-- GoFormatterFunctions.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_GoFormatterFunctions_h_
-#define liblldb_GoFormatterFunctions_h_
-
-// C Includes
-#include <stdint.h>
-#include <time.h>
-
-// C++ Includes
-// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-
-// Project includes
-#include "lldb/lldb-forward.h"
-
-#include "lldb/DataFormatters/FormatClasses.h"
-#include "lldb/DataFormatters/TypeSynthetic.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/ConstString.h"
-
-namespace lldb_private {
-namespace formatters {
-
-bool GoStringSummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options);
-
-SyntheticChildrenFrontEnd *
-GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP);
-
-} // namespace formatters
-} // namespace lldb_private
-
-#endif // liblldb_GoFormatterFunctions_h_
diff --git a/source/Plugins/Language/Go/GoLanguage.cpp b/source/Plugins/Language/Go/GoLanguage.cpp
deleted file mode 100644
index 66b4530abc76..000000000000
--- a/source/Plugins/Language/Go/GoLanguage.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-//===-- GoLanguage.cpp ------------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <string.h>
-// C++ Includes
-#include <functional>
-#include <mutex>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Threading.h"
-
-// Project includes
-#include "GoLanguage.h"
-#include "Plugins/Language/Go/GoFormatterFunctions.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Utility/ConstString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-void GoLanguage::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language",
- CreateInstance);
-}
-
-void GoLanguage::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString GoLanguage::GetPluginNameStatic() {
- static ConstString g_name("Go");
- return g_name;
-}
-
-//------------------------------------------------------------------
-// PluginInterface protocol
-//------------------------------------------------------------------
-lldb_private::ConstString GoLanguage::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t GoLanguage::GetPluginVersion() { return 1; }
-
-//------------------------------------------------------------------
-// Static Functions
-//------------------------------------------------------------------
-Language *GoLanguage::CreateInstance(lldb::LanguageType language) {
- if (language == eLanguageTypeGo)
- return new GoLanguage();
- return nullptr;
-}
-
-HardcodedFormatters::HardcodedSummaryFinder
-GoLanguage::GetHardcodedSummaries() {
- static llvm::once_flag g_initialize;
- static HardcodedFormatters::HardcodedSummaryFinder g_formatters;
-
- llvm::call_once(g_initialize, []() -> void {
- g_formatters.push_back(
- [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
- FormatManager &) -> TypeSummaryImpl::SharedPointer {
- static CXXFunctionSummaryFormat::SharedPointer formatter_sp(
- new CXXFunctionSummaryFormat(
- TypeSummaryImpl::Flags().SetDontShowChildren(true),
- lldb_private::formatters::GoStringSummaryProvider,
- "Go string summary provider"));
- if (GoASTContext::IsGoString(valobj.GetCompilerType())) {
- return formatter_sp;
- }
- if (GoASTContext::IsGoString(
- valobj.GetCompilerType().GetPointeeType())) {
- return formatter_sp;
- }
- return nullptr;
- });
- g_formatters.push_back(
- [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
- FormatManager &) -> TypeSummaryImpl::SharedPointer {
- static lldb::TypeSummaryImplSP formatter_sp(new StringSummaryFormat(
- TypeSummaryImpl::Flags().SetHideItemNames(true),
- "(len ${var.len}, cap ${var.cap})"));
- if (GoASTContext::IsGoSlice(valobj.GetCompilerType())) {
- return formatter_sp;
- }
- if (GoASTContext::IsGoSlice(
- valobj.GetCompilerType().GetPointeeType())) {
- return formatter_sp;
- }
- return nullptr;
- });
- });
- return g_formatters;
-}
-
-HardcodedFormatters::HardcodedSyntheticFinder
-GoLanguage::GetHardcodedSynthetics() {
- static llvm::once_flag g_initialize;
- static HardcodedFormatters::HardcodedSyntheticFinder g_formatters;
-
- llvm::call_once(g_initialize, []() -> void {
- g_formatters.push_back(
- [](lldb_private::ValueObject &valobj, lldb::DynamicValueType,
- FormatManager &fmt_mgr) -> SyntheticChildren::SharedPointer {
- static CXXSyntheticChildren::SharedPointer formatter_sp(
- new CXXSyntheticChildren(
- SyntheticChildren::Flags(), "slice synthetic children",
- lldb_private::formatters::GoSliceSyntheticFrontEndCreator));
- if (GoASTContext::IsGoSlice(valobj.GetCompilerType())) {
- return formatter_sp;
- }
- return nullptr;
- });
- });
-
- return g_formatters;
-}
diff --git a/source/Plugins/Language/Go/GoLanguage.h b/source/Plugins/Language/Go/GoLanguage.h
deleted file mode 100644
index ebec1d7205fa..000000000000
--- a/source/Plugins/Language/Go/GoLanguage.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- GoLanguage.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_GoLanguage_h_
-#define liblldb_GoLanguage_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "lldb/Target/Language.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class GoLanguage : public Language {
-public:
- GoLanguage() = default;
-
- ~GoLanguage() override = default;
-
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeGo;
- }
-
- HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries() override;
-
- HardcodedFormatters::HardcodedSyntheticFinder
- GetHardcodedSynthetics() override;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::Language *CreateInstance(lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_GoLanguage_h_
diff --git a/source/Plugins/Language/Java/CMakeLists.txt b/source/Plugins/Language/Java/CMakeLists.txt
deleted file mode 100644
index f0cbcd8d3f59..000000000000
--- a/source/Plugins/Language/Java/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-add_lldb_library(lldbPluginJavaLanguage PLUGIN
- JavaFormatterFunctions.cpp
- JavaLanguage.cpp
-
- LINK_LIBS
- lldbCore
- lldbDataFormatters
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
-)
diff --git a/source/Plugins/Language/Java/JavaFormatterFunctions.cpp b/source/Plugins/Language/Java/JavaFormatterFunctions.cpp
deleted file mode 100644
index 498795c90be8..000000000000
--- a/source/Plugins/Language/Java/JavaFormatterFunctions.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//===-- JavaFormatterFunctions.cpp-------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "JavaFormatterFunctions.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/DataFormatters/StringPrinter.h"
-#include "lldb/Symbol/JavaASTContext.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-namespace {
-
-class JavaArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd {
-public:
- JavaArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
- : SyntheticChildrenFrontEnd(*valobj_sp) {
- if (valobj_sp)
- Update();
- }
-
- size_t CalculateNumChildren() override {
- ValueObjectSP valobj = GetDereferencedValueObject();
- if (!valobj)
- return 0;
-
- CompilerType type = valobj->GetCompilerType();
- uint32_t size = JavaASTContext::CalculateArraySize(type, *valobj);
- if (size == UINT32_MAX)
- return 0;
- return size;
- }
-
- lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
- ValueObjectSP valobj = GetDereferencedValueObject();
- if (!valobj)
- return nullptr;
-
- ProcessSP process_sp = valobj->GetProcessSP();
- if (!process_sp)
- return nullptr;
-
- CompilerType type = valobj->GetCompilerType();
- CompilerType element_type = type.GetArrayElementType();
- lldb::addr_t address =
- valobj->GetAddressOf() +
- JavaASTContext::CalculateArrayElementOffset(type, idx);
-
- Status error;
- size_t byte_size = element_type.GetByteSize(nullptr);
- DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0));
- size_t bytes_read = process_sp->ReadMemory(address, buffer_sp->GetBytes(),
- byte_size, error);
- if (error.Fail() || byte_size != bytes_read)
- return nullptr;
-
- StreamString name;
- name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- DataExtractor data(buffer_sp, process_sp->GetByteOrder(),
- process_sp->GetAddressByteSize());
- return CreateValueObjectFromData(
- name.GetString(), data, valobj->GetExecutionContextRef(), element_type);
- }
-
- bool Update() override { return false; }
-
- bool MightHaveChildren() override { return true; }
-
- size_t GetIndexOfChildWithName(const ConstString &name) override {
- return ExtractIndexFromString(name.GetCString());
- }
-
-private:
- ValueObjectSP GetDereferencedValueObject() {
- if (!m_backend.IsPointerOrReferenceType())
- return m_backend.GetSP();
-
- Status error;
- return m_backend.Dereference(error);
- }
-};
-
-} // end of anonymous namespace
-
-bool lldb_private::formatters::JavaStringSummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) {
- if (valobj.IsPointerOrReferenceType()) {
- Status error;
- ValueObjectSP deref = valobj.Dereference(error);
- if (error.Fail())
- return false;
- return JavaStringSummaryProvider(*deref, stream, opts);
- }
-
- ProcessSP process_sp = valobj.GetProcessSP();
- if (!process_sp)
- return false;
-
- ConstString data_name("value");
- ConstString length_name("count");
-
- ValueObjectSP length_sp = valobj.GetChildMemberWithName(length_name, true);
- ValueObjectSP data_sp = valobj.GetChildMemberWithName(data_name, true);
- if (!data_sp || !length_sp)
- return false;
-
- bool success = false;
- uint64_t length = length_sp->GetValueAsUnsigned(0, &success);
- if (!success)
- return false;
-
- if (length == 0) {
- stream.Printf("\"\"");
- return true;
- }
- lldb::addr_t valobj_addr = data_sp->GetAddressOf();
-
- StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
- options.SetLocation(valobj_addr);
- options.SetProcessSP(process_sp);
- options.SetStream(&stream);
- options.SetSourceSize(length);
- options.SetNeedsZeroTermination(false);
- options.SetLanguage(eLanguageTypeJava);
-
- if (StringPrinter::ReadStringAndDumpToStream<
- StringPrinter::StringElementType::UTF16>(options))
- return true;
-
- stream.Printf("Summary Unavailable");
- return true;
-}
-
-bool lldb_private::formatters::JavaArraySummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
- if (valobj.IsPointerOrReferenceType()) {
- Status error;
- ValueObjectSP deref = valobj.Dereference(error);
- if (error.Fail())
- return false;
- return JavaArraySummaryProvider(*deref, stream, options);
- }
-
- CompilerType type = valobj.GetCompilerType();
- uint32_t size = JavaASTContext::CalculateArraySize(type, valobj);
- if (size == UINT32_MAX)
- return false;
- stream.Printf("[%u]{...}", size);
- return true;
-}
-
-SyntheticChildrenFrontEnd *
-lldb_private::formatters::JavaArraySyntheticFrontEndCreator(
- CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
- return valobj_sp ? new JavaArraySyntheticFrontEnd(valobj_sp) : nullptr;
-}
diff --git a/source/Plugins/Language/Java/JavaFormatterFunctions.h b/source/Plugins/Language/Java/JavaFormatterFunctions.h
deleted file mode 100644
index d1983429529c..000000000000
--- a/source/Plugins/Language/Java/JavaFormatterFunctions.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===-- JavaFormatterFunctions.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_JavaFormatterFunctions_h_
-#define liblldb_JavaFormatterFunctions_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-forward.h"
-
-namespace lldb_private {
-namespace formatters {
-
-bool JavaStringSummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options);
-
-bool JavaArraySummaryProvider(ValueObject &valobj, Stream &stream,
- const TypeSummaryOptions &options);
-
-SyntheticChildrenFrontEnd *
-JavaArraySyntheticFrontEndCreator(CXXSyntheticChildren *,
- lldb::ValueObjectSP valobj_sp);
-
-} // namespace formatters
-} // namespace lldb_private
-
-#endif // liblldb_JavaFormatterFunctions_h_
diff --git a/source/Plugins/Language/Java/JavaLanguage.cpp b/source/Plugins/Language/Java/JavaLanguage.cpp
deleted file mode 100644
index b17862f0b6a2..000000000000
--- a/source/Plugins/Language/Java/JavaLanguage.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-//===-- JavaLanguage.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <string.h>
-// C++ Includes
-#include <functional>
-#include <mutex>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Threading.h"
-
-// Project includes
-#include "JavaFormatterFunctions.h"
-#include "JavaLanguage.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/JavaASTContext.h"
-#include "lldb/Utility/ConstString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-using namespace lldb_private::formatters;
-
-void JavaLanguage::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java Language",
- CreateInstance);
-}
-
-void JavaLanguage::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString JavaLanguage::GetPluginNameStatic() {
- static ConstString g_name("Java");
- return g_name;
-}
-
-lldb_private::ConstString JavaLanguage::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t JavaLanguage::GetPluginVersion() { return 1; }
-
-Language *JavaLanguage::CreateInstance(lldb::LanguageType language) {
- if (language == eLanguageTypeJava)
- return new JavaLanguage();
- return nullptr;
-}
-
-bool JavaLanguage::IsNilReference(ValueObject &valobj) {
- if (!valobj.GetCompilerType().IsReferenceType())
- return false;
-
- // If we failed to read the value then it is not a nil reference.
- return valobj.GetValueAsUnsigned(UINT64_MAX) == 0;
-}
-
-lldb::TypeCategoryImplSP JavaLanguage::GetFormatters() {
- static llvm::once_flag g_initialize;
- static TypeCategoryImplSP g_category;
-
- llvm::call_once(g_initialize, [this]() -> void {
- DataVisualization::Categories::GetCategory(GetPluginName(), g_category);
- if (g_category) {
- llvm::StringRef array_regexp("^.*\\[\\]&?$");
-
- lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat(
- TypeSummaryImpl::Flags().SetDontShowChildren(true),
- lldb_private::formatters::JavaStringSummaryProvider,
- "java.lang.String summary provider"));
- g_category->GetTypeSummariesContainer()->Add(
- ConstString("java::lang::String"), string_summary_sp);
-
- lldb::TypeSummaryImplSP array_summary_sp(new CXXFunctionSummaryFormat(
- TypeSummaryImpl::Flags().SetDontShowChildren(true),
- lldb_private::formatters::JavaArraySummaryProvider,
- "Java array summary provider"));
- g_category->GetRegexTypeSummariesContainer()->Add(
- RegularExpressionSP(new RegularExpression(array_regexp)),
- array_summary_sp);
-
-#ifndef LLDB_DISABLE_PYTHON
- AddCXXSynthetic(
- g_category,
- lldb_private::formatters::JavaArraySyntheticFrontEndCreator,
- "Java array synthetic children", ConstString(array_regexp),
- SyntheticChildren::Flags().SetCascades(true), true);
-#endif
- }
- });
- return g_category;
-}
diff --git a/source/Plugins/Language/Java/JavaLanguage.h b/source/Plugins/Language/Java/JavaLanguage.h
deleted file mode 100644
index 5b652502a3d1..000000000000
--- a/source/Plugins/Language/Java/JavaLanguage.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===-- JavaLanguage.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_JavaLanguage_h_
-#define liblldb_JavaLanguage_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "lldb/Target/Language.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class JavaLanguage : public Language {
-public:
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeJava;
- }
-
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::Language *CreateInstance(lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- bool IsNilReference(ValueObject &valobj) override;
-
- lldb::TypeCategoryImplSP GetFormatters() override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_JavaLanguage_h_
diff --git a/source/Plugins/Language/OCaml/CMakeLists.txt b/source/Plugins/Language/OCaml/CMakeLists.txt
deleted file mode 100644
index e779ae2acd08..000000000000
--- a/source/Plugins/Language/OCaml/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-add_lldb_library(lldbPluginOCamlLanguage PLUGIN
- OCamlLanguage.cpp
-
- LINK_LIBS
- lldbCore
- lldbDataFormatters
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
-)
-
diff --git a/source/Plugins/Language/OCaml/OCamlLanguage.cpp b/source/Plugins/Language/OCaml/OCamlLanguage.cpp
deleted file mode 100644
index ec24a36fe8f3..000000000000
--- a/source/Plugins/Language/OCaml/OCamlLanguage.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- OCamlLanguage.cpp ----------------------------------------*- C++
-//-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <string.h>
-// C++ Includes
-#include <functional>
-#include <mutex>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "OCamlLanguage.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/DataFormatters/DataVisualization.h"
-#include "lldb/DataFormatters/FormattersHelpers.h"
-#include "lldb/Symbol/OCamlASTContext.h"
-#include "lldb/Utility/ConstString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-void OCamlLanguage::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "OCaml Language",
- CreateInstance);
-}
-
-void OCamlLanguage::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString OCamlLanguage::GetPluginNameStatic() {
- static ConstString g_name("OCaml");
- return g_name;
-}
-
-lldb_private::ConstString OCamlLanguage::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t OCamlLanguage::GetPluginVersion() { return 1; }
-
-Language *OCamlLanguage::CreateInstance(lldb::LanguageType language) {
- if (language == eLanguageTypeOCaml)
- return new OCamlLanguage();
- return nullptr;
-}
-
-bool OCamlLanguage::IsNilReference(ValueObject &valobj) {
- if (!valobj.GetCompilerType().IsReferenceType())
- return false;
-
- // If we failed to read the value then it is not a nil reference.
- return valobj.GetValueAsUnsigned(UINT64_MAX) == 0;
-}
diff --git a/source/Plugins/Language/OCaml/OCamlLanguage.h b/source/Plugins/Language/OCaml/OCamlLanguage.h
deleted file mode 100644
index 21837fe5add4..000000000000
--- a/source/Plugins/Language/OCaml/OCamlLanguage.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===-- OCamlLanguage.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_OCamlLanguage_h_
-#define liblldb_OCamlLanguage_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-
-// Other libraries and framework includes
-#include "llvm/ADT/StringRef.h"
-
-// Project includes
-#include "lldb/Target/Language.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class OCamlLanguage : public Language {
-public:
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeOCaml;
- }
-
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::Language *CreateInstance(lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- bool IsNilReference(ValueObject &valobj) override;
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_OCamlLanguage_h_
diff --git a/source/Plugins/Language/ObjC/CF.cpp b/source/Plugins/Language/ObjC/CF.cpp
index 9bb8eeab1d2e..e3dab5a1442d 100644
--- a/source/Plugins/Language/ObjC/CF.cpp
+++ b/source/Plugins/Language/ObjC/CF.cpp
@@ -149,7 +149,7 @@ bool lldb_private::formatters::CFBitVectorSummaryProvider(
}
}
- if (is_type_ok == false)
+ if (!is_type_ok)
return false;
Status error;
diff --git a/source/Plugins/Language/ObjC/CMakeLists.txt b/source/Plugins/Language/ObjC/CMakeLists.txt
index 95ace3a3633a..afb68d4de831 100644
--- a/source/Plugins/Language/ObjC/CMakeLists.txt
+++ b/source/Plugins/Language/ObjC/CMakeLists.txt
@@ -31,6 +31,7 @@ add_lldb_library(lldbPluginObjCLanguage PLUGIN
lldbTarget
lldbUtility
lldbPluginAppleObjCRuntime
+ lldbPluginClangCommon
EXTRA_CXXFLAGS ${EXTRA_CXXFLAGS}
)
diff --git a/source/Plugins/Language/ObjC/Cocoa.cpp b/source/Plugins/Language/ObjC/Cocoa.cpp
index 8f278fc2d513..48085378939e 100644
--- a/source/Plugins/Language/ObjC/Cocoa.cpp
+++ b/source/Plugins/Language/ObjC/Cocoa.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/Mangled.h"
@@ -746,6 +742,59 @@ bool lldb_private::formatters::NSURLSummaryProvider(
return false;
}
+/// Bias value for tagged pointer exponents.
+/// Recommended values:
+/// 0x3e3: encodes all dates between distantPast and distantFuture
+/// except for the range within about 1e-28 second of the reference date.
+/// 0x3ef: encodes all dates for a few million years beyond distantPast and
+/// distantFuture, except within about 1e-25 second of the reference date.
+const int TAGGED_DATE_EXPONENT_BIAS = 0x3ef;
+
+typedef union {
+ struct {
+ uint64_t fraction:52; // unsigned
+ uint64_t exponent:11; // signed
+ uint64_t sign:1;
+ };
+ uint64_t i;
+ double d;
+} DoubleBits;
+typedef union {
+ struct {
+ uint64_t fraction:52; // unsigned
+ uint64_t exponent:7; // signed
+ uint64_t sign:1;
+ uint64_t unused:4; // placeholder for pointer tag bits
+ };
+ uint64_t i;
+} TaggedDoubleBits;
+
+static uint64_t decodeExponent(uint64_t exp) {
+ // Tagged exponent field is 7-bit signed. Sign-extend the value to 64 bits
+ // before performing arithmetic.
+ return llvm::SignExtend64<7>(exp) + TAGGED_DATE_EXPONENT_BIAS;
+}
+
+static uint64_t decodeTaggedTimeInterval(uint64_t encodedTimeInterval) {
+ if (encodedTimeInterval == 0)
+ return 0.0;
+ if (encodedTimeInterval == std::numeric_limits<uint64_t>::max())
+ return (uint64_t)-0.0;
+
+ TaggedDoubleBits encodedBits = {};
+ encodedBits.i = encodedTimeInterval;
+ DoubleBits decodedBits;
+
+ // Sign and fraction are represented exactly.
+ // Exponent is encoded.
+ assert(encodedBits.unused == 0);
+ decodedBits.sign = encodedBits.sign;
+ decodedBits.fraction = encodedBits.fraction;
+ decodedBits.exponent = decodeExponent(encodedBits.exponent);
+
+ return decodedBits.d;
+}
+
bool lldb_private::formatters::NSDateSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
ProcessSP process_sp = valobj.GetProcessSP();
@@ -785,9 +834,9 @@ bool lldb_private::formatters::NSDateSummaryProvider(
if (class_name.IsEmpty())
return false;
+ uint64_t info_bits = 0, value_bits = 0;
if ((class_name == g_NSDate) || (class_name == g___NSDate) ||
(class_name == g___NSTaggedDate)) {
- uint64_t info_bits = 0, value_bits = 0;
if (descriptor->GetTaggedPointerInfo(&info_bits, &value_bits)) {
date_value_bits = ((value_bits << 8) | (info_bits << 4));
memcpy(&date_value, &date_value_bits, sizeof(date_value_bits));
@@ -817,6 +866,14 @@ bool lldb_private::formatters::NSDateSummaryProvider(
stream.Printf("0001-12-30 00:00:00 +0000");
return true;
}
+
+ // Accomodate for the __NSTaggedDate format introduced in Foundation 1600.
+ if (class_name == g___NSTaggedDate) {
+ auto *runtime = llvm::dyn_cast_or_null<AppleObjCRuntime>(process_sp->GetObjCLanguageRuntime());
+ if (runtime && runtime->GetFoundationVersion() >= 1600)
+ date_value = decodeTaggedTimeInterval(value_bits << 4);
+ }
+
// this snippet of code assumes that time_t == seconds since Jan-1-1970 this
// is generally true and POSIXly happy, but might break if a library vendor
// decides to get creative
diff --git a/source/Plugins/Language/ObjC/NSArray.cpp b/source/Plugins/Language/ObjC/NSArray.cpp
index f6d159201951..6c110da9ecc2 100644
--- a/source/Plugins/Language/ObjC/NSArray.cpp
+++ b/source/Plugins/Language/ObjC/NSArray.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
-// Project includes
#include "Cocoa.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
@@ -218,6 +214,25 @@ namespace Foundation1437 {
}
+namespace CallStackArray {
+struct DataDescriptor_32 {
+ uint32_t _data;
+ uint32_t _used;
+ uint32_t _offset;
+ const uint32_t _size = 0;
+};
+
+struct DataDescriptor_64 {
+ uint64_t _data;
+ uint64_t _used;
+ uint64_t _offset;
+ const uint64_t _size = 0;
+};
+
+using NSCallStackArraySyntheticFrontEnd =
+ GenericNSArrayMSyntheticFrontEnd<DataDescriptor_32, DataDescriptor_64>;
+} // namespace CallStackArray
+
template <typename D32, typename D64, bool Inline>
class GenericNSArrayISyntheticFrontEnd : public SyntheticChildrenFrontEnd {
public:
@@ -368,6 +383,7 @@ bool lldb_private::formatters::NSArraySummaryProvider(
static const ConstString g_NSArrayCF("__NSCFArray");
static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
+ static const ConstString g_NSCallStackArray("_NSCallStackArray");
if (class_name.IsEmpty())
return false;
@@ -417,7 +433,9 @@ bool lldb_private::formatters::NSArraySummaryProvider(
value = 0;
} else if (class_name == g_NSArray1) {
value = 1;
- } else if (class_name == g_NSArrayCF) {
+ } else if (class_name == g_NSArrayCF || class_name == g_NSCallStackArray) {
+ // __NSCFArray and _NSCallStackArray store the number of elements as a
+ // pointer-sized value at offset `2 * ptr_size`.
Status error;
value = process_sp->ReadUnsignedIntegerFromMemory(
valobj_addr + 2 * ptr_size, ptr_size, 0, error);
@@ -817,6 +835,7 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
static const ConstString g_NSArray1("__NSSingleObjectArrayI");
static const ConstString g_NSArrayMLegacy("__NSArrayM_Legacy");
static const ConstString g_NSArrayMImmutable("__NSArrayM_Immutable");
+ static const ConstString g_NSCallStackArray("_NSCallStackArray");
if (class_name.IsEmpty())
return nullptr;
@@ -846,6 +865,8 @@ lldb_private::formatters::NSArraySyntheticFrontEndCreator(
return (new Foundation1010::NSArrayMSyntheticFrontEnd(valobj_sp));
else
return (new Foundation109::NSArrayMSyntheticFrontEnd(valobj_sp));
+ } else if (class_name == g_NSCallStackArray) {
+ return (new CallStackArray::NSCallStackArraySyntheticFrontEnd(valobj_sp));
} else {
auto &map(NSArray_Additionals::GetAdditionalSynthetics());
auto iter = map.find(class_name), end = map.end();
diff --git a/source/Plugins/Language/ObjC/NSDictionary.cpp b/source/Plugins/Language/ObjC/NSDictionary.cpp
index 5be051b46bd6..9a7fc2bd97cb 100644
--- a/source/Plugins/Language/ObjC/NSDictionary.cpp
+++ b/source/Plugins/Language/ObjC/NSDictionary.cpp
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"
-// Project includes
#include "NSDictionary.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
diff --git a/source/Plugins/Language/ObjC/NSError.cpp b/source/Plugins/Language/ObjC/NSError.cpp
index 77721e2db326..975bda5179f2 100644
--- a/source/Plugins/Language/ObjC/NSError.cpp
+++ b/source/Plugins/Language/ObjC/NSError.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
diff --git a/source/Plugins/Language/ObjC/NSException.cpp b/source/Plugins/Language/ObjC/NSException.cpp
index c6970efae4d3..2404ef9d1003 100644
--- a/source/Plugins/Language/ObjC/NSException.cpp
+++ b/source/Plugins/Language/ObjC/NSException.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/DeclCXX.h"
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
@@ -33,52 +29,78 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-bool lldb_private::formatters::NSException_SummaryProvider(
- ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+static bool ExtractFields(ValueObject &valobj, ValueObjectSP *name_sp,
+ ValueObjectSP *reason_sp, ValueObjectSP *userinfo_sp,
+ ValueObjectSP *reserved_sp) {
ProcessSP process_sp(valobj.GetProcessSP());
if (!process_sp)
return false;
- lldb::addr_t ptr_value = LLDB_INVALID_ADDRESS;
+ lldb::addr_t ptr = LLDB_INVALID_ADDRESS;
CompilerType valobj_type(valobj.GetCompilerType());
Flags type_flags(valobj_type.GetTypeInfo());
if (type_flags.AllClear(eTypeHasValue)) {
if (valobj.IsBaseClass() && valobj.GetParent())
- ptr_value = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- } else
- ptr_value = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ ptr = valobj.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ } else {
+ ptr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ }
- if (ptr_value == LLDB_INVALID_ADDRESS)
+ if (ptr == LLDB_INVALID_ADDRESS)
return false;
size_t ptr_size = process_sp->GetAddressByteSize();
- lldb::addr_t name_location = ptr_value + 1 * ptr_size;
- lldb::addr_t reason_location = ptr_value + 2 * ptr_size;
Status error;
- lldb::addr_t name = process_sp->ReadPointerFromMemory(name_location, error);
+ auto name = process_sp->ReadPointerFromMemory(ptr + 1 * ptr_size, error);
if (error.Fail() || name == LLDB_INVALID_ADDRESS)
return false;
-
- lldb::addr_t reason =
- process_sp->ReadPointerFromMemory(reason_location, error);
+ auto reason = process_sp->ReadPointerFromMemory(ptr + 2 * ptr_size, error);
if (error.Fail() || reason == LLDB_INVALID_ADDRESS)
return false;
+ auto userinfo = process_sp->ReadPointerFromMemory(ptr + 3 * ptr_size, error);
+ if (error.Fail() || userinfo == LLDB_INVALID_ADDRESS)
+ return false;
+ auto reserved = process_sp->ReadPointerFromMemory(ptr + 4 * ptr_size, error);
+ if (error.Fail() || reserved == LLDB_INVALID_ADDRESS)
+ return false;
InferiorSizedWord name_isw(name, *process_sp);
InferiorSizedWord reason_isw(reason, *process_sp);
+ InferiorSizedWord userinfo_isw(userinfo, *process_sp);
+ InferiorSizedWord reserved_isw(reserved, *process_sp);
CompilerType voidstar = process_sp->GetTarget()
.GetScratchClangASTContext()
->GetBasicType(lldb::eBasicTypeVoid)
.GetPointerType();
- ValueObjectSP name_sp = ValueObject::CreateValueObjectFromData(
- "name_str", name_isw.GetAsData(process_sp->GetByteOrder()),
- valobj.GetExecutionContextRef(), voidstar);
- ValueObjectSP reason_sp = ValueObject::CreateValueObjectFromData(
- "reason_str", reason_isw.GetAsData(process_sp->GetByteOrder()),
- valobj.GetExecutionContextRef(), voidstar);
+ if (name_sp)
+ *name_sp = ValueObject::CreateValueObjectFromData(
+ "name", name_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+ if (reason_sp)
+ *reason_sp = ValueObject::CreateValueObjectFromData(
+ "reason", reason_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+ if (userinfo_sp)
+ *userinfo_sp = ValueObject::CreateValueObjectFromData(
+ "userInfo", userinfo_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+ if (reserved_sp)
+ *reserved_sp = ValueObject::CreateValueObjectFromData(
+ "reserved", reserved_isw.GetAsData(process_sp->GetByteOrder()),
+ valobj.GetExecutionContextRef(), voidstar);
+
+ return true;
+}
+
+bool lldb_private::formatters::NSException_SummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ lldb::ValueObjectSP name_sp;
+ lldb::ValueObjectSP reason_sp;
+ if (!ExtractFields(valobj, &name_sp, &reason_sp, nullptr, nullptr))
+ return false;
if (!name_sp || !reason_sp)
return false;
@@ -101,83 +123,55 @@ public:
: SyntheticChildrenFrontEnd(*valobj_sp) {}
~NSExceptionSyntheticFrontEnd() override = default;
- // no need to delete m_child_ptr - it's kept alive by the cluster manager on
- // our behalf
size_t CalculateNumChildren() override {
- if (m_child_ptr)
- return 1;
- if (m_child_sp)
- return 1;
- return 0;
+ return 4;
}
lldb::ValueObjectSP GetChildAtIndex(size_t idx) override {
- if (idx != 0)
- return lldb::ValueObjectSP();
-
- if (m_child_ptr)
- return m_child_ptr->GetSP();
- return m_child_sp;
+ switch (idx) {
+ case 0: return m_name_sp;
+ case 1: return m_reason_sp;
+ case 2: return m_userinfo_sp;
+ case 3: return m_reserved_sp;
+ }
+ return lldb::ValueObjectSP();
}
bool Update() override {
- m_child_ptr = nullptr;
- m_child_sp.reset();
-
- ProcessSP process_sp(m_backend.GetProcessSP());
- if (!process_sp)
- return false;
-
- lldb::addr_t userinfo_location = LLDB_INVALID_ADDRESS;
-
- CompilerType valobj_type(m_backend.GetCompilerType());
- Flags type_flags(valobj_type.GetTypeInfo());
- if (type_flags.AllClear(eTypeHasValue)) {
- if (m_backend.IsBaseClass() && m_backend.GetParent())
- userinfo_location =
- m_backend.GetParent()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
- } else
- userinfo_location = m_backend.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
- if (userinfo_location == LLDB_INVALID_ADDRESS)
- return false;
-
- size_t ptr_size = process_sp->GetAddressByteSize();
-
- userinfo_location += 3 * ptr_size;
- Status error;
- lldb::addr_t userinfo =
- process_sp->ReadPointerFromMemory(userinfo_location, error);
- if (userinfo == LLDB_INVALID_ADDRESS || error.Fail())
- return false;
- InferiorSizedWord isw(userinfo, *process_sp);
- m_child_sp = CreateValueObjectFromData(
- "userInfo", isw.GetAsData(process_sp->GetByteOrder()),
- m_backend.GetExecutionContextRef(),
- process_sp->GetTarget().GetScratchClangASTContext()->GetBasicType(
- lldb::eBasicTypeObjCID));
- return false;
+ m_name_sp.reset();
+ m_reason_sp.reset();
+ m_userinfo_sp.reset();
+ m_reserved_sp.reset();
+
+ return ExtractFields(m_backend, &m_name_sp, &m_reason_sp, &m_userinfo_sp,
+ &m_reserved_sp);
}
bool MightHaveChildren() override { return true; }
size_t GetIndexOfChildWithName(const ConstString &name) override {
+ // NSException has 4 members:
+ // NSString *name;
+ // NSString *reason;
+ // NSDictionary *userInfo;
+ // id reserved;
+ static ConstString g___name("name");
+ static ConstString g___reason("reason");
static ConstString g___userInfo("userInfo");
- if (name == g___userInfo)
- return 0;
+ static ConstString g___reserved("reserved");
+ if (name == g___name) return 0;
+ if (name == g___reason) return 1;
+ if (name == g___userInfo) return 2;
+ if (name == g___reserved) return 3;
return UINT32_MAX;
}
private:
- // the child here can be "real" (i.e. an actual child of the root) or
- // synthetized from raw memory if the former, I need to store a plain pointer
- // to it - or else a loop of references will cause this entire hierarchy of
- // values to leak if the latter, then I need to store a SharedPointer to it -
- // so that it only goes away when everyone else in the cluster goes away oh
- // joy!
- ValueObject *m_child_ptr;
- ValueObjectSP m_child_sp;
+ ValueObjectSP m_name_sp;
+ ValueObjectSP m_reason_sp;
+ ValueObjectSP m_userinfo_sp;
+ ValueObjectSP m_reserved_sp;
};
SyntheticChildrenFrontEnd *
diff --git a/source/Plugins/Language/ObjC/NSIndexPath.cpp b/source/Plugins/Language/ObjC/NSIndexPath.cpp
index 9533e96004a5..41df9abb3eb2 100644
--- a/source/Plugins/Language/ObjC/NSIndexPath.cpp
+++ b/source/Plugins/Language/ObjC/NSIndexPath.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Cocoa.h"
#include "lldb/Core/ValueObject.h"
@@ -130,11 +126,7 @@ public:
return false;
}
- bool MightHaveChildren() override {
- if (m_impl.m_mode == Mode::Invalid)
- return false;
- return true;
- }
+ bool MightHaveChildren() override { return m_impl.m_mode != Mode::Invalid; }
size_t GetIndexOfChildWithName(const ConstString &name) override {
const char *item_name = name.GetCString();
diff --git a/source/Plugins/Language/ObjC/NSSet.cpp b/source/Plugins/Language/ObjC/NSSet.cpp
index 2da4bc034f32..7e03d7574af0 100644
--- a/source/Plugins/Language/ObjC/NSSet.cpp
+++ b/source/Plugins/Language/ObjC/NSSet.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "NSSet.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h"
diff --git a/source/Plugins/Language/ObjC/NSString.cpp b/source/Plugins/Language/ObjC/NSString.cpp
index 0b12edb53d7a..f882b2adc260 100644
--- a/source/Plugins/Language/ObjC/NSString.cpp
+++ b/source/Plugins/Language/ObjC/NSString.cpp
@@ -225,10 +225,10 @@ bool lldb_private::formatters::NSStringSummaryProvider(
options.SetStream(&stream);
options.SetQuote('"');
options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetNeedsZeroTermination(!has_explicit_length);
options.SetIgnoreMaxLength(summary_options.GetCapping() ==
TypeSummaryCapping::eTypeSummaryUncapped);
- options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetBinaryZeroIsTerminator(!has_explicit_length);
options.SetLanguage(summary_options.GetLanguage());
return StringPrinter::ReadStringAndDumpToStream<
StringPrinter::StringElementType::UTF16>(options);
@@ -245,10 +245,10 @@ bool lldb_private::formatters::NSStringSummaryProvider(
options.SetStream(&stream);
options.SetQuote('"');
options.SetSourceSize(explicit_length);
- options.SetNeedsZeroTermination(has_explicit_length == false);
+ options.SetNeedsZeroTermination(!has_explicit_length);
options.SetIgnoreMaxLength(summary_options.GetCapping() ==
TypeSummaryCapping::eTypeSummaryUncapped);
- options.SetBinaryZeroIsTerminator(has_explicit_length == false);
+ options.SetBinaryZeroIsTerminator(!has_explicit_length);
options.SetLanguage(summary_options.GetLanguage());
return StringPrinter::ReadStringAndDumpToStream<
StringPrinter::StringElementType::UTF16>(options);
@@ -260,10 +260,7 @@ bool lldb_private::formatters::NSStringSummaryProvider(
Status error;
explicit_length =
process_sp->ReadUnsignedIntegerFromMemory(location, 1, 0, error);
- if (error.Fail() || explicit_length == 0)
- has_explicit_length = false;
- else
- has_explicit_length = true;
+ has_explicit_length = !(error.Fail() || explicit_length == 0);
location++;
}
options.SetLocation(location);
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index 47874b3be8fd..0598d69f6ebb 100644
--- a/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "ObjCLanguage.h"
#include "lldb/Core/PluginManager.h"
@@ -413,6 +409,9 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
"NSArray summary provider", ConstString("__NSCFArray"), appkit_flags);
AddCXXSummary(
objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
+ "NSArray summary provider", ConstString("_NSCallStackArray"), appkit_flags);
+ AddCXXSummary(
+ objc_category_sp, lldb_private::formatters::NSArraySummaryProvider,
"NSArray summary provider", ConstString("CFArrayRef"), appkit_flags);
AddCXXSummary(objc_category_sp,
lldb_private::formatters::NSArraySummaryProvider,
@@ -532,6 +531,10 @@ static void LoadObjCFormatters(TypeCategoryImplSP objc_category_sp) {
ScriptedSyntheticChildren::Flags());
AddCXXSynthetic(objc_category_sp,
lldb_private::formatters::NSArraySyntheticFrontEndCreator,
+ "NSArray synthetic children", ConstString("_NSCallStackArray"),
+ ScriptedSyntheticChildren::Flags());
+ AddCXXSynthetic(objc_category_sp,
+ lldb_private::formatters::NSArraySyntheticFrontEndCreator,
"NSArray synthetic children",
ConstString("CFMutableArrayRef"),
ScriptedSyntheticChildren::Flags());
@@ -1102,3 +1105,12 @@ bool ObjCLanguage::IsNilReference(ValueObject &valobj) {
bool isZero = valobj.GetValueAsUnsigned(0, &canReadValue) == 0;
return canReadValue && isZero;
}
+
+bool ObjCLanguage::IsSourceFile(llvm::StringRef file_path) const {
+ const auto suffixes = {".h", ".m", ".M"};
+ for (auto suffix : suffixes) {
+ if (file_path.endswith_lower(suffix))
+ return true;
+ }
+ return false;
+}
diff --git a/source/Plugins/Language/ObjC/ObjCLanguage.h b/source/Plugins/Language/ObjC/ObjCLanguage.h
index 9782c5da0d67..114f9323de02 100644
--- a/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -10,13 +10,10 @@
#ifndef liblldb_ObjCLanguage_h_
#define liblldb_ObjCLanguage_h_
-// C Includes
-// C++ Includes
#include <cstring>
#include <vector>
-// Other libraries and framework includes
-// Project includes
+#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
@@ -24,6 +21,8 @@
namespace lldb_private {
class ObjCLanguage : public Language {
+ ClangHighlighter m_highlighter;
+
public:
class MethodName {
public:
@@ -121,6 +120,10 @@ public:
bool IsNilReference(ValueObject &valobj) override;
+ bool IsSourceFile(llvm::StringRef file_path) const override;
+
+ const Highlighter *GetHighlighter() const override { return &m_highlighter; }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt b/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
index 75df9794d75d..1aa5cc1ed488 100644
--- a/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
+++ b/source/Plugins/Language/ObjCPlusPlus/CMakeLists.txt
@@ -1,7 +1,8 @@
add_lldb_library(lldbPluginObjCPlusPlusLanguage PLUGIN
ObjCPlusPlusLanguage.cpp
-
+
LINK_LIBS
lldbCore
lldbTarget
+ lldbPluginClangCommon
)
diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
index bfc22c9ee650..5e6d86e05318 100644
--- a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
+++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.cpp
@@ -16,6 +16,15 @@
using namespace lldb;
using namespace lldb_private;
+bool ObjCPlusPlusLanguage::IsSourceFile(llvm::StringRef file_path) const {
+ const auto suffixes = {".h", ".mm"};
+ for (auto suffix : suffixes) {
+ if (file_path.endswith_lower(suffix))
+ return true;
+ }
+ return false;
+}
+
void ObjCPlusPlusLanguage::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), "Objective-C++ Language",
CreateInstance);
diff --git a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
index 588b52215c10..b64f0f81e001 100644
--- a/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
+++ b/source/Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h
@@ -10,16 +10,15 @@
#ifndef liblldb_ObjCPlusPlusLanguage_h_
#define liblldb_ObjCPlusPlusLanguage_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "Plugins/Language/ClangCommon/ClangHighlighter.h"
#include "lldb/Target/Language.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
class ObjCPlusPlusLanguage : public Language {
+ ClangHighlighter m_highlighter;
+
public:
ObjCPlusPlusLanguage() = default;
@@ -29,6 +28,10 @@ public:
return lldb::eLanguageTypeObjC_plus_plus;
}
+ bool IsSourceFile(llvm::StringRef file_path) const override;
+
+ const Highlighter *GetHighlighter() const override { return &m_highlighter; }
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/source/Plugins/LanguageRuntime/CMakeLists.txt b/source/Plugins/LanguageRuntime/CMakeLists.txt
index 2cf579212ec1..c62791445a9a 100644
--- a/source/Plugins/LanguageRuntime/CMakeLists.txt
+++ b/source/Plugins/LanguageRuntime/CMakeLists.txt
@@ -1,5 +1,3 @@
add_subdirectory(CPlusPlus)
add_subdirectory(ObjC)
-add_subdirectory(Go)
-add_subdirectory(Java)
add_subdirectory(RenderScript)
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index fc661bbbf2c9..49a3d40d7b37 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -14,9 +14,11 @@
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Expression/DiagnosticManager.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -32,6 +34,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include <vector>
@@ -98,7 +101,7 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
llvm::DenseSet<SymbolFile *> searched_symbol_files;
if (sc.module_sp) {
num_matches = sc.module_sp->FindTypes(
- sc, ConstString(lookup_name), exact_match, 1,
+ ConstString(lookup_name), exact_match, 1,
searched_symbol_files, class_types);
}
@@ -106,7 +109,7 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfoFromVTableAddress(
// list in the target and get as many unique matches as possible
if (num_matches == 0) {
num_matches = target.GetImages().FindTypes(
- sc, ConstString(lookup_name), exact_match, UINT32_MAX,
+ nullptr, ConstString(lookup_name), exact_match, UINT32_MAX,
searched_symbol_files, class_types);
}
@@ -204,71 +207,71 @@ bool ItaniumABILanguageRuntime::GetDynamicTypeAndAddress(
// Only a pointer or reference type can have a different dynamic and static
// type:
- if (CouldHaveDynamicValue(in_value)) {
- // First job, pull out the address at 0 offset from the object.
- AddressType address_type;
- lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
- if (original_ptr == LLDB_INVALID_ADDRESS)
- return false;
+ if (!CouldHaveDynamicValue(in_value))
+ return false;
- ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
+ // First job, pull out the address at 0 offset from the object.
+ AddressType address_type;
+ lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
+ if (original_ptr == LLDB_INVALID_ADDRESS)
+ return false;
- Process *process = exe_ctx.GetProcessPtr();
+ ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
- if (process == nullptr)
- return false;
+ Process *process = exe_ctx.GetProcessPtr();
- Status error;
- const lldb::addr_t vtable_address_point =
- process->ReadPointerFromMemory(original_ptr, error);
+ if (process == nullptr)
+ return false;
- if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS) {
- return false;
- }
+ Status error;
+ const lldb::addr_t vtable_address_point =
+ process->ReadPointerFromMemory(original_ptr, error);
- class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr,
- vtable_address_point);
-
- if (class_type_or_name) {
- TypeSP type_sp = class_type_or_name.GetTypeSP();
- // There can only be one type with a given name, so we've just found
- // duplicate definitions, and this one will do as well as any other. We
- // don't consider something to have a dynamic type if it is the same as
- // the static type. So compare against the value we were handed.
- if (type_sp) {
- if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(),
- type_sp->GetForwardCompilerType())) {
- // The dynamic type we found was the same type, so we don't have a
- // dynamic type here...
- return false;
- }
+ if (!error.Success() || vtable_address_point == LLDB_INVALID_ADDRESS)
+ return false;
- // The offset_to_top is two pointers above the vtable pointer.
- const uint32_t addr_byte_size = process->GetAddressByteSize();
- const lldb::addr_t offset_to_top_location =
- vtable_address_point - 2 * addr_byte_size;
- // Watch for underflow, offset_to_top_location should be less than
- // vtable_address_point
- if (offset_to_top_location >= vtable_address_point)
- return false;
- const int64_t offset_to_top = process->ReadSignedIntegerFromMemory(
- offset_to_top_location, addr_byte_size, INT64_MIN, error);
-
- if (offset_to_top == INT64_MIN)
- return false;
- // So the dynamic type is a value that starts at offset_to_top above
- // the original address.
- lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
- if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(
- dynamic_addr, dynamic_address)) {
- dynamic_address.SetRawAddress(dynamic_addr);
- }
- return true;
- }
- }
+ class_type_or_name = GetTypeInfoFromVTableAddress(in_value, original_ptr,
+ vtable_address_point);
+
+ if (!class_type_or_name)
+ return false;
+
+ TypeSP type_sp = class_type_or_name.GetTypeSP();
+ // There can only be one type with a given name, so we've just found
+ // duplicate definitions, and this one will do as well as any other. We
+ // don't consider something to have a dynamic type if it is the same as
+ // the static type. So compare against the value we were handed.
+ if (!type_sp)
+ return true;
+
+ if (ClangASTContext::AreTypesSame(in_value.GetCompilerType(),
+ type_sp->GetForwardCompilerType())) {
+ // The dynamic type we found was the same type, so we don't have a
+ // dynamic type here...
+ return false;
}
- return class_type_or_name.IsEmpty() == false;
+ // The offset_to_top is two pointers above the vtable pointer.
+ const uint32_t addr_byte_size = process->GetAddressByteSize();
+ const lldb::addr_t offset_to_top_location =
+ vtable_address_point - 2 * addr_byte_size;
+ // Watch for underflow, offset_to_top_location should be less than
+ // vtable_address_point
+ if (offset_to_top_location >= vtable_address_point)
+ return false;
+ const int64_t offset_to_top = process->ReadSignedIntegerFromMemory(
+ offset_to_top_location, addr_byte_size, INT64_MIN, error);
+
+ if (offset_to_top == INT64_MIN)
+ return false;
+ // So the dynamic type is a value that starts at offset_to_top above
+ // the original address.
+ lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
+ if (!process->GetTarget().GetSectionLoadList().ResolveLoadAddress(
+ dynamic_addr, dynamic_address)) {
+ dynamic_address.SetRawAddress(dynamic_addr);
+ }
+ return true;
}
TypeAndOrName ItaniumABILanguageRuntime::FixUpDynamicType(
@@ -309,10 +312,7 @@ bool ItaniumABILanguageRuntime::IsVTableName(const char *name) {
return false;
// Can we maybe ask Clang about this?
- if (strstr(name, "_vptr$") == name)
- return true;
- else
- return false;
+ return strstr(name, "_vptr$") == name;
}
//------------------------------------------------------------------
@@ -483,8 +483,8 @@ lldb::SearchFilterSP ItaniumABILanguageRuntime::CreateExceptionSearchFilter() {
// Limit the number of modules that are searched for these breakpoints for
// Apple binaries.
FileSpecList filter_modules;
- filter_modules.Append(FileSpec("libc++abi.dylib", false));
- filter_modules.Append(FileSpec("libSystem.B.dylib", false));
+ filter_modules.Append(FileSpec("libc++abi.dylib"));
+ filter_modules.Append(FileSpec("libSystem.B.dylib"));
return target.GetSearchFilterForModuleList(&filter_modules);
} else {
return LanguageRuntime::CreateExceptionSearchFilter();
@@ -552,6 +552,64 @@ bool ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop(
break_site_id, m_cxx_exception_bp_sp->GetID());
}
+ValueObjectSP ItaniumABILanguageRuntime::GetExceptionObjectForThread(
+ ThreadSP thread_sp) {
+ if (!thread_sp->SafeToCallFunctions())
+ return {};
+
+ ClangASTContext *clang_ast_context =
+ m_process->GetTarget().GetScratchClangASTContext();
+ CompilerType voidstar =
+ clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+
+ DiagnosticManager diagnostics;
+ ExecutionContext exe_ctx;
+ EvaluateExpressionOptions options;
+
+ options.SetUnwindOnError(true);
+ options.SetIgnoreBreakpoints(true);
+ options.SetStopOthers(true);
+ options.SetTimeout(std::chrono::milliseconds(500));
+ options.SetTryAllThreads(false);
+ thread_sp->CalculateExecutionContext(exe_ctx);
+
+ const ModuleList &modules = m_process->GetTarget().GetImages();
+ SymbolContextList contexts;
+ SymbolContext context;
+
+ modules.FindSymbolsWithNameAndType(
+ ConstString("__cxa_current_exception_type"), eSymbolTypeCode, contexts);
+ contexts.GetContextAtIndex(0, context);
+ Address addr = context.symbol->GetAddress();
+
+ Status error;
+ FunctionCaller *function_caller =
+ m_process->GetTarget().GetFunctionCallerForLanguage(
+ eLanguageTypeC, voidstar, addr, ValueList(), "caller", error);
+
+ ExpressionResults func_call_ret;
+ Value results;
+ func_call_ret = function_caller->ExecuteFunction(exe_ctx, nullptr, options,
+ diagnostics, results);
+ if (func_call_ret != eExpressionCompleted || !error.Success()) {
+ return ValueObjectSP();
+ }
+
+ size_t ptr_size = m_process->GetAddressByteSize();
+ addr_t result_ptr = results.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
+ addr_t exception_addr =
+ m_process->ReadPointerFromMemory(result_ptr - ptr_size, error);
+
+ lldb_private::formatters::InferiorSizedWord exception_isw(exception_addr,
+ *m_process);
+ ValueObjectSP exception = ValueObject::CreateValueObjectFromData(
+ "exception", exception_isw.GetAsData(m_process->GetByteOrder()), exe_ctx,
+ voidstar);
+ exception = exception->GetDynamicValue(eDynamicDontRunTarget);
+
+ return exception;
+}
+
TypeAndOrName ItaniumABILanguageRuntime::GetDynamicTypeInfo(
const lldb_private::Address &vtable_addr) {
std::lock_guard<std::mutex> locker(m_dynamic_type_map_mutex);
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index 480c32691c8b..abed3706c6b8 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -10,14 +10,10 @@
#ifndef liblldb_ItaniumABILanguageRuntime_h_
#define liblldb_ItaniumABILanguageRuntime_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/Type.h"
@@ -69,6 +65,9 @@ public:
bool throw_bp) override;
lldb::SearchFilterSP CreateExceptionSearchFilter() override;
+
+ lldb::ValueObjectSP GetExceptionObjectForThread(
+ lldb::ThreadSP thread_sp) override;
//------------------------------------------------------------------
// PluginInterface protocol
diff --git a/source/Plugins/LanguageRuntime/Go/CMakeLists.txt b/source/Plugins/LanguageRuntime/Go/CMakeLists.txt
index 16756d5c985a..62418def58f6 100644
--- a/source/Plugins/LanguageRuntime/Go/CMakeLists.txt
+++ b/source/Plugins/LanguageRuntime/Go/CMakeLists.txt
@@ -1,8 +1,6 @@
set(LLVM_NO_RTTI 1)
add_lldb_library(lldbPluginLanguageRuntimeGo PLUGIN
- GoLanguageRuntime.cpp
-
LINK_LIBS
lldbBreakpoint
lldbCore
diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
deleted file mode 100644
index 6670f89dde5f..000000000000
--- a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-//===-- GoLanguageRuntime.cpp --------------------------------------*- C++
-//-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "GoLanguageRuntime.h"
-
-#include "lldb/Breakpoint/BreakpointLocation.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Core/ValueObjectMemory.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Symbol/Symbol.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/TypeList.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/RegisterContext.h"
-#include "lldb/Target/SectionLoadList.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Status.h"
-#include "llvm/ADT/Twine.h"
-
-#include <vector>
-
-using namespace lldb;
-using namespace lldb_private;
-
-namespace {
-ValueObjectSP GetChild(ValueObject &obj, const char *name,
- bool dereference = true) {
- ConstString name_const_str(name);
- ValueObjectSP result = obj.GetChildMemberWithName(name_const_str, true);
- if (dereference && result && result->IsPointerType()) {
- Status err;
- result = result->Dereference(err);
- if (err.Fail())
- result.reset();
- }
- return result;
-}
-
-ConstString ReadString(ValueObject &str, Process *process) {
- ConstString result;
- ValueObjectSP data = GetChild(str, "str", false);
- ValueObjectSP len = GetChild(str, "len");
- if (len && data) {
- Status err;
- lldb::addr_t addr = data->GetPointerValue();
- if (addr == LLDB_INVALID_ADDRESS)
- return result;
- uint64_t byte_size = len->GetValueAsUnsigned(0);
- char *buf = new char[byte_size + 1];
- buf[byte_size] = 0;
- size_t bytes_read = process->ReadMemory(addr, buf, byte_size, err);
- if (!(err.Fail() || bytes_read != byte_size))
- result = ConstString(buf, bytes_read);
- delete[] buf;
- }
- return result;
-}
-
-ConstString ReadTypeName(ValueObjectSP type, Process *process) {
- if (ValueObjectSP uncommon = GetChild(*type, "x")) {
- ValueObjectSP name = GetChild(*uncommon, "name");
- ValueObjectSP package = GetChild(*uncommon, "pkgpath");
- if (name && name->GetPointerValue() != 0 && package &&
- package->GetPointerValue() != 0) {
- ConstString package_const_str = ReadString(*package, process);
- ConstString name_const_str = ReadString(*name, process);
- if (package_const_str.GetLength() == 0)
- return name_const_str;
- return ConstString((package_const_str.GetStringRef() + "." +
- name_const_str.GetStringRef())
- .str());
- }
- }
- ValueObjectSP name = GetChild(*type, "_string");
- if (name)
- return ReadString(*name, process);
- return ConstString("");
-}
-
-CompilerType LookupRuntimeType(ValueObjectSP type, ExecutionContext *exe_ctx,
- bool *is_direct) {
- uint8_t kind = GetChild(*type, "kind")->GetValueAsUnsigned(0);
- *is_direct = GoASTContext::IsDirectIface(kind);
- if (GoASTContext::IsPointerKind(kind)) {
- CompilerType type_ptr = type->GetCompilerType().GetPointerType();
- Status err;
- ValueObjectSP elem =
- type->CreateValueObjectFromAddress("elem", type->GetAddressOf() +
- type->GetByteSize(),
- *exe_ctx, type_ptr)
- ->Dereference(err);
- if (err.Fail())
- return CompilerType();
- bool tmp_direct;
- return LookupRuntimeType(elem, exe_ctx, &tmp_direct).GetPointerType();
- }
- Target *target = exe_ctx->GetTargetPtr();
- Process *process = exe_ctx->GetProcessPtr();
-
- ConstString const_typename = ReadTypeName(type, process);
- if (const_typename.GetLength() == 0)
- return CompilerType();
-
- SymbolContext sc;
- TypeList type_list;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- uint32_t num_matches = target->GetImages().FindTypes(
- sc, const_typename, false, 2, searched_symbol_files, type_list);
- if (num_matches > 0) {
- return type_list.GetTypeAtIndex(0)->GetFullCompilerType();
- }
- return CompilerType();
-}
-}
-
-bool GoLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
- return GoASTContext::IsGoInterface(in_value.GetCompilerType());
-}
-
-bool GoLanguageRuntime::GetDynamicTypeAndAddress(
- ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &dynamic_address,
- Value::ValueType &value_type) {
- value_type = Value::eValueTypeScalar;
- class_type_or_name.Clear();
- if (CouldHaveDynamicValue(in_value)) {
- Status err;
- ValueObjectSP iface = in_value.GetStaticValue();
- ValueObjectSP data_sp = GetChild(*iface, "data", false);
- if (!data_sp)
- return false;
-
- if (ValueObjectSP tab = GetChild(*iface, "tab"))
- iface = tab;
- ValueObjectSP type = GetChild(*iface, "_type");
- if (!type) {
- return false;
- }
-
- bool direct;
- ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
- CompilerType final_type = LookupRuntimeType(type, &exe_ctx, &direct);
- if (!final_type)
- return false;
- if (direct) {
- class_type_or_name.SetCompilerType(final_type);
- } else {
- // TODO: implement reference types or fix caller to support dynamic types
- // that aren't pointers
- // so we don't have to introduce this extra pointer.
- class_type_or_name.SetCompilerType(final_type.GetPointerType());
- }
-
- dynamic_address.SetLoadAddress(data_sp->GetPointerValue(),
- exe_ctx.GetTargetPtr());
-
- return true;
- }
- return false;
-}
-
-TypeAndOrName
-GoLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
- ValueObject &static_value) {
- return type_and_or_name;
-}
-
-//------------------------------------------------------------------
-// Static Functions
-//------------------------------------------------------------------
-LanguageRuntime *
-GoLanguageRuntime::CreateInstance(Process *process,
- lldb::LanguageType language) {
- if (language == eLanguageTypeGo)
- return new GoLanguageRuntime(process);
- else
- return NULL;
-}
-
-void GoLanguageRuntime::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Go Language Runtime",
- CreateInstance);
-}
-
-void GoLanguageRuntime::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString GoLanguageRuntime::GetPluginNameStatic() {
- static ConstString g_name("golang");
- return g_name;
-}
-
-//------------------------------------------------------------------
-// PluginInterface protocol
-//------------------------------------------------------------------
-lldb_private::ConstString GoLanguageRuntime::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t GoLanguageRuntime::GetPluginVersion() { return 1; }
diff --git a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h b/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
deleted file mode 100644
index 9c2ee15cff65..000000000000
--- a/source/Plugins/LanguageRuntime/Go/GoLanguageRuntime.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//===-- GoLanguageRuntime.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_GoLanguageRuntime_h_
-#define liblldb_GoLanguageRuntime_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Breakpoint/BreakpointResolver.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Target/LanguageRuntime.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class GoLanguageRuntime : public lldb_private::LanguageRuntime {
-public:
- ~GoLanguageRuntime() override = default;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeGo;
- }
-
- bool GetObjectDescription(Stream &str, ValueObject &object) override {
- // TODO(ribrdb): Maybe call String() method?
- return false;
- }
-
- bool GetObjectDescription(Stream &str, Value &value,
- ExecutionContextScope *exe_scope) override {
- return false;
- }
-
- bool GetDynamicTypeAndAddress(ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type) override;
-
- bool CouldHaveDynamicValue(ValueObject &in_value) override;
-
- lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
- bool catch_bp,
- bool throw_bp) override {
- return lldb::BreakpointResolverSP();
- }
-
- TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
- ValueObject &static_value) override;
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- lldb_private::ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
-private:
- GoLanguageRuntime(Process *process)
- : lldb_private::LanguageRuntime(process) {
- } // Call CreateInstance instead.
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_GoLanguageRuntime_h_
diff --git a/source/Plugins/LanguageRuntime/Java/CMakeLists.txt b/source/Plugins/LanguageRuntime/Java/CMakeLists.txt
deleted file mode 100644
index ec87718752e7..000000000000
--- a/source/Plugins/LanguageRuntime/Java/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-add_lldb_library(lldbPluginLanguageRuntimeJava PLUGIN
- JavaLanguageRuntime.cpp
-
- LINK_LIBS
- lldbCore
- lldbSymbol
- lldbTarget
- LINK_COMPONENTS
- Support
- )
diff --git a/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp b/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp
deleted file mode 100644
index 36c30a99ff87..000000000000
--- a/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.cpp
+++ /dev/null
@@ -1,157 +0,0 @@
-//===-- JavaLanguageRuntime.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JavaLanguageRuntime.h"
-
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Symbol/JavaASTContext.h"
-#include "lldb/Symbol/Symbol.h"
-#include "lldb/Symbol/SymbolContext.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/TypeList.h"
-#include "lldb/Target/SectionLoadList.h"
-#include "lldb/Target/Target.h"
-#include "llvm/ADT/StringRef.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-JavaLanguageRuntime::JavaLanguageRuntime(Process *process)
- : LanguageRuntime(process) {}
-
-LanguageRuntime *
-JavaLanguageRuntime::CreateInstance(Process *process,
- lldb::LanguageType language) {
- if (language == eLanguageTypeJava)
- return new JavaLanguageRuntime(process);
- return nullptr;
-}
-
-void JavaLanguageRuntime::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "Java language runtime",
- CreateInstance);
-}
-
-void JavaLanguageRuntime::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-lldb_private::ConstString JavaLanguageRuntime::GetPluginNameStatic() {
- static ConstString g_name("java");
- return g_name;
-}
-
-lldb_private::ConstString JavaLanguageRuntime::GetPluginName() {
- return GetPluginNameStatic();
-}
-
-uint32_t JavaLanguageRuntime::GetPluginVersion() { return 1; }
-
-bool JavaLanguageRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
- return true;
-}
-
-static ConstString GetDynamicTypeId(ExecutionContext *exe_ctx, Target *target,
- ValueObject &in_value) {
- SymbolContext sc;
- TypeList class_types;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- size_t num_matches = target->GetImages().FindTypes(
- sc, ConstString("Object"),
- true, // name_is_fully_qualified
- UINT32_MAX, searched_symbol_files, class_types);
- for (size_t i = 0; i < num_matches; ++i) {
- TypeSP type_sp = class_types.GetTypeAtIndex(i);
- CompilerType compiler_type = type_sp->GetFullCompilerType();
-
- if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava ||
- compiler_type.GetTypeName() != ConstString("java::lang::Object"))
- continue;
-
- if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) {
- uint64_t type_id = JavaASTContext::CalculateDynamicTypeId(
- exe_ctx, compiler_type, in_value);
- if (type_id != UINT64_MAX) {
- char id[32];
- snprintf(id, sizeof(id), "0x%" PRIX64, type_id);
- return ConstString(id);
- }
- }
- }
- return ConstString();
-}
-
-bool JavaLanguageRuntime::GetDynamicTypeAndAddress(
- ValueObject &in_value, lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name, Address &dynamic_address,
- Value::ValueType &value_type) {
- class_type_or_name.Clear();
-
- // null references don't have a dynamic type
- if (in_value.IsNilReference())
- return false;
-
- ExecutionContext exe_ctx(in_value.GetExecutionContextRef());
- Target *target = exe_ctx.GetTargetPtr();
- if (!target)
- return false;
-
- ConstString linkage_name;
- CompilerType in_type = in_value.GetCompilerType();
- if (in_type.IsPossibleDynamicType(nullptr, false, false))
- linkage_name = GetDynamicTypeId(&exe_ctx, target, in_value);
- else
- linkage_name = JavaASTContext::GetLinkageName(in_type);
-
- if (!linkage_name)
- return false;
-
- class_type_or_name.SetName(in_type.GetNonReferenceType().GetTypeName());
-
- SymbolContext sc;
- TypeList class_types;
- llvm::DenseSet<SymbolFile *> searched_symbol_files;
- size_t num_matches = target->GetImages().FindTypes(
- sc, linkage_name,
- true, // name_is_fully_qualified
- UINT32_MAX, searched_symbol_files, class_types);
-
- for (size_t i = 0; i < num_matches; ++i) {
- TypeSP type_sp = class_types.GetTypeAtIndex(i);
- CompilerType compiler_type = type_sp->GetFullCompilerType();
-
- if (compiler_type.GetMinimumLanguage() != eLanguageTypeJava)
- continue;
-
- if (compiler_type.GetCompleteType() && compiler_type.IsCompleteType()) {
- class_type_or_name.SetTypeSP(type_sp);
-
- Value &value = in_value.GetValue();
- value_type = value.GetValueType();
- dynamic_address.SetRawAddress(value.GetScalar().ULongLong(0));
- return true;
- }
- }
- return false;
-}
-
-TypeAndOrName
-JavaLanguageRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
- ValueObject &static_value) {
- CompilerType static_type(static_value.GetCompilerType());
-
- TypeAndOrName ret(type_and_or_name);
- if (type_and_or_name.HasType()) {
- CompilerType orig_type = type_and_or_name.GetCompilerType();
- if (static_type.IsReferenceType())
- ret.SetCompilerType(orig_type.GetLValueReferenceType());
- }
- return ret;
-}
diff --git a/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h b/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h
deleted file mode 100644
index 6eeb4041572a..000000000000
--- a/source/Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===-- JavaLanguageRuntime.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_JavaLanguageRuntime_h_
-#define liblldb_JavaLanguageRuntime_h_
-
-// C Includes
-// C++ Includes
-#include <vector>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/PluginInterface.h"
-#include "lldb/Target/LanguageRuntime.h"
-#include "lldb/lldb-private.h"
-
-namespace lldb_private {
-
-class JavaLanguageRuntime : public LanguageRuntime {
-public:
- static void Initialize();
-
- static void Terminate();
-
- static lldb_private::LanguageRuntime *
- CreateInstance(Process *process, lldb::LanguageType language);
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- lldb_private::ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- lldb::LanguageType GetLanguageType() const override {
- return lldb::eLanguageTypeJava;
- }
-
- bool GetObjectDescription(Stream &str, ValueObject &object) override {
- return false;
- }
-
- bool GetObjectDescription(Stream &str, Value &value,
- ExecutionContextScope *exe_scope) override {
- return false;
- }
-
- lldb::BreakpointResolverSP CreateExceptionResolver(Breakpoint *bkpt,
- bool catch_bp,
- bool throw_bp) override {
- return nullptr;
- }
-
- TypeAndOrName FixUpDynamicType(const TypeAndOrName &type_and_or_name,
- ValueObject &static_value) override;
-
- bool CouldHaveDynamicValue(ValueObject &in_value) override;
-
- bool GetDynamicTypeAndAddress(ValueObject &in_value,
- lldb::DynamicValueType use_dynamic,
- TypeAndOrName &class_type_or_name,
- Address &address,
- Value::ValueType &value_type) override;
-
-protected:
- JavaLanguageRuntime(Process *process);
-
-private:
- DISALLOW_COPY_AND_ASSIGN(JavaLanguageRuntime);
-};
-
-} // namespace lldb_private
-
-#endif // liblldb_JavaLanguageRuntime_h_
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index edb29e735ca9..679c3c850e5b 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -264,11 +264,7 @@ bool ClassDescriptorV2::method_t::Read(Process *process, lldb::addr_t addr) {
}
process->ReadCStringFromMemory(m_types_ptr, m_types, error);
- if (error.Fail()) {
- return false;
- }
-
- return true;
+ return !error.Fail();
}
bool ClassDescriptorV2::ivar_list_t::Read(Process *process, lldb::addr_t addr) {
@@ -323,11 +319,7 @@ bool ClassDescriptorV2::ivar_t::Read(Process *process, lldb::addr_t addr) {
}
process->ReadCStringFromMemory(m_type_ptr, m_type, error);
- if (error.Fail()) {
- return false;
- }
-
- return true;
+ return !error.Fail();
}
bool ClassDescriptorV2::Describe(
@@ -524,7 +516,8 @@ void ClassDescriptorV2::iVarsStorage::fill(AppleObjCRuntimeV2 &runtime,
LLDB_LOGV(log,
"name = {0}, encoding = {1}, offset_ptr = {2:x}, size = "
"{3}, type_size = {4}",
- name, type, offset_ptr, size, ivar_type.GetByteSize(nullptr));
+ name, type, offset_ptr, size,
+ ivar_type.GetByteSize(nullptr).getValueOr(0));
Scalar offset_scalar;
Status error;
const int offset_ptr_size = 4;
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
index 787423b54766..308ff1426fb2 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h
@@ -10,12 +10,8 @@
#ifndef liblldb_AppleObjCClassDescriptorV2_h_
#define liblldb_AppleObjCClassDescriptorV2_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "AppleObjCRuntimeV2.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
index 105c088b9e91..4fc340b23c2c 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.cpp
@@ -558,7 +558,7 @@ AppleObjCDeclVendor::FindDecls(const ConstString &name, bool append,
LIBLLDB_LOG_EXPRESSIONS)); // FIXME - a more appropriate log channel?
if (log)
- log->Printf("AppleObjCDeclVendor::FindTypes [%u] ('%s', %s, %u, )",
+ log->Printf("AppleObjCDeclVendor::FindDecls [%u] ('%s', %s, %u, )",
current_id, (const char *)name.AsCString(),
append ? "true" : "false", max_matches);
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
index 2f087da16bc1..7f5c0bf3eb63 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCDeclVendor.h
@@ -10,10 +10,6 @@
#ifndef liblldb_AppleObjCDeclVendor_h_
#define liblldb_AppleObjCDeclVendor_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/DeclVendor.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index fef42c78b24f..ed47b481a810 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -17,13 +17,15 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -32,9 +34,13 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
+#include "Plugins/Process/Utility/HistoryThread.h"
+#include "Plugins/Language/ObjC/NSString.h"
+
#include <vector>
using namespace lldb;
@@ -167,6 +173,7 @@ bool AppleObjCRuntime::GetObjectDescription(Stream &strm, Value &value,
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeout(g_po_function_timeout);
+ options.SetIsForUtilityExpr(true);
ExpressionResults results = m_print_object_caller_up->ExecuteFunction(
exe_ctx, &wrapper_struct_addr, options, diagnostics, ret);
@@ -440,13 +447,10 @@ bool AppleObjCRuntime::CalculateHasNewLiteralsAndIndexing() {
SymbolContextList sc_list;
- if (target.GetImages().FindSymbolsWithNameAndType(s_method_signature,
- eSymbolTypeCode, sc_list) ||
- target.GetImages().FindSymbolsWithNameAndType(s_arclite_method_signature,
- eSymbolTypeCode, sc_list))
- return true;
- else
- return false;
+ return target.GetImages().FindSymbolsWithNameAndType(
+ s_method_signature, eSymbolTypeCode, sc_list) ||
+ target.GetImages().FindSymbolsWithNameAndType(
+ s_arclite_method_signature, eSymbolTypeCode, sc_list);
}
lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() {
@@ -454,13 +458,115 @@ lldb::SearchFilterSP AppleObjCRuntime::CreateExceptionSearchFilter() {
if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple) {
FileSpecList filter_modules;
- filter_modules.Append(FileSpec("libobjc.A.dylib", false));
+ filter_modules.Append(std::get<0>(GetExceptionThrowLocation()));
return target.GetSearchFilterForModuleList(&filter_modules);
} else {
return LanguageRuntime::CreateExceptionSearchFilter();
}
}
+ValueObjectSP AppleObjCRuntime::GetExceptionObjectForThread(
+ ThreadSP thread_sp) {
+ auto cpp_runtime = m_process->GetCPPLanguageRuntime();
+ if (!cpp_runtime) return ValueObjectSP();
+ auto cpp_exception = cpp_runtime->GetExceptionObjectForThread(thread_sp);
+ if (!cpp_exception) return ValueObjectSP();
+
+ auto descriptor = GetClassDescriptor(*cpp_exception.get());
+ if (!descriptor || !descriptor->IsValid()) return ValueObjectSP();
+
+ while (descriptor) {
+ ConstString class_name(descriptor->GetClassName());
+ if (class_name == ConstString("NSException")) return cpp_exception;
+ descriptor = descriptor->GetSuperclass();
+ }
+
+ return ValueObjectSP();
+}
+
+ThreadSP AppleObjCRuntime::GetBacktraceThreadFromException(
+ lldb::ValueObjectSP exception_sp) {
+ ValueObjectSP reserved_dict =
+ exception_sp->GetChildMemberWithName(ConstString("reserved"), true);
+ if (!reserved_dict) return ThreadSP();
+
+ reserved_dict = reserved_dict->GetSyntheticValue();
+ if (!reserved_dict) return ThreadSP();
+
+ CompilerType objc_id =
+ exception_sp->GetTargetSP()->GetScratchClangASTContext()->GetBasicType(
+ lldb::eBasicTypeObjCID);
+ ValueObjectSP return_addresses;
+
+ auto objc_object_from_address = [&exception_sp, &objc_id](uint64_t addr,
+ const char *name) {
+ Value value(addr);
+ value.SetCompilerType(objc_id);
+ auto object = ValueObjectConstResult::Create(
+ exception_sp->GetTargetSP().get(), value, ConstString(name));
+ object = object->GetDynamicValue(eDynamicDontRunTarget);
+ return object;
+ };
+
+ for (size_t idx = 0; idx < reserved_dict->GetNumChildren(); idx++) {
+ ValueObjectSP dict_entry = reserved_dict->GetChildAtIndex(idx, true);
+
+ DataExtractor data;
+ data.SetAddressByteSize(dict_entry->GetProcessSP()->GetAddressByteSize());
+ Status error;
+ dict_entry->GetData(data, error);
+ if (error.Fail()) return ThreadSP();
+
+ lldb::offset_t data_offset = 0;
+ auto dict_entry_key = data.GetPointer(&data_offset);
+ auto dict_entry_value = data.GetPointer(&data_offset);
+
+ auto key_nsstring = objc_object_from_address(dict_entry_key, "key");
+ StreamString key_summary;
+ if (lldb_private::formatters::NSStringSummaryProvider(
+ *key_nsstring, key_summary, TypeSummaryOptions()) &&
+ !key_summary.Empty()) {
+ if (key_summary.GetString() == "\"callStackReturnAddresses\"") {
+ return_addresses = objc_object_from_address(dict_entry_value,
+ "callStackReturnAddresses");
+ break;
+ }
+ }
+ }
+
+ if (!return_addresses) return ThreadSP();
+ auto frames_value =
+ return_addresses->GetChildMemberWithName(ConstString("_frames"), true);
+ addr_t frames_addr = frames_value->GetValueAsUnsigned(0);
+ auto count_value =
+ return_addresses->GetChildMemberWithName(ConstString("_cnt"), true);
+ size_t count = count_value->GetValueAsUnsigned(0);
+ auto ignore_value =
+ return_addresses->GetChildMemberWithName(ConstString("_ignore"), true);
+ size_t ignore = ignore_value->GetValueAsUnsigned(0);
+
+ size_t ptr_size = m_process->GetAddressByteSize();
+ std::vector<lldb::addr_t> pcs;
+ for (size_t idx = 0; idx < count; idx++) {
+ Status error;
+ addr_t pc = m_process->ReadPointerFromMemory(
+ frames_addr + (ignore + idx) * ptr_size, error);
+ pcs.push_back(pc);
+ }
+
+ if (pcs.empty()) return ThreadSP();
+
+ ThreadSP new_thread_sp(new HistoryThread(*m_process, 0, pcs, 0, false));
+ m_process->GetExtendedThreadList().AddThread(new_thread_sp);
+ return new_thread_sp;
+}
+
+std::tuple<FileSpec, ConstString>
+AppleObjCRuntime::GetExceptionThrowLocation() {
+ return std::make_tuple(
+ FileSpec("libobjc.A.dylib"), ConstString("objc_exception_throw"));
+}
+
void AppleObjCRuntime::ReadObjCLibraryIfNeeded(const ModuleList &module_list) {
if (!HasReadObjCLibrary()) {
std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
index 1b22ee4c3be1..866064600149 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
@@ -10,12 +10,8 @@
#ifndef liblldb_AppleObjCRuntime_h_
#define liblldb_AppleObjCRuntime_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/Optional.h"
-// Project includes
#include "AppleObjCTrampolineHandler.h"
#include "AppleThreadPlanStepThroughObjCTrampoline.h"
#include "lldb/Target/LanguageRuntime.h"
@@ -90,6 +86,14 @@ public:
bool ExceptionBreakpointsExplainStop(lldb::StopInfoSP stop_reason) override;
lldb::SearchFilterSP CreateExceptionSearchFilter() override;
+
+ static std::tuple<FileSpec, ConstString> GetExceptionThrowLocation();
+
+ lldb::ValueObjectSP GetExceptionObjectForThread(
+ lldb::ThreadSP thread_sp) override;
+
+ lldb::ThreadSP GetBacktraceThreadFromException(
+ lldb::ValueObjectSP thread_sp) override;
uint32_t GetFoundationVersion();
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 5001c0461b3b..1cfc7a1a022b 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -17,7 +17,6 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -29,6 +28,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -58,7 +58,7 @@ bool AppleObjCRuntimeV1::GetDynamicTypeAndAddress(
class_type_or_name.SetName(class_descriptor->GetClassName());
}
}
- return class_type_or_name.IsEmpty() == false;
+ return !class_type_or_name.IsEmpty();
}
//------------------------------------------------------------------
@@ -113,8 +113,9 @@ AppleObjCRuntimeV1::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
if (throw_bp)
resolver_sp.reset(new BreakpointResolverName(
- bkpt, "objc_exception_throw", eFunctionNameTypeBase,
- eLanguageTypeUnknown, Breakpoint::Exact, 0, eLazyBoolNo));
+ bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(),
+ eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0,
+ eLazyBoolNo));
// FIXME: don't do catch yet.
return resolver_sp;
}
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index 52eec0f692fb..442a3a1fb5e1 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -10,10 +10,6 @@
#ifndef liblldb_AppleObjCRuntimeV1_h_
#define liblldb_AppleObjCRuntimeV1_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "AppleObjCRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index d217ed3ff325..b6ed2fe376d3 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -7,18 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
-// Project includes
#include "lldb/Core/ClangForward.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Symbol/CompilerType.h"
@@ -28,8 +24,8 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/FunctionCaller.h"
@@ -44,14 +40,17 @@
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/TypeList.h"
#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
@@ -377,6 +376,8 @@ ExtractRuntimeGlobalSymbol(Process *process, ConstString name,
}
}
+static void RegisterObjCExceptionRecognizer();
+
AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
const ModuleSP &objc_module_sp)
: AppleObjCRuntime(process), m_get_class_info_code(),
@@ -397,6 +398,7 @@ AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
static const ConstString g_gdb_object_getClass("gdb_object_getClass");
m_has_object_getClass = (objc_module_sp->FindFirstSymbolWithNameAndType(
g_gdb_object_getClass, eSymbolTypeCode) != NULL);
+ RegisterObjCExceptionRecognizer();
}
bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
@@ -452,7 +454,7 @@ bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
}
}
}
- return class_type_or_name.IsEmpty() == false;
+ return !class_type_or_name.IsEmpty();
}
//------------------------------------------------------------------
@@ -475,9 +477,9 @@ LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process,
return NULL;
}
-static OptionDefinition g_objc_classtable_dump_options[] = {
+static constexpr OptionDefinition g_objc_classtable_dump_options[] = {
{LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Print ivar and method information in detail"}};
class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
@@ -803,8 +805,9 @@ AppleObjCRuntimeV2::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp,
if (throw_bp)
resolver_sp.reset(new BreakpointResolverName(
- bkpt, "objc_exception_throw", eFunctionNameTypeBase,
- eLanguageTypeUnknown, Breakpoint::Exact, 0, eLazyBoolNo));
+ bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(),
+ eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0,
+ eLazyBoolNo));
// FIXME: We don't do catch breakpoints for ObjC yet.
// Should there be some way for the runtime to specify what it can do in this
// regard?
@@ -1409,6 +1412,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeout(g_utility_function_timeout);
+ options.SetIsForUtilityExpr(true);
Value return_value;
return_value.SetValueType(Value::eValueTypeScalar);
@@ -1659,6 +1663,7 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() {
options.SetStopOthers(true);
options.SetIgnoreBreakpoints(true);
options.SetTimeout(g_utility_function_timeout);
+ options.SetIsForUtilityExpr(true);
Value return_value;
return_value.SetValueType(Value::eValueTypeScalar);
@@ -1847,8 +1852,8 @@ void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
// warn if:
// - we could not run either expression
// - we found fewer than num_classes_to_warn_at classes total
- if ((false == shared_cache_update_result.m_update_ran) ||
- (false == dynamic_update_result.m_update_ran))
+ if ((!shared_cache_update_result.m_update_ran) ||
+ (!dynamic_update_result.m_update_ran))
WarnIfNoClassesCached(
SharedCacheWarningReason::eExpressionExecutionFailure);
else if (dynamic_update_result.m_num_found +
@@ -2423,7 +2428,7 @@ AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
ObjCLanguageRuntime::ClassDescriptorSP
AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) {
ObjCISA real_isa = 0;
- if (EvaluateNonPointerISA(isa, real_isa) == false)
+ if (!EvaluateNonPointerISA(isa, real_isa))
return ObjCLanguageRuntime::ClassDescriptorSP();
auto cache_iter = m_cache.find(real_isa);
if (cache_iter != m_cache.end())
@@ -2447,7 +2452,7 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
// If all of the indexed ISA variables are set, then its possible that this
// ISA is indexed, and we should first try to get its value using the index.
- // Note, we check these varaibles first as the ObjC runtime will set at least
+ // Note, we check these variables first as the ObjC runtime will set at least
// one of their values to 0 if they aren't needed.
if (m_objc_debug_indexed_isa_magic_mask &&
m_objc_debug_indexed_isa_magic_value &&
@@ -2534,7 +2539,7 @@ bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
return false;
}
- // Definately not an indexed ISA, so try to use a mask to extract the pointer
+ // Definitely not an indexed ISA, so try to use a mask to extract the pointer
// from the ISA.
if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
ret_isa = isa & m_objc_debug_isa_class_mask;
@@ -2594,3 +2599,62 @@ void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
} else
this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
}
+
+#pragma mark Frame recognizers
+
+class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
+ public:
+ ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
+ ThreadSP thread_sp = frame_sp->GetThread();
+ ProcessSP process_sp = thread_sp->GetProcess();
+
+ const lldb::ABISP &abi = process_sp->GetABI();
+ if (!abi) return;
+
+ CompilerType voidstar = process_sp->GetTarget()
+ .GetScratchClangASTContext()
+ ->GetBasicType(lldb::eBasicTypeVoid)
+ .GetPointerType();
+
+ ValueList args;
+ Value input_value;
+ input_value.SetCompilerType(voidstar);
+ args.PushValue(input_value);
+
+ if (!abi->GetArgumentValues(*thread_sp, args)) return;
+
+ addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
+
+ Value value(exception_addr);
+ value.SetCompilerType(voidstar);
+ exception = ValueObjectConstResult::Create(frame_sp.get(), value,
+ ConstString("exception"));
+ exception = exception->GetDynamicValue(eDynamicDontRunTarget);
+
+ m_arguments = ValueObjectListSP(new ValueObjectList());
+ m_arguments->Append(exception);
+ }
+
+ ValueObjectSP exception;
+
+ lldb::ValueObjectSP GetExceptionObject() override { return exception; }
+};
+
+class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
+ lldb::RecognizedStackFrameSP RecognizeFrame(lldb::StackFrameSP frame) {
+ return lldb::RecognizedStackFrameSP(
+ new ObjCExceptionRecognizedStackFrame(frame));
+ };
+};
+
+static void RegisterObjCExceptionRecognizer() {
+ static llvm::once_flag g_once_flag;
+ llvm::call_once(g_once_flag, []() {
+ FileSpec module;
+ ConstString function;
+ std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
+ StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
+ module.GetFilename(), function, /*first_instruction_only*/ true);
+ });
+}
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 487b67ca6271..aa91f857219b 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -10,14 +10,10 @@
#ifndef liblldb_AppleObjCRuntimeV2_h_
#define liblldb_AppleObjCRuntimeV2_h_
-// C Includes
-// C++ Includes
#include <map>
#include <memory>
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "AppleObjCRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index c75fa71ba131..e9182c590977 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -10,10 +10,6 @@
#include "AppleObjCTrampolineHandler.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "AppleThreadPlanStepThroughObjCTrampoline.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -80,7 +76,7 @@ extern \"C\" void * __lldb_objc_find_implementation_for_selector ( \n\
void *super_ptr; \n\
}; \n\
struct __lldb_objc_super { \n\
- void *reciever; \n\
+ void *receiver; \n\
struct __lldb_objc_class *class_ptr; \n\
}; \n\
struct __lldb_msg_ref { \n\
@@ -202,7 +198,7 @@ extern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object,
void *super_ptr; \n\
}; \n\
struct __lldb_objc_super { \n\
- void *reciever; \n\
+ void *receiver; \n\
struct __lldb_objc_class *class_ptr; \n\
}; \n\
struct __lldb_msg_ref { \n\
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
index dc58a8bc1eb6..fe3390757d08 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -10,14 +10,10 @@
#ifndef lldb_AppleObjCTrampolineHandler_h_
#define lldb_AppleObjCTrampolineHandler_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/lldb-public.h"
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
index 4da84dd92c3f..fac564e33165 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTypeEncodingParser.h
@@ -10,12 +10,8 @@
#ifndef liblldb_AppleObjCTypeEncodingParser_h_
#define liblldb_AppleObjCTypeEncodingParser_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/ASTContext.h"
-// Project includes
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index 75b670739427..2b54d0a542d9 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -8,10 +8,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "AppleThreadPlanStepThroughObjCTrampoline.h"
#include "AppleObjCTrampolineHandler.h"
#include "lldb/Expression/DiagnosticManager.h"
@@ -161,13 +157,15 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
SymbolContext sc = m_thread.GetStackFrameAtIndex(0)->GetSymbolContext(
eSymbolContextEverything);
+ Status status;
const bool abort_other_plans = false;
const bool first_insn = true;
const uint32_t frame_idx = 0;
m_run_to_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
abort_other_plans, &sc, first_insn, m_stop_others, eVoteNoOpinion,
- eVoteNoOpinion, frame_idx);
- m_run_to_sp->SetPrivate(true);
+ eVoteNoOpinion, frame_idx, status);
+ if (m_run_to_sp && status.Success())
+ m_run_to_sp->SetPrivate(true);
return false;
}
@@ -202,10 +200,7 @@ bool AppleThreadPlanStepThroughObjCTrampoline::ShouldStop(Event *event_ptr) {
// The base class MischiefManaged does some cleanup - so you have to call it in
// your MischiefManaged derived class.
bool AppleThreadPlanStepThroughObjCTrampoline::MischiefManaged() {
- if (IsPlanComplete())
- return true;
- else
- return false;
+ return IsPlanComplete();
}
bool AppleThreadPlanStepThroughObjCTrampoline::WillStop() { return true; }
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
index 60c8b92d9cc7..5758e19f83ca 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
@@ -10,10 +10,6 @@
#ifndef lldb_AppleThreadPlanStepThroughObjCTrampoline_h_
#define lldb_AppleThreadPlanStepThroughObjCTrampoline_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "AppleObjCTrampolineHandler.h"
#include "lldb/Core/Value.h"
#include "lldb/Target/ThreadPlan.h"
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
index cbbc35f1c08a..2c12cf9af637 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.cpp
@@ -7,11 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
#include "llvm/ADT/None.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Instruction.h"
@@ -24,7 +21,6 @@
#include "clang/Basic/TargetOptions.h"
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
index f45ff83c5a2b..647558171d1c 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptExpressionOpts.h
@@ -10,15 +10,11 @@
#ifndef LLDB_RENDERSCRIPT_EXPROPTS_H
#define LLDB_RENDERSCRIPT_EXPROPTS_H
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/IR/Module.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
-// Project includes
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 4eb15369aa1e..fa775d9bfa94 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringSwitch.h"
-// Project includes
#include "RenderScriptRuntime.h"
#include "RenderScriptScriptGroup.h"
@@ -20,7 +16,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Expression/UserExpression.h"
@@ -41,8 +36,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Status.h"
@@ -2079,10 +2074,8 @@ bool RenderScriptRuntime::JITElementPacked(Element &elem,
// If this Element has subelements then JIT rsaElementGetSubElements() for
// details about its fields
- if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr))
- return false;
-
- return true;
+ return !(*elem.field_count.get() > 0 &&
+ !JITSubelements(elem, context, frame_ptr));
}
// JITs the RS runtime for information about the subelements/fields of a struct
@@ -2305,10 +2298,7 @@ bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
SetElementSize(alloc->element);
// Use GetOffsetPointer() to infer size of the allocation
- if (!JITAllocationSize(alloc, frame_ptr))
- return false;
-
- return true;
+ return JITAllocationSize(alloc, frame_ptr);
}
// Function attempts to set the type_name member of the paramaterised Element
@@ -2529,21 +2519,22 @@ bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
"Allocation information not available");
// Check we can read from file
- FileSpec file(path, true);
- if (!file.Exists()) {
+ FileSpec file(path);
+ FileSystem::Instance().Resolve(file);
+ if (!FileSystem::Instance().Exists(file)) {
strm.Printf("Error: File %s does not exist", path);
strm.EOL();
return false;
}
- if (!file.Readable()) {
+ if (!FileSystem::Instance().Readable(file)) {
strm.Printf("Error: File %s does not have readable permissions", path);
strm.EOL();
return false;
}
// Read file into data buffer
- auto data_sp = DataBufferLLVM::CreateFromPath(file.GetPath());
+ auto data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath());
// Cast start of buffer to FileHeader and use pointer to read metadata
void *file_buf = data_sp->GetBytes();
@@ -2753,9 +2744,14 @@ bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
"Allocation information not available");
// Check we can create writable file
- FileSpec file_spec(path, true);
- File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
- File::eOpenOptionTruncate);
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
+ File file;
+ FileSystem::Instance().Open(file, file_spec,
+ File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate |
+ File::eOpenOptionTruncate);
+
if (!file) {
strm.Printf("Error: Failed to open '%s' for writing", path);
strm.EOL();
@@ -3079,7 +3075,8 @@ bool RSModuleDescriptor::ParseRSInfo() {
const addr_t size = info_sym->GetByteSize();
const FileSpec fs = m_module->GetFileSpec();
- auto buffer = DataBufferLLVM::CreateSliceFromPath(fs.GetPath(), size, addr);
+ auto buffer =
+ FileSystem::Instance().CreateDataBuffer(fs.GetPath(), size, addr);
if (!buffer)
return false;
@@ -3718,7 +3715,8 @@ bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
continue;
// Find the function name
- const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false);
+ const SymbolContext sym_ctx =
+ frame_sp->GetSymbolContext(eSymbolContextFunction);
const ConstString func_name = sym_ctx.GetFunctionName();
if (!func_name)
continue;
@@ -4171,13 +4169,13 @@ public:
}
};
-static OptionDefinition g_renderscript_reduction_bp_set_options[] = {
+static constexpr OptionDefinition g_renderscript_reduction_bp_set_options[] = {
{LLDB_OPT_SET_1, false, "function-role", 't',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,
"Break on a comma separated set of reduction kernel types "
"(accumulator,outcoverter,combiner,initializer"},
{LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeValue,
+ nullptr, {}, 0, eArgTypeValue,
"Set a breakpoint on a single invocation of the kernel with specified "
"coordinate.\n"
"Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
@@ -4330,9 +4328,9 @@ private:
CommandOptions m_options;
};
-static OptionDefinition g_renderscript_kernel_bp_set_options[] = {
+static constexpr OptionDefinition g_renderscript_kernel_bp_set_options[] = {
{LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeValue,
+ nullptr, {}, 0, eArgTypeValue,
"Set a breakpoint on a single invocation of the kernel with specified "
"coordinate.\n"
"Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
@@ -4602,9 +4600,9 @@ public:
}
};
-static OptionDefinition g_renderscript_runtime_alloc_dump_options[] = {
+static constexpr OptionDefinition g_renderscript_runtime_alloc_dump_options[] = {
{LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Print results to specified file instead of command line."}};
class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword {
@@ -4650,8 +4648,9 @@ public:
switch (short_option) {
case 'f':
- m_outfile.SetFile(option_arg, true, FileSpec::Style::native);
- if (m_outfile.Exists()) {
+ m_outfile.SetFile(option_arg, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(m_outfile);
+ if (FileSystem::Instance().Exists(m_outfile)) {
m_outfile.Clear();
err.SetErrorStringWithFormat("file already exists: '%s'",
option_arg.str().c_str());
@@ -4706,16 +4705,17 @@ public:
m_options.m_outfile; // Dump allocation to file instead
if (outfile_spec) {
// Open output file
- char path[256];
- outfile_spec.GetPath(path, sizeof(path));
- if (outfile_stream.GetFile()
- .Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate)
- .Success()) {
+ std::string path = outfile_spec.GetPath();
+ auto error = FileSystem::Instance().Open(
+ outfile_stream.GetFile(), outfile_spec,
+ File::eOpenOptionWrite | File::eOpenOptionCanCreate);
+ if (error.Success()) {
output_strm = &outfile_stream;
- result.GetOutputStream().Printf("Results written to '%s'", path);
+ result.GetOutputStream().Printf("Results written to '%s'",
+ path.c_str());
result.GetOutputStream().EOL();
} else {
- result.AppendErrorWithFormat("Couldn't open file '%s'", path);
+ result.AppendErrorWithFormat("Couldn't open file '%s'", path.c_str());
result.SetStatus(eReturnStatusFailed);
return false;
}
@@ -4738,9 +4738,9 @@ private:
CommandOptions m_options;
};
-static OptionDefinition g_renderscript_runtime_alloc_list_options[] = {
+static constexpr OptionDefinition g_renderscript_runtime_alloc_list_options[] = {
{LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr,
- nullptr, 0, eArgTypeIndex,
+ {}, 0, eArgTypeIndex,
"Only show details of a single allocation with specified id."}};
class CommandObjectRenderScriptRuntimeAllocationList
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 0fe9134ce9e4..31714dd4a453 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -10,18 +10,14 @@
#ifndef liblldb_RenderScriptRuntime_h_
#define liblldb_RenderScriptRuntime_h_
-// C Includes
-// C++ Includes
#include <array>
#include <map>
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Expression/LLVMUserExpression.h"
#include "lldb/Target/CPPLanguageRuntime.h"
@@ -74,7 +70,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override { return Searcher::eDepthModule; }
+ lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
lldb::BreakpointResolverSP
CopyForBreakpoint(Breakpoint &breakpoint) override {
@@ -124,7 +120,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override { return Searcher::eDepthModule; }
+ lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
lldb::BreakpointResolverSP
CopyForBreakpoint(Breakpoint &breakpoint) override {
@@ -269,7 +265,7 @@ public:
SymbolContext &context, Address *addr,
bool containing) override;
- Searcher::Depth GetDepth() override { return Searcher::eDepthModule; }
+ lldb::SearchDepth GetDepth() override { return lldb::eSearchDepthModule; }
lldb::BreakpointResolverSP
CopyForBreakpoint(Breakpoint &breakpoint) override {
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
index e1f8ea648414..0b298c90a50b 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptx86ABIFixups.cpp
@@ -7,11 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <set>
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
@@ -23,7 +20,6 @@
#include "llvm/IRReader/IRReader.h"
#include "llvm/Pass.h"
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/Log.h"
diff --git a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
index 31e9873fb1ee..c08acd0151ef 100644
--- a/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
+++ b/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.h
@@ -10,10 +10,6 @@
#ifndef liblldb_MemoryHistoryASan_h_
#define liblldb_MemoryHistoryASan_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Target/Process.h"
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
index 275f1fa2f70b..391ab7546967 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -33,7 +33,6 @@ typedef struct ar_hdr {
#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
@@ -208,7 +207,7 @@ ObjectContainerBSDArchive::Archive::FindCachedArchive(
while (pos != archive_map.end() && pos->first == file) {
bool match = true;
if (arch.IsValid() &&
- pos->second->GetArchitecture().IsCompatibleMatch(arch) == false)
+ !pos->second->GetArchitecture().IsCompatibleMatch(arch))
match = false;
else if (file_offset != LLDB_INVALID_OFFSET &&
pos->second->GetFileOffset() != file_offset)
@@ -313,7 +312,7 @@ ObjectContainer *ObjectContainerBSDArchive::CreateInstance(
// file gets updated by a new build while this .a file is being used for
// debugging
DataBufferSP archive_data_sp =
- DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset);
+ FileSystem::Instance().CreateDataBuffer(*file, length, file_offset);
if (!archive_data_sp)
return nullptr;
@@ -461,14 +460,14 @@ size_t ObjectContainerBSDArchive::GetModuleSpecifications(
return 0;
const size_t initial_count = specs.GetSize();
- llvm::sys::TimePoint<> file_mod_time = FileSystem::GetModificationTime(file);
+ llvm::sys::TimePoint<> file_mod_time = FileSystem::Instance().GetModificationTime(file);
Archive::shared_ptr archive_sp(
Archive::FindCachedArchive(file, ArchSpec(), file_mod_time, file_offset));
bool set_archive_arch = false;
if (!archive_sp) {
set_archive_arch = true;
data_sp =
- DataBufferLLVM::CreateSliceFromPath(file.GetPath(), file_size, file_offset);
+ FileSystem::Instance().CreateDataBuffer(file, file_size, file_offset);
if (data_sp) {
data.SetData(data_sp, 0, data_sp->GetByteSize());
archive_sp = Archive::ParseAndCacheArchiveForFile(
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
index cb63eccff65e..86eaee1375a6 100644
--- a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -16,11 +16,8 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/FileSpec.h"
-// Other libraries and framework includes
#include "llvm/Support/Chrono.h"
-// C Includes
-// C++ Includes
#include <map>
#include <memory>
#include <mutex>
diff --git a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
index d3c0a080a6f9..d6e4fe1747cf 100644
--- a/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
+++ b/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h
@@ -10,13 +10,9 @@
#ifndef liblldb_ObjectContainerUniversalMachO_h_
#define liblldb_ObjectContainerUniversalMachO_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Symbol/ObjectContainer.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/SafeMachO.h"
class ObjectContainerUniversalMachO : public lldb_private::ObjectContainer {
public:
diff --git a/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt b/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
new file mode 100644
index 000000000000..2f51b2c8719a
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginObjectFileBreakpad PLUGIN
+ ObjectFileBreakpad.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
new file mode 100644
index 000000000000..917025030ada
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
@@ -0,0 +1,315 @@
+//===-- ObjectFileBreakpad.cpp -------------------------------- -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::breakpad;
+
+namespace {
+struct Header {
+ ArchSpec arch;
+ UUID uuid;
+ static llvm::Optional<Header> parse(llvm::StringRef text);
+};
+
+enum class Token { Unknown, Module, Info, File, Func, Public, Stack };
+} // namespace
+
+static Token toToken(llvm::StringRef str) {
+ return llvm::StringSwitch<Token>(str)
+ .Case("MODULE", Token::Module)
+ .Case("INFO", Token::Info)
+ .Case("FILE", Token::File)
+ .Case("FUNC", Token::Func)
+ .Case("PUBLIC", Token::Public)
+ .Case("STACK", Token::Stack)
+ .Default(Token::Unknown);
+}
+
+static llvm::StringRef toString(Token t) {
+ switch (t) {
+ case Token::Unknown:
+ return "";
+ case Token::Module:
+ return "MODULE";
+ case Token::Info:
+ return "INFO";
+ case Token::File:
+ return "FILE";
+ case Token::Func:
+ return "FUNC";
+ case Token::Public:
+ return "PUBLIC";
+ case Token::Stack:
+ return "STACK";
+ }
+ llvm_unreachable("Unknown token!");
+}
+
+static llvm::Triple::OSType toOS(llvm::StringRef str) {
+ using llvm::Triple;
+ return llvm::StringSwitch<Triple::OSType>(str)
+ .Case("Linux", Triple::Linux)
+ .Case("mac", Triple::MacOSX)
+ .Case("windows", Triple::Win32)
+ .Default(Triple::UnknownOS);
+}
+
+static llvm::Triple::ArchType toArch(llvm::StringRef str) {
+ using llvm::Triple;
+ return llvm::StringSwitch<Triple::ArchType>(str)
+ .Case("arm", Triple::arm)
+ .Case("arm64", Triple::aarch64)
+ .Case("mips", Triple::mips)
+ .Case("ppc", Triple::ppc)
+ .Case("ppc64", Triple::ppc64)
+ .Case("s390", Triple::systemz)
+ .Case("sparc", Triple::sparc)
+ .Case("sparcv9", Triple::sparcv9)
+ .Case("x86", Triple::x86)
+ .Case("x86_64", Triple::x86_64)
+ .Default(Triple::UnknownArch);
+}
+
+static llvm::StringRef consume_front(llvm::StringRef &str, size_t n) {
+ llvm::StringRef result = str.take_front(n);
+ str = str.drop_front(n);
+ return result;
+}
+
+static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) {
+ struct uuid_data {
+ llvm::support::ulittle32_t uuid1;
+ llvm::support::ulittle16_t uuid2[2];
+ uint8_t uuid3[8];
+ llvm::support::ulittle32_t age;
+ } data;
+ static_assert(sizeof(data) == 20, "");
+ // The textual module id encoding should be between 33 and 40 bytes long,
+ // depending on the size of the age field, which is of variable length.
+ // The first three chunks of the id are encoded in big endian, so we need to
+ // byte-swap those.
+ if (str.size() < 33 || str.size() > 40)
+ return UUID();
+ uint32_t t;
+ if (to_integer(consume_front(str, 8), t, 16))
+ data.uuid1 = t;
+ else
+ return UUID();
+ for (int i = 0; i < 2; ++i) {
+ if (to_integer(consume_front(str, 4), t, 16))
+ data.uuid2[i] = t;
+ else
+ return UUID();
+ }
+ for (int i = 0; i < 8; ++i) {
+ if (!to_integer(consume_front(str, 2), data.uuid3[i], 16))
+ return UUID();
+ }
+ if (to_integer(str, t, 16))
+ data.age = t;
+ else
+ return UUID();
+
+ // On non-windows, the age field should always be zero, so we don't include to
+ // match the native uuid format of these platforms.
+ return UUID::fromData(&data, os == llvm::Triple::Win32 ? 20 : 16);
+}
+
+llvm::Optional<Header> Header::parse(llvm::StringRef text) {
+ // A valid module should start with something like:
+ // MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 a.out
+ // optionally followed by
+ // INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC [a.exe]
+ llvm::StringRef token, line;
+ std::tie(line, text) = text.split('\n');
+ std::tie(token, line) = getToken(line);
+ if (toToken(token) != Token::Module)
+ return llvm::None;
+
+ std::tie(token, line) = getToken(line);
+ llvm::Triple triple;
+ triple.setOS(toOS(token));
+ if (triple.getOS() == llvm::Triple::UnknownOS)
+ return llvm::None;
+
+ std::tie(token, line) = getToken(line);
+ triple.setArch(toArch(token));
+ if (triple.getArch() == llvm::Triple::UnknownArch)
+ return llvm::None;
+
+ llvm::StringRef module_id;
+ std::tie(module_id, line) = getToken(line);
+
+ std::tie(line, text) = text.split('\n');
+ std::tie(token, line) = getToken(line);
+ if (token == "INFO") {
+ std::tie(token, line) = getToken(line);
+ if (token != "CODE_ID")
+ return llvm::None;
+
+ std::tie(token, line) = getToken(line);
+ // If we don't have any text following the code id (e.g. on linux), we
+ // should use the module id as UUID. Otherwise, we revert back to the module
+ // id.
+ if (line.trim().empty()) {
+ UUID uuid;
+ if (uuid.SetFromStringRef(token, token.size() / 2) != token.size())
+ return llvm::None;
+
+ return Header{ArchSpec(triple), uuid};
+ }
+ }
+
+ // We reach here if we don't have a INFO CODE_ID section, or we chose not to
+ // use it. In either case, we need to properly decode the module id, whose
+ // fields are encoded in big-endian.
+ UUID uuid = parseModuleId(triple.getOS(), module_id);
+ if (!uuid)
+ return llvm::None;
+
+ return Header{ArchSpec(triple), uuid};
+}
+
+void ObjectFileBreakpad::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications);
+}
+
+void ObjectFileBreakpad::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString ObjectFileBreakpad::GetPluginNameStatic() {
+ static ConstString g_name("breakpad");
+ return g_name;
+}
+
+ObjectFile *ObjectFileBreakpad::CreateInstance(
+ const ModuleSP &module_sp, DataBufferSP &data_sp, offset_t data_offset,
+ const FileSpec *file, offset_t file_offset, offset_t length) {
+ if (!data_sp) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ }
+ auto text = toStringRef(data_sp->GetData());
+ llvm::Optional<Header> header = Header::parse(text);
+ if (!header)
+ return nullptr;
+
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ }
+
+ return new ObjectFileBreakpad(module_sp, data_sp, data_offset, file,
+ file_offset, length, std::move(header->arch),
+ std::move(header->uuid));
+}
+
+ObjectFile *ObjectFileBreakpad::CreateMemoryInstance(
+ const ModuleSP &module_sp, DataBufferSP &data_sp,
+ const ProcessSP &process_sp, addr_t header_addr) {
+ return nullptr;
+}
+
+size_t ObjectFileBreakpad::GetModuleSpecifications(
+ const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
+ offset_t file_offset, offset_t length, ModuleSpecList &specs) {
+ auto text = toStringRef(data_sp->GetData());
+ llvm::Optional<Header> header = Header::parse(text);
+ if (!header)
+ return 0;
+ ModuleSpec spec(file, std::move(header->arch));
+ spec.GetUUID() = std::move(header->uuid);
+ specs.Append(spec);
+ return 1;
+}
+
+ObjectFileBreakpad::ObjectFileBreakpad(const ModuleSP &module_sp,
+ DataBufferSP &data_sp,
+ offset_t data_offset,
+ const FileSpec *file, offset_t offset,
+ offset_t length, ArchSpec arch,
+ UUID uuid)
+ : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
+ m_arch(std::move(arch)), m_uuid(std::move(uuid)) {}
+
+bool ObjectFileBreakpad::ParseHeader() {
+ // We already parsed the header during initialization.
+ return true;
+}
+
+Symtab *ObjectFileBreakpad::GetSymtab() {
+ // TODO
+ return nullptr;
+}
+
+bool ObjectFileBreakpad::GetUUID(UUID *uuid) {
+ *uuid = m_uuid;
+ return true;
+}
+
+void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
+ if (m_sections_ap)
+ return;
+ m_sections_ap = llvm::make_unique<SectionList>();
+
+ Token current_section = Token::Unknown;
+ offset_t section_start;
+ llvm::StringRef text = toStringRef(m_data.GetData());
+ uint32_t next_section_id = 1;
+ auto maybe_add_section = [&](const uint8_t *end_ptr) {
+ if (current_section == Token::Unknown)
+ return; // We have been called before parsing the first line.
+
+ offset_t end_offset = end_ptr - m_data.GetDataStart();
+ auto section_sp = std::make_shared<Section>(
+ GetModule(), this, next_section_id++,
+ ConstString(toString(current_section)), eSectionTypeOther,
+ /*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,
+ end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);
+ m_sections_ap->AddSection(section_sp);
+ unified_section_list.AddSection(section_sp);
+ };
+ while (!text.empty()) {
+ llvm::StringRef line;
+ std::tie(line, text) = text.split('\n');
+
+ Token token = toToken(getToken(line).first);
+ if (token == Token::Unknown) {
+ // We assume this is a line record, which logically belongs to the Func
+ // section. Errors will be handled when parsing the Func section.
+ token = Token::Func;
+ }
+ if (token == current_section)
+ continue;
+
+ // Changing sections, finish off the previous one, if there was any.
+ maybe_add_section(line.bytes_begin());
+ // And start a new one.
+ current_section = token;
+ section_start = line.bytes_begin() - m_data.GetDataStart();
+ }
+ // Finally, add the last section.
+ maybe_add_section(m_data.GetDataEnd());
+}
diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
new file mode 100644
index 000000000000..ba2a3ad30e5f
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
@@ -0,0 +1,109 @@
+//===-- ObjectFileBreakpad.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_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
+#define LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "llvm/ADT/Triple.h"
+
+namespace lldb_private {
+namespace breakpad {
+
+class ObjectFileBreakpad : public ObjectFile {
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+ static const char *GetPluginDescriptionStatic() {
+ return "Breakpad object file reader.";
+ }
+
+ static ObjectFile *
+ CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset, const FileSpec *file,
+ lldb::offset_t file_offset, lldb::offset_t length);
+
+ static ObjectFile *CreateMemoryInstance(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP &data_sp,
+ const lldb::ProcessSP &process_sp,
+ lldb::addr_t header_addr);
+
+ static size_t GetModuleSpecifications(const FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ ModuleSpecList &specs);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override { return GetPluginNameStatic(); }
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ //------------------------------------------------------------------
+ // ObjectFile Protocol.
+ //------------------------------------------------------------------
+
+ bool ParseHeader() override;
+
+ lldb::ByteOrder GetByteOrder() const override {
+ return m_arch.GetByteOrder();
+ }
+
+ bool IsExecutable() const override { return false; }
+
+ uint32_t GetAddressByteSize() const override {
+ return m_arch.GetAddressByteSize();
+ }
+
+ AddressClass GetAddressClass(lldb::addr_t file_addr) override {
+ return AddressClass::eInvalid;
+ }
+
+ Symtab *GetSymtab() override;
+
+ bool IsStripped() override { return false; }
+
+ void CreateSections(SectionList &unified_section_list) override;
+
+ void Dump(Stream *s) override {}
+
+ ArchSpec GetArchitecture() override { return m_arch; }
+
+ bool GetUUID(UUID *uuid) override;
+
+ FileSpecList GetDebugSymbolFilePaths() override { return FileSpecList(); }
+
+ uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
+
+ Type CalculateType() override { return eTypeDebugInfo; }
+
+ Strata CalculateStrata() override { return eStrataUser; }
+
+private:
+ ArchSpec m_arch;
+ UUID m_uuid;
+
+ ObjectFileBreakpad(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP &data_sp, lldb::offset_t data_offset,
+ const FileSpec *file, lldb::offset_t offset,
+ lldb::offset_t length, ArchSpec arch, UUID uuid);
+};
+
+} // namespace breakpad
+} // namespace lldb_private
+#endif // LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
diff --git a/source/Plugins/ObjectFile/CMakeLists.txt b/source/Plugins/ObjectFile/CMakeLists.txt
index 06aa01c4f004..4edd667b9723 100644
--- a/source/Plugins/ObjectFile/CMakeLists.txt
+++ b/source/Plugins/ObjectFile/CMakeLists.txt
@@ -1,4 +1,5 @@
+add_subdirectory(Breakpad)
add_subdirectory(ELF)
add_subdirectory(Mach-O)
add_subdirectory(PECOFF)
-add_subdirectory(JIT) \ No newline at end of file
+add_subdirectory(JIT)
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index 16cbb6e5753b..3d4735286bf2 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -38,7 +38,7 @@ static bool GetMaxU64(const lldb_private::DataExtractor &data,
lldb::offset_t saved_offset = *offset;
for (uint32_t i = 0; i < count; ++i, ++value) {
- if (GetMaxU64(data, offset, value, byte_size) == false) {
+ if (!GetMaxU64(data, offset, value, byte_size)) {
*offset = saved_offset;
return false;
}
@@ -60,7 +60,7 @@ static bool GetMaxS64(const lldb_private::DataExtractor &data,
lldb::offset_t saved_offset = *offset;
for (uint32_t i = 0; i < count; ++i, ++value) {
- if (GetMaxS64(data, offset, value, byte_size) == false) {
+ if (!GetMaxS64(data, offset, value, byte_size)) {
*offset = saved_offset;
return false;
}
@@ -133,7 +133,7 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data,
return false;
// Read e_entry, e_phoff and e_shoff.
- if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
+ if (!GetMaxU64(data, offset, &e_entry, byte_size, 3))
return false;
// Read e_flags.
@@ -232,11 +232,11 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read sh_flags.
- if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
+ if (!GetMaxU64(data, offset, &sh_flags, byte_size))
return false;
// Read sh_addr, sh_off and sh_size.
- if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
+ if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3))
return false;
// Read sh_link and sh_info.
@@ -244,7 +244,7 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read sh_addralign and sh_entsize.
- if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
+ if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2))
return false;
return true;
@@ -332,7 +332,7 @@ bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
if (parsing_32) {
// Read st_value and st_size.
- if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
+ if (!GetMaxU64(data, offset, &st_value, byte_size, 2))
return false;
// Read st_info and st_other.
@@ -376,7 +376,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
if (parsing_32) {
// Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
- if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
+ if (!GetMaxU64(data, offset, &p_offset, byte_size, 5))
return false;
// Read p_flags.
@@ -384,7 +384,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read p_align.
- if (GetMaxU64(data, offset, &p_align, byte_size) == false)
+ if (!GetMaxU64(data, offset, &p_align, byte_size))
return false;
} else {
// Read p_flags.
@@ -392,7 +392,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
- if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
+ if (!GetMaxU64(data, offset, &p_offset, byte_size, 6))
return false;
}
@@ -420,10 +420,7 @@ bool ELFRel::Parse(const lldb_private::DataExtractor &data,
const unsigned byte_size = data.GetAddressByteSize();
// Read r_offset and r_info.
- if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
- return false;
-
- return true;
+ return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
}
//------------------------------------------------------------------------------
@@ -436,11 +433,11 @@ bool ELFRela::Parse(const lldb_private::DataExtractor &data,
const unsigned byte_size = data.GetAddressByteSize();
// Read r_offset and r_info.
- if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
+ if (!GetMaxU64(data, offset, &r_offset, byte_size, 2))
return false;
// Read r_addend;
- if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
+ if (!GetMaxS64(data, offset, &r_addend, byte_size))
return false;
return true;
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 8701908378f1..9a6563afa0a0 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -17,7 +17,9 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RangeMap.h"
#include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/SectionLoadList.h"
@@ -29,6 +31,7 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Decompressor.h"
@@ -235,6 +238,8 @@ unsigned ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
} // end anonymous namespace
+static user_id_t SegmentID(size_t PHdrIndex) { return ~PHdrIndex; }
+
bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
// Read all fields.
if (data.GetU32(offset, &n_namesz, 3) == NULL)
@@ -433,9 +438,8 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
if (address_size == 4 || address_size == 8) {
std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(
module_sp, data_sp, data_offset, file, file_offset, length));
- ArchSpec spec;
- if (objfile_ap->GetArchitecture(spec) &&
- objfile_ap->SetModulesArchitecture(spec))
+ ArchSpec spec = objfile_ap->GetArchitecture();
+ if (spec && objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
@@ -452,9 +456,8 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance(
if (address_size == 4 || address_size == 8) {
std::unique_ptr<ObjectFileELF> objfile_ap(
new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
- ArchSpec spec;
- if (objfile_ap->GetArchitecture(spec) &&
- objfile_ap->SetModulesArchitecture(spec))
+ ArchSpec spec = objfile_ap->GetArchitecture();
+ if (spec && objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
}
@@ -538,14 +541,13 @@ static uint32_t calc_gnu_debuglink_crc32(const void *buf, size_t size) {
uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
const ProgramHeaderColl &program_headers, DataExtractor &object_data) {
- typedef ProgramHeaderCollConstIter Iter;
uint32_t core_notes_crc = 0;
- for (Iter I = program_headers.begin(); I != program_headers.end(); ++I) {
- if (I->p_type == llvm::ELF::PT_NOTE) {
- const elf_off ph_offset = I->p_offset;
- const size_t ph_size = I->p_filesz;
+ for (const ELFProgramHeader &H : program_headers) {
+ if (H.p_type == llvm::ELF::PT_NOTE) {
+ const elf_off ph_offset = H.p_offset;
+ const size_t ph_size = H.p_filesz;
DataExtractor segment_data;
if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
@@ -713,7 +715,8 @@ size_t ObjectFileELF::GetModuleSpecifications(
func_cat,
"Calculating module crc32 %s with size %" PRIu64 " KiB",
file.GetLastPathComponent().AsCString(),
- (file.GetByteSize() - file_offset) / 1024);
+ (FileSystem::Instance().GetByteSize(file) - file_offset) /
+ 1024);
// For core files - which usually don't happen to have a
// gnu_debuglink, and are pretty bulky - calculating whole
@@ -803,21 +806,10 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
SectionList *section_list = GetSectionList();
if (section_list) {
if (!value_is_offset) {
- bool found_offset = false;
- for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
- const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
- if (header == nullptr)
- continue;
-
- if (header->p_type != PT_LOAD || header->p_offset != 0)
- continue;
-
- value = value - header->p_vaddr;
- found_offset = true;
- break;
- }
- if (!found_offset)
+ addr_t base = GetBaseAddress().GetFileAddress();
+ if (base == LLDB_INVALID_ADDRESS)
return false;
+ value -= base;
}
const size_t num_sections = section_list->GetSize();
@@ -827,7 +819,8 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
// Iterate through the object file sections to find all of the sections
// that have SHF_ALLOC in their flag bits.
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
- if (section_sp && section_sp->Test(SHF_ALLOC)) {
+ if (section_sp->Test(SHF_ALLOC) ||
+ section_sp->GetType() == eSectionTypeContainer) {
lldb::addr_t load_addr = section_sp->GetFileAddress();
// We don't want to update the load address of a section with type
// eSectionTypeAbsoluteAddress as they already have the absolute load
@@ -892,11 +885,11 @@ AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
}
size_t ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I) {
- return std::distance(m_section_headers.begin(), I) + 1u;
+ return std::distance(m_section_headers.begin(), I);
}
size_t ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const {
- return std::distance(m_section_headers.begin(), I) + 1u;
+ return std::distance(m_section_headers.begin(), I);
}
bool ObjectFileELF::ParseHeader() {
@@ -953,7 +946,7 @@ lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() {
FileSpecList file_spec_list;
if (!m_gnu_debuglink_file.empty()) {
- FileSpec file_spec(m_gnu_debuglink_file, false);
+ FileSpec file_spec(m_gnu_debuglink_file);
file_spec_list.Append(file_spec);
}
return file_spec_list;
@@ -1055,6 +1048,18 @@ lldb_private::Address ObjectFileELF::GetEntryPointAddress() {
return m_entry_point_address;
}
+Address ObjectFileELF::GetBaseAddress() {
+ for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
+ const ELFProgramHeader &H = EnumPHdr.value();
+ if (H.p_type != PT_LOAD)
+ continue;
+
+ return Address(
+ GetSectionList()->FindSectionByID(SegmentID(EnumPHdr.index())), 0);
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
@@ -1084,7 +1089,7 @@ size_t ObjectFileELF::ParseDependentModules() {
return 0;
// sh_link: section header index of string table used by entries in the
// section.
- Section *dynstr = section_list->FindSectionByID(header->sh_link + 1).get();
+ Section *dynstr = section_list->FindSectionByID(header->sh_link).get();
if (!dynstr)
return 0;
@@ -1107,7 +1112,9 @@ size_t ObjectFileELF::ParseDependentModules() {
uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
const char *lib_name = dynstr_data.PeekCStr(str_index);
- m_filespec_ap->Append(FileSpec(lib_name, true));
+ FileSpec file_spec(lib_name);
+ FileSystem::Instance().Resolve(file_spec);
+ m_filespec_ap->Append(file_spec);
}
}
@@ -1141,7 +1148,7 @@ size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
uint32_t idx;
lldb::offset_t offset;
for (idx = 0, offset = 0; idx < header.e_phnum; ++idx) {
- if (program_headers[idx].Parse(data, &offset) == false)
+ if (!program_headers[idx].Parse(data, &offset))
break;
}
@@ -1154,8 +1161,8 @@ size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
//----------------------------------------------------------------------
// ParseProgramHeaders
//----------------------------------------------------------------------
-size_t ObjectFileELF::ParseProgramHeaders() {
- return GetProgramHeaderInfo(m_program_headers, m_data, m_header);
+bool ObjectFileELF::ParseProgramHeaders() {
+ return GetProgramHeaderInfo(m_program_headers, m_data, m_header) != 0;
}
lldb_private::Status
@@ -1390,7 +1397,7 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS)
// In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing for some
// cases (e.g. compile with -nostdlib) Hence set OS to Linux
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
}
}
@@ -1494,7 +1501,7 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
const uint32_t sub_type = subTypeFromElfHeader(header);
arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
header.e_ident[EI_OSABI]);
-
+
// Validate if it is ok to remove GetOsFromOSABI. Note, that now the OS is
// determined based on EI_OSABI flag and the info extracted from ELF notes
// (see RefineModuleDetailsFromNote). However in some cases that still
@@ -1553,7 +1560,7 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
uint32_t idx;
lldb::offset_t offset;
for (idx = 0, offset = 0; idx < header.e_shnum; ++idx) {
- if (section_headers[idx].Parse(sh_data, &offset) == false)
+ if (!section_headers[idx].Parse(sh_data, &offset))
break;
}
if (idx < section_headers.size())
@@ -1701,27 +1708,6 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
return 0;
}
-size_t ObjectFileELF::GetProgramHeaderCount() { return ParseProgramHeaders(); }
-
-const elf::ELFProgramHeader *
-ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id) {
- if (!id || !ParseProgramHeaders())
- return NULL;
-
- if (--id < m_program_headers.size())
- return &m_program_headers[id];
-
- return NULL;
-}
-
-DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) {
- const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
- if (segment_header == NULL)
- return DataExtractor();
- return DataExtractor(m_data, segment_header->p_offset,
- segment_header->p_filesz);
-}
-
llvm::StringRef
ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
size_t pos = symbol_name.find('@');
@@ -1739,10 +1725,10 @@ size_t ObjectFileELF::ParseSectionHeaders() {
const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) {
- if (!id || !ParseSectionHeaders())
+ if (!ParseSectionHeaders())
return NULL;
- if (--id < m_section_headers.size())
+ if (id < m_section_headers.size())
return &m_section_headers[id];
return NULL;
@@ -1757,233 +1743,273 @@ lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
return 0;
}
-void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
- if (!m_sections_ap.get() && ParseSectionHeaders()) {
- m_sections_ap.reset(new SectionList());
-
- // Object files frequently have 0 for every section address, meaning we
- // need to compute synthetic addresses in order for "file addresses" from
- // different sections to not overlap
- bool synthaddrs = (CalculateType() == ObjectFile::Type::eTypeObjectFile);
- uint64_t nextaddr = 0;
-
- for (SectionHeaderCollIter I = m_section_headers.begin();
- I != m_section_headers.end(); ++I) {
- const ELFSectionHeaderInfo &header = *I;
-
- ConstString &name = I->section_name;
- const uint64_t file_size =
- header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
- const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
-
- static ConstString g_sect_name_text(".text");
- static ConstString g_sect_name_data(".data");
- static ConstString g_sect_name_bss(".bss");
- static ConstString g_sect_name_tdata(".tdata");
- static ConstString g_sect_name_tbss(".tbss");
- static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
- static ConstString g_sect_name_dwarf_debug_addr(".debug_addr");
- static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
- static ConstString g_sect_name_dwarf_debug_cu_index(".debug_cu_index");
- static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
- static ConstString g_sect_name_dwarf_debug_info(".debug_info");
- static ConstString g_sect_name_dwarf_debug_line(".debug_line");
- static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
- static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
- static ConstString g_sect_name_dwarf_debug_macro(".debug_macro");
- static ConstString g_sect_name_dwarf_debug_names(".debug_names");
- static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
- static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
- static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
- static ConstString g_sect_name_dwarf_debug_str(".debug_str");
- static ConstString g_sect_name_dwarf_debug_str_offsets(
- ".debug_str_offsets");
- static ConstString g_sect_name_dwarf_debug_abbrev_dwo(
- ".debug_abbrev.dwo");
- static ConstString g_sect_name_dwarf_debug_info_dwo(".debug_info.dwo");
- static ConstString g_sect_name_dwarf_debug_line_dwo(".debug_line.dwo");
- static ConstString g_sect_name_dwarf_debug_macro_dwo(".debug_macro.dwo");
- static ConstString g_sect_name_dwarf_debug_loc_dwo(".debug_loc.dwo");
- static ConstString g_sect_name_dwarf_debug_str_dwo(".debug_str.dwo");
- static ConstString g_sect_name_dwarf_debug_str_offsets_dwo(
- ".debug_str_offsets.dwo");
- static ConstString g_sect_name_dwarf_debug_types(".debug_types");
- static ConstString g_sect_name_eh_frame(".eh_frame");
- static ConstString g_sect_name_arm_exidx(".ARM.exidx");
- static ConstString g_sect_name_arm_extab(".ARM.extab");
- static ConstString g_sect_name_go_symtab(".gosymtab");
- static ConstString g_sect_name_dwarf_gnu_debugaltlink(".gnu_debugaltlink");
-
- SectionType sect_type = eSectionTypeOther;
-
- bool is_thread_specific = false;
-
- if (name == g_sect_name_text)
- sect_type = eSectionTypeCode;
- else if (name == g_sect_name_data)
- sect_type = eSectionTypeData;
- else if (name == g_sect_name_bss)
- sect_type = eSectionTypeZeroFill;
- else if (name == g_sect_name_tdata) {
- sect_type = eSectionTypeData;
- is_thread_specific = true;
- } else if (name == g_sect_name_tbss) {
- sect_type = eSectionTypeZeroFill;
- is_thread_specific = true;
- }
- // .debug_abbrev – Abbreviations used in the .debug_info section
- // .debug_aranges – Lookup table for mapping addresses to compilation
- // units .debug_frame – Call frame information .debug_info – The core
- // DWARF information section .debug_line – Line number information
- // .debug_loc – Location lists used in DW_AT_location attributes
- // .debug_macinfo – Macro information .debug_pubnames – Lookup table
- // for mapping object and function names to compilation units
- // .debug_pubtypes – Lookup table for mapping type names to compilation
- // units .debug_ranges – Address ranges used in DW_AT_ranges attributes
- // .debug_str – String table used in .debug_info MISSING?
- // .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
- // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html MISSING?
- // .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build
- // /gdb-add-index?pathrev=144644 MISSING? .debug_types - Type
- // descriptions from DWARF 4? See
- // http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
- else if (name == g_sect_name_dwarf_debug_abbrev)
- sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_addr)
- sect_type = eSectionTypeDWARFDebugAddr;
- else if (name == g_sect_name_dwarf_debug_aranges)
- sect_type = eSectionTypeDWARFDebugAranges;
- else if (name == g_sect_name_dwarf_debug_cu_index)
- sect_type = eSectionTypeDWARFDebugCuIndex;
- else if (name == g_sect_name_dwarf_debug_frame)
- sect_type = eSectionTypeDWARFDebugFrame;
- else if (name == g_sect_name_dwarf_debug_info)
- sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line)
- sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_loc)
- sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_macinfo)
- sect_type = eSectionTypeDWARFDebugMacInfo;
- else if (name == g_sect_name_dwarf_debug_macro)
- sect_type = eSectionTypeDWARFDebugMacro;
- else if (name == g_sect_name_dwarf_debug_names)
- sect_type = eSectionTypeDWARFDebugNames;
- else if (name == g_sect_name_dwarf_debug_pubnames)
- sect_type = eSectionTypeDWARFDebugPubNames;
- else if (name == g_sect_name_dwarf_debug_pubtypes)
- sect_type = eSectionTypeDWARFDebugPubTypes;
- else if (name == g_sect_name_dwarf_debug_ranges)
- sect_type = eSectionTypeDWARFDebugRanges;
- else if (name == g_sect_name_dwarf_debug_str)
- sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_dwarf_debug_types)
- sect_type = eSectionTypeDWARFDebugTypes;
- else if (name == g_sect_name_dwarf_debug_str_offsets)
- sect_type = eSectionTypeDWARFDebugStrOffsets;
- else if (name == g_sect_name_dwarf_debug_abbrev_dwo)
- sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_info_dwo)
- sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line_dwo)
- sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_macro_dwo)
- sect_type = eSectionTypeDWARFDebugMacro;
- else if (name == g_sect_name_dwarf_debug_loc_dwo)
- sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_str_dwo)
- sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_dwarf_debug_str_offsets_dwo)
- sect_type = eSectionTypeDWARFDebugStrOffsets;
- else if (name == g_sect_name_eh_frame)
- sect_type = eSectionTypeEHFrame;
- else if (name == g_sect_name_arm_exidx)
- sect_type = eSectionTypeARMexidx;
- else if (name == g_sect_name_arm_extab)
- sect_type = eSectionTypeARMextab;
- else if (name == g_sect_name_go_symtab)
- sect_type = eSectionTypeGoSymtab;
- else if (name == g_sect_name_dwarf_gnu_debugaltlink)
- sect_type = eSectionTypeDWARFGNUDebugAltLink;
-
- const uint32_t permissions =
- ((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0u) |
- ((header.sh_flags & SHF_WRITE) ? ePermissionsWritable : 0u) |
- ((header.sh_flags & SHF_EXECINSTR) ? ePermissionsExecutable : 0u);
- switch (header.sh_type) {
- case SHT_SYMTAB:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFSymbolTable;
- break;
- case SHT_DYNSYM:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFDynamicSymbols;
- break;
- case SHT_RELA:
- case SHT_REL:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFRelocationEntries;
- break;
- case SHT_DYNAMIC:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFDynamicLinkInfo;
- break;
- }
+static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
+ return llvm::StringSwitch<SectionType>(Name)
+ .Case(".ARM.exidx", eSectionTypeARMexidx)
+ .Case(".ARM.extab", eSectionTypeARMextab)
+ .Cases(".bss", ".tbss", eSectionTypeZeroFill)
+ .Cases(".data", ".tdata", eSectionTypeData)
+ .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
+ .Case(".debug_abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo)
+ .Case(".debug_addr", eSectionTypeDWARFDebugAddr)
+ .Case(".debug_aranges", eSectionTypeDWARFDebugAranges)
+ .Case(".debug_cu_index", eSectionTypeDWARFDebugCuIndex)
+ .Case(".debug_frame", eSectionTypeDWARFDebugFrame)
+ .Case(".debug_info", eSectionTypeDWARFDebugInfo)
+ .Case(".debug_info.dwo", eSectionTypeDWARFDebugInfoDwo)
+ .Cases(".debug_line", ".debug_line.dwo", eSectionTypeDWARFDebugLine)
+ .Cases(".debug_line_str", ".debug_line_str.dwo",
+ eSectionTypeDWARFDebugLineStr)
+ .Cases(".debug_loc", ".debug_loc.dwo", eSectionTypeDWARFDebugLoc)
+ .Cases(".debug_loclists", ".debug_loclists.dwo",
+ eSectionTypeDWARFDebugLocLists)
+ .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo)
+ .Cases(".debug_macro", ".debug_macro.dwo", eSectionTypeDWARFDebugMacro)
+ .Case(".debug_names", eSectionTypeDWARFDebugNames)
+ .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
+ .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
+ .Case(".debug_ranges", eSectionTypeDWARFDebugRanges)
+ .Case(".debug_rnglists", eSectionTypeDWARFDebugRngLists)
+ .Case(".debug_str", eSectionTypeDWARFDebugStr)
+ .Case(".debug_str.dwo", eSectionTypeDWARFDebugStrDwo)
+ .Case(".debug_str_offsets", eSectionTypeDWARFDebugStrOffsets)
+ .Case(".debug_str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)
+ .Case(".debug_types", eSectionTypeDWARFDebugTypes)
+ .Case(".eh_frame", eSectionTypeEHFrame)
+ .Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
+ .Case(".gosymtab", eSectionTypeGoSymtab)
+ .Case(".text", eSectionTypeCode)
+ .Default(eSectionTypeOther);
+}
+
+SectionType ObjectFileELF::GetSectionType(const ELFSectionHeaderInfo &H) const {
+ switch (H.sh_type) {
+ case SHT_PROGBITS:
+ if (H.sh_flags & SHF_EXECINSTR)
+ return eSectionTypeCode;
+ break;
+ case SHT_SYMTAB:
+ return eSectionTypeELFSymbolTable;
+ case SHT_DYNSYM:
+ return eSectionTypeELFDynamicSymbols;
+ case SHT_RELA:
+ case SHT_REL:
+ return eSectionTypeELFRelocationEntries;
+ case SHT_DYNAMIC:
+ return eSectionTypeELFDynamicLinkInfo;
+ }
+ SectionType Type = GetSectionTypeFromName(H.section_name.GetStringRef());
+ if (Type == eSectionTypeOther) {
+ // the kalimba toolchain assumes that ELF section names are free-form.
+ // It does support linkscripts which (can) give rise to various
+ // arbitrarily named sections being "Code" or "Data".
+ Type = kalimbaSectionType(m_header, H);
+ }
+ return Type;
+}
+
+static uint32_t GetTargetByteSize(SectionType Type, const ArchSpec &arch) {
+ switch (Type) {
+ case eSectionTypeData:
+ case eSectionTypeZeroFill:
+ return arch.GetDataByteSize();
+ case eSectionTypeCode:
+ return arch.GetCodeByteSize();
+ default:
+ return 1;
+ }
+}
- if (eSectionTypeOther == sect_type) {
- // the kalimba toolchain assumes that ELF section names are free-form.
- // It does support linkscripts which (can) give rise to various
- // arbitrarily named sections being "Code" or "Data".
- sect_type = kalimbaSectionType(m_header, header);
- }
+static Permissions GetPermissions(const ELFSectionHeader &H) {
+ Permissions Perm = Permissions(0);
+ if (H.sh_flags & SHF_ALLOC)
+ Perm |= ePermissionsReadable;
+ if (H.sh_flags & SHF_WRITE)
+ Perm |= ePermissionsWritable;
+ if (H.sh_flags & SHF_EXECINSTR)
+ Perm |= ePermissionsExecutable;
+ return Perm;
+}
- // In common case ELF code section can have arbitrary name (for example,
- // we can specify it using section attribute for particular function) so
- // assume that section is a code section if it has SHF_EXECINSTR flag set
- // and has SHT_PROGBITS type.
- if (eSectionTypeOther == sect_type &&
- llvm::ELF::SHT_PROGBITS == header.sh_type &&
- (header.sh_flags & SHF_EXECINSTR)) {
- sect_type = eSectionTypeCode;
- }
+static Permissions GetPermissions(const ELFProgramHeader &H) {
+ Permissions Perm = Permissions(0);
+ if (H.p_flags & PF_R)
+ Perm |= ePermissionsReadable;
+ if (H.p_flags & PF_W)
+ Perm |= ePermissionsWritable;
+ if (H.p_flags & PF_X)
+ Perm |= ePermissionsExecutable;
+ return Perm;
+}
- const uint32_t target_bytes_size =
- (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type)
- ? m_arch_spec.GetDataByteSize()
- : eSectionTypeCode == sect_type ? m_arch_spec.GetCodeByteSize()
- : 1;
- elf::elf_xword log2align =
- (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);
-
- uint64_t addr = header.sh_addr;
-
- if ((header.sh_flags & SHF_ALLOC) && synthaddrs) {
- nextaddr =
- (nextaddr + header.sh_addralign - 1) & ~(header.sh_addralign - 1);
- addr = nextaddr;
- nextaddr += vm_size;
- }
+namespace {
+
+using VMRange = lldb_private::Range<addr_t, addr_t>;
- SectionSP section_sp(new Section(
- GetModule(), // Module to which this section belongs.
- this, // ObjectFile to which this section belongs and should read
- // section data from.
- SectionIndex(I), // Section ID.
- name, // Section name.
- sect_type, // Section type.
- addr, // VM address.
- vm_size, // VM size in bytes of this section.
- header.sh_offset, // Offset of this section in the file.
- file_size, // Size of the section as found in the file.
- log2align, // Alignment of the section
- header.sh_flags, // Flags for this section.
- target_bytes_size)); // Number of host bytes per target byte
-
- section_sp->SetPermissions(permissions);
- if (is_thread_specific)
- section_sp->SetIsThreadSpecific(is_thread_specific);
- m_sections_ap->AddSection(section_sp);
+struct SectionAddressInfo {
+ SectionSP Segment;
+ VMRange Range;
+};
+
+// (Unlinked) ELF object files usually have 0 for every section address, meaning
+// we need to compute synthetic addresses in order for "file addresses" from
+// different sections to not overlap. This class handles that logic.
+class VMAddressProvider {
+ using VMMap = llvm::IntervalMap<addr_t, SectionSP, 4,
+ llvm::IntervalMapHalfOpenInfo<addr_t>>;
+
+ ObjectFile::Type ObjectType;
+ addr_t NextVMAddress = 0;
+ VMMap::Allocator Alloc;
+ VMMap Segments = VMMap(Alloc);
+ VMMap Sections = VMMap(Alloc);
+ lldb_private::Log *Log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+
+ VMRange GetVMRange(const ELFSectionHeader &H) {
+ addr_t Address = H.sh_addr;
+ addr_t Size = H.sh_flags & SHF_ALLOC ? H.sh_size : 0;
+ if (ObjectType == ObjectFile::Type::eTypeObjectFile && Segments.empty() && (H.sh_flags & SHF_ALLOC)) {
+ NextVMAddress =
+ llvm::alignTo(NextVMAddress, std::max<addr_t>(H.sh_addralign, 1));
+ Address = NextVMAddress;
+ NextVMAddress += Size;
}
+ return VMRange(Address, Size);
+ }
+
+public:
+ VMAddressProvider(ObjectFile::Type Type) : ObjectType(Type) {}
+
+ llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) {
+ if (H.p_memsz == 0) {
+ LLDB_LOG(Log,
+ "Ignoring zero-sized PT_LOAD segment. Corrupt object file?");
+ return llvm::None;
+ }
+
+ if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) {
+ LLDB_LOG(Log,
+ "Ignoring overlapping PT_LOAD segment. Corrupt object file?");
+ return llvm::None;
+ }
+ return VMRange(H.p_vaddr, H.p_memsz);
+ }
+
+ llvm::Optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) {
+ VMRange Range = GetVMRange(H);
+ SectionSP Segment;
+ auto It = Segments.find(Range.GetRangeBase());
+ if ((H.sh_flags & SHF_ALLOC) && It.valid()) {
+ addr_t MaxSize;
+ if (It.start() <= Range.GetRangeBase()) {
+ MaxSize = It.stop() - Range.GetRangeBase();
+ Segment = *It;
+ } else
+ MaxSize = It.start() - Range.GetRangeBase();
+ if (Range.GetByteSize() > MaxSize) {
+ LLDB_LOG(Log, "Shortening section crossing segment boundaries. "
+ "Corrupt object file?");
+ Range.SetByteSize(MaxSize);
+ }
+ }
+ if (Range.GetByteSize() > 0 &&
+ Sections.overlaps(Range.GetRangeBase(), Range.GetRangeEnd())) {
+ LLDB_LOG(Log, "Ignoring overlapping section. Corrupt object file?");
+ return llvm::None;
+ }
+ if (Segment)
+ Range.Slide(-Segment->GetFileAddress());
+ return SectionAddressInfo{Segment, Range};
+ }
+
+ void AddSegment(const VMRange &Range, SectionSP Seg) {
+ Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg));
+ }
+
+ void AddSection(SectionAddressInfo Info, SectionSP Sect) {
+ if (Info.Range.GetByteSize() == 0)
+ return;
+ if (Info.Segment)
+ Info.Range.Slide(Info.Segment->GetFileAddress());
+ Sections.insert(Info.Range.GetRangeBase(), Info.Range.GetRangeEnd(),
+ std::move(Sect));
+ }
+};
+}
+
+void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
+ if (m_sections_ap)
+ return;
+
+ m_sections_ap = llvm::make_unique<SectionList>();
+ VMAddressProvider address_provider(CalculateType());
+
+ size_t LoadID = 0;
+ for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
+ const ELFProgramHeader &PHdr = EnumPHdr.value();
+ if (PHdr.p_type != PT_LOAD)
+ continue;
+
+ auto InfoOr = address_provider.GetAddressInfo(PHdr);
+ if (!InfoOr)
+ continue;
+
+ ConstString Name(("PT_LOAD[" + llvm::Twine(LoadID++) + "]").str());
+ uint32_t Log2Align = llvm::Log2_64(std::max<elf_xword>(PHdr.p_align, 1));
+ SectionSP Segment = std::make_shared<Section>(
+ GetModule(), this, SegmentID(EnumPHdr.index()), Name,
+ eSectionTypeContainer, InfoOr->GetRangeBase(), InfoOr->GetByteSize(),
+ PHdr.p_offset, PHdr.p_filesz, Log2Align, /*flags*/ 0);
+ Segment->SetPermissions(GetPermissions(PHdr));
+ m_sections_ap->AddSection(Segment);
+
+ address_provider.AddSegment(*InfoOr, std::move(Segment));
+ }
+
+ ParseSectionHeaders();
+ if (m_section_headers.empty())
+ return;
+
+ for (SectionHeaderCollIter I = std::next(m_section_headers.begin());
+ I != m_section_headers.end(); ++I) {
+ const ELFSectionHeaderInfo &header = *I;
+
+ ConstString &name = I->section_name;
+ const uint64_t file_size =
+ header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+
+ auto InfoOr = address_provider.GetAddressInfo(header);
+ if (!InfoOr)
+ continue;
+
+ SectionType sect_type = GetSectionType(header);
+
+ const uint32_t target_bytes_size =
+ GetTargetByteSize(sect_type, m_arch_spec);
+
+ elf::elf_xword log2align =
+ (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);
+
+ SectionSP section_sp(new Section(
+ InfoOr->Segment, GetModule(), // Module to which this section belongs.
+ this, // ObjectFile to which this section belongs and should
+ // read section data from.
+ SectionIndex(I), // Section ID.
+ name, // Section name.
+ sect_type, // Section type.
+ InfoOr->Range.GetRangeBase(), // VM address.
+ InfoOr->Range.GetByteSize(), // VM size in bytes of this section.
+ header.sh_offset, // Offset of this section in the file.
+ file_size, // Size of the section as found in the file.
+ log2align, // Alignment of the section
+ header.sh_flags, // Flags for this section.
+ target_bytes_size)); // Number of host bytes per target byte
+
+ section_sp->SetPermissions(GetPermissions(header));
+ section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS);
+ (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_ap)
+ .AddSection(section_sp);
+ address_provider.AddSection(std::move(*InfoOr), std::move(section_sp));
}
// For eTypeDebugInfo files, the Symbol Vendor will take care of updating the
@@ -2050,8 +2076,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
file_extension == ConstString(".odex");
- ArchSpec arch;
- GetArchitecture(arch);
+ ArchSpec arch = GetArchitecture();
ModuleSP module_sp(GetModule());
SectionList *module_section_list =
module_sp ? module_sp->GetSectionList() : nullptr;
@@ -2063,7 +2088,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
unsigned i;
for (i = 0; i < num_symbols; ++i) {
- if (symbol.Parse(symtab_data, &offset) == false)
+ if (!symbol.Parse(symtab_data, &offset))
break;
const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
@@ -2083,9 +2108,9 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
SectionSP symbol_section_sp;
SymbolType symbol_type = eSymbolTypeInvalid;
- Elf64_Half section_idx = symbol.st_shndx;
+ Elf64_Half shndx = symbol.st_shndx;
- switch (section_idx) {
+ switch (shndx) {
case SHN_ABS:
symbol_type = eSymbolTypeAbsolute;
break;
@@ -2093,7 +2118,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
symbol_type = eSymbolTypeUndefined;
break;
default:
- symbol_section_sp = section_list->GetSectionAtIndex(section_idx);
+ symbol_section_sp = section_list->FindSectionByID(shndx);
break;
}
@@ -2262,7 +2287,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
// symbols. See above for more details.
uint64_t symbol_value = symbol.st_value + symbol_value_offset;
- if (symbol_section_sp == nullptr && section_idx == SHN_ABS &&
+ if (symbol_section_sp == nullptr && shndx == SHN_ABS &&
symbol.st_size != 0) {
// We don't have a section for a symbol with non-zero size. Create a new
// section for it so the address range covered by the symbol is also
@@ -2375,9 +2400,8 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
- // sh_link: section header index of associated string table. Section ID's are
- // ones based.
- user_id_t strtab_id = symtab_hdr->sh_link + 1;
+ // sh_link: section header index of associated string table.
+ user_id_t strtab_id = symtab_hdr->sh_link;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
if (symtab && strtab) {
@@ -2529,7 +2553,7 @@ static unsigned ParsePLTRelocations(
unsigned slot_type = hdr->GetRelocationJumpSlotType();
unsigned i;
for (i = 0; i < num_relocations; ++i) {
- if (rel.Parse(rel_data, &offset) == false)
+ if (!rel.Parse(rel_data, &offset))
break;
if (reloc_type(rel) != slot_type)
@@ -2587,10 +2611,6 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
if (!symtab_id || !plt_id)
return 0;
- // Section ID's are ones based;
- symtab_id++;
- plt_id++;
-
const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
if (!plt_hdr)
return 0;
@@ -2616,7 +2636,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
return 0;
// sh_link points to associated string table.
- Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
+ Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link).get();
if (!strtab)
return 0;
@@ -2662,7 +2682,7 @@ unsigned ObjectFileELF::ApplyRelocations(
}
for (unsigned i = 0; i < num_relocations; ++i) {
- if (rel.Parse(rel_data, &offset) == false)
+ if (!rel.Parse(rel_data, &offset))
break;
Symbol *symbol = NULL;
@@ -2684,6 +2704,7 @@ unsigned ObjectFileELF::ApplyRelocations(
}
} else {
switch (reloc_type(rel)) {
+ case R_AARCH64_ABS64:
case R_X86_64_64: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
@@ -2692,26 +2713,34 @@ unsigned ObjectFileELF::ApplyRelocations(
uint64_t *dst = reinterpret_cast<uint64_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset64(rel));
- *dst = value + ELFRelocation::RelocAddend64(rel);
+ uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
+ memcpy(dst, &val_offset, sizeof(uint64_t));
}
break;
}
case R_X86_64_32:
- case R_X86_64_32S: {
+ case R_X86_64_32S:
+ case R_AARCH64_ABS32: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
addr_t value = symbol->GetAddressRef().GetFileAddress();
value += ELFRelocation::RelocAddend32(rel);
- assert(
- (reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
+ if ((reloc_type(rel) == R_X86_64_32 && (value > UINT32_MAX)) ||
(reloc_type(rel) == R_X86_64_32S &&
- ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
+ ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN)) ||
+ (reloc_type(rel) == R_AARCH64_ABS32 &&
+ ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) {
+ Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+ log->Printf("Failed to apply debug info relocations");
+ break;
+ }
uint32_t truncated_addr = (value & 0xFFFFFFFF);
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
uint32_t *dst = reinterpret_cast<uint32_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset32(rel));
- *dst = truncated_addr;
+ memcpy(dst, &truncated_addr, sizeof(uint32_t));
}
break;
}
@@ -2735,9 +2764,8 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
if (!section_list)
return 0;
- // Section ID's are ones based.
- user_id_t symtab_id = rel_hdr->sh_link + 1;
- user_id_t debug_id = rel_hdr->sh_info + 1;
+ user_id_t symtab_id = rel_hdr->sh_link;
+ user_id_t debug_id = rel_hdr->sh_info;
const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
if (!symtab_hdr)
@@ -2975,8 +3003,7 @@ void ObjectFileELF::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFileELF");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', arch = " << header_arch.GetArchitectureName() << "\n";
@@ -3153,11 +3180,9 @@ void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
s->PutCString("==== --------------- -------- -------- -------- "
"-------- -------- ------------------------- --------\n");
- uint32_t idx = 0;
- for (ProgramHeaderCollConstIter I = m_program_headers.begin();
- I != m_program_headers.end(); ++I, ++idx) {
- s->Printf("[%2u] ", idx);
- ObjectFileELF::DumpELFProgramHeader(s, *I);
+ for (const auto &H : llvm::enumerate(m_program_headers)) {
+ s->Format("[{0,2}] ", H.index());
+ ObjectFileELF::DumpELFProgramHeader(s, H.value());
s->EOL();
}
}
@@ -3264,9 +3289,9 @@ void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) {
}
}
-bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFileELF::GetArchitecture() {
if (!ParseHeader())
- return false;
+ return ArchSpec();
if (m_section_headers.empty()) {
// Allow elf notes to be parsed which may affect the detected architecture.
@@ -3277,23 +3302,17 @@ bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
// Core files don't have section headers yet they have PT_NOTE program
// headers that might shed more light on the architecture
- if (ParseProgramHeaders()) {
- for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
- const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
- if (header && header->p_type == PT_NOTE && header->p_offset != 0 &&
- header->p_filesz > 0) {
- DataExtractor data;
- if (data.SetData(m_data, header->p_offset, header->p_filesz) ==
- header->p_filesz) {
- lldb_private::UUID uuid;
- RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
- }
- }
+ for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
+ if (H.p_type != PT_NOTE || H.p_offset == 0 || H.p_filesz == 0)
+ continue;
+ DataExtractor data;
+ if (data.SetData(m_data, H.p_offset, H.p_filesz) == H.p_filesz) {
+ UUID uuid;
+ RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
}
}
}
- arch = m_arch_spec;
- return true;
+ return m_arch_spec;
}
ObjectFile::Type ObjectFileELF::CalculateType() {
@@ -3385,8 +3404,6 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
if (section->GetObjectFile() != this)
return section->GetObjectFile()->ReadSectionData(section, section_data);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
-
size_t result = ObjectFile::ReadSectionData(section, section_data);
if (result == 0 || !section->Test(SHF_COMPRESSED))
return result;
@@ -3397,29 +3414,43 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
size_t(section_data.GetByteSize())},
GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
if (!Decompressor) {
- LLDB_LOG_ERROR(log, Decompressor.takeError(),
- "Unable to initialize decompressor for section {0}",
- section->GetName());
- return result;
+ GetModule()->ReportWarning(
+ "Unable to initialize decompressor for section '%s': %s",
+ section->GetName().GetCString(),
+ llvm::toString(Decompressor.takeError()).c_str());
+ section_data.Clear();
+ return 0;
}
+
auto buffer_sp =
std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0);
- if (auto Error = Decompressor->decompress(
+ if (auto error = Decompressor->decompress(
{reinterpret_cast<char *>(buffer_sp->GetBytes()),
size_t(buffer_sp->GetByteSize())})) {
- LLDB_LOG_ERROR(log, std::move(Error), "Decompression of section {0} failed",
- section->GetName());
- return result;
+ GetModule()->ReportWarning(
+ "Decompression of section '%s' failed: %s",
+ section->GetName().GetCString(),
+ llvm::toString(std::move(error)).c_str());
+ section_data.Clear();
+ return 0;
}
+
section_data.SetData(buffer_sp);
return buffer_sp->GetByteSize();
}
+llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() {
+ ParseProgramHeaders();
+ return m_program_headers;
+}
+
+DataExtractor ObjectFileELF::GetSegmentData(const ELFProgramHeader &H) {
+ return DataExtractor(m_data, H.p_offset, H.p_filesz);
+}
+
bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
- size_t header_count = ParseProgramHeaders();
- for (size_t i = 1; i <= header_count; ++i) {
- auto header = GetProgramHeaderByIndex(i);
- if (header->p_paddr != 0)
+ for (const ELFProgramHeader &H : ProgramHeaders()) {
+ if (H.p_paddr != 0)
return true;
}
return false;
@@ -3430,19 +3461,17 @@ ObjectFileELF::GetLoadableData(Target &target) {
// Create a list of loadable data from loadable segments, using physical
// addresses if they aren't all null
std::vector<LoadableData> loadables;
- size_t header_count = ParseProgramHeaders();
bool should_use_paddr = AnySegmentHasPhysicalAddress();
- for (size_t i = 1; i <= header_count; ++i) {
+ for (const ELFProgramHeader &H : ProgramHeaders()) {
LoadableData loadable;
- auto header = GetProgramHeaderByIndex(i);
- if (header->p_type != llvm::ELF::PT_LOAD)
+ if (H.p_type != llvm::ELF::PT_LOAD)
continue;
- loadable.Dest = should_use_paddr ? header->p_paddr : header->p_vaddr;
+ loadable.Dest = should_use_paddr ? H.p_paddr : H.p_vaddr;
if (loadable.Dest == LLDB_INVALID_ADDRESS)
continue;
- if (header->p_filesz == 0)
+ if (H.p_filesz == 0)
continue;
- auto segment_data = GetSegmentDataByIndex(i);
+ auto segment_data = GetSegmentData(H);
loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
segment_data.GetByteSize());
loadables.push_back(loadable);
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 2664595fd81d..08fd5bdc60a9 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -10,10 +10,8 @@
#ifndef liblldb_ObjectFileELF_h_
#define liblldb_ObjectFileELF_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <vector>
#include "lldb/Symbol/ObjectFile.h"
@@ -123,7 +121,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -136,6 +134,8 @@ public:
lldb_private::Address GetEntryPointAddress() override;
+ lldb_private::Address GetBaseAddress() override;
+
ObjectFile::Type CalculateType() override;
ObjectFile::Strata CalculateStrata() override;
@@ -147,14 +147,8 @@ public:
size_t ReadSectionData(lldb_private::Section *section,
lldb_private::DataExtractor &section_data) override;
- // Returns number of program headers found in the ELF file.
- size_t GetProgramHeaderCount();
-
- // Returns the program header with the given index.
- const elf::ELFProgramHeader *GetProgramHeaderByIndex(lldb::user_id_t id);
-
- // Returns segment data for the given index.
- lldb_private::DataExtractor GetSegmentDataByIndex(lldb::user_id_t id);
+ llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();
+ lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);
llvm::StringRef
StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
@@ -176,8 +170,6 @@ private:
const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
- typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
- typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {
lldb_private::ConstString section_name;
@@ -230,10 +222,10 @@ private:
/// The address class for each symbol in the elf file
FileAddressToAddressClassMap m_address_class_map;
- /// Returns a 1 based index of the given section header.
+ /// Returns the index of the given section header.
size_t SectionIndex(const SectionHeaderCollIter &I);
- /// Returns a 1 based index of the given section header.
+ /// Returns the index of the given section header.
size_t SectionIndex(const SectionHeaderCollConstIter &I) const;
// Parses the ELF program headers.
@@ -248,14 +240,16 @@ private:
/// Parses all section headers present in this object file and populates
/// m_program_headers. This method will compute the header list only once.
- /// Returns the number of headers parsed.
- size_t ParseProgramHeaders();
+ /// Returns true iff the headers have been successfully parsed.
+ bool ParseProgramHeaders();
/// Parses all section headers present in this object file and populates
/// m_section_headers. This method will compute the header list only once.
/// Returns the number of headers parsed.
size_t ParseSectionHeaders();
+ lldb::SectionType GetSectionType(const ELFSectionHeaderInfo &H) const;
+
static void ParseARMAttributes(lldb_private::DataExtractor &data,
uint64_t length,
lldb_private::ArchSpec &arch_spec);
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index af040322ec52..cfe61992be0d 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -153,8 +153,7 @@ void ObjectFileJIT::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFileJIT");
- ArchSpec arch;
- if (GetArchitecture(arch))
+ if (ArchSpec arch = GetArchitecture())
*s << ", arch = " << arch.GetArchitectureName();
s->EOL();
@@ -184,17 +183,16 @@ lldb_private::Address ObjectFileJIT::GetEntryPointAddress() {
return Address();
}
-lldb_private::Address ObjectFileJIT::GetHeaderAddress() { return Address(); }
+lldb_private::Address ObjectFileJIT::GetBaseAddress() { return Address(); }
ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; }
ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; }
-bool ObjectFileJIT::GetArchitecture(ArchSpec &arch) {
- ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
- if (delegate_sp)
- return delegate_sp->GetArchitecture(arch);
- return false;
+ArchSpec ObjectFileJIT::GetArchitecture() {
+ if (ObjectFileJITDelegateSP delegate_sp = m_delegate_wp.lock())
+ return delegate_sp->GetArchitecture();
+ return ArchSpec();
}
//------------------------------------------------------------------
@@ -218,7 +216,7 @@ bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
// that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->GetFileSize() > 0 &&
- section_sp->IsThreadSpecific() == false) {
+ !section_sp->IsThreadSpecific()) {
if (target.GetSectionLoadList().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress() + value))
++num_loaded_sections;
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
index c964906a5e8e..3d9e4748d3df 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ObjectFileJIT_h_
#define liblldb_ObjectFileJIT_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -77,7 +73,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -93,7 +89,7 @@ public:
lldb_private::Address GetEntryPointAddress() override;
- lldb_private::Address GetHeaderAddress() override;
+ lldb_private::Address GetBaseAddress() override;
ObjectFile::Type CalculateType() override;
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 91e7f3353270..06908fecf984 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
@@ -23,7 +19,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RangeMap.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Host.h"
@@ -41,12 +36,13 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
-#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Host/SafeMachO.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -919,12 +915,10 @@ size_t ObjectFileMachO::GetModuleSpecifications(
spec.SetObjectOffset(file_offset);
spec.SetObjectSize(length);
- if (GetArchitecture(header, data, data_offset,
- spec.GetArchitecture())) {
- if (spec.GetArchitecture().IsValid()) {
- GetUUID(header, data, data_offset, spec.GetUUID());
- specs.Append(spec);
- }
+ spec.GetArchitecture() = GetArchitecture(header, data, data_offset);
+ if (spec.GetArchitecture().IsValid()) {
+ GetUUID(header, data, data_offset, spec.GetUUID());
+ specs.Append(spec);
}
}
}
@@ -962,6 +956,11 @@ const ConstString &ObjectFileMachO::GetSegmentNameLINKEDIT() {
return g_section_name_LINKEDIT;
}
+const ConstString &ObjectFileMachO::GetSegmentNameDWARF() {
+ static ConstString g_section_name("__DWARF");
+ return g_section_name;
+}
+
const ConstString &ObjectFileMachO::GetSectionNameEHFrame() {
static ConstString g_section_name_eh_frame("__eh_frame");
return g_section_name_eh_frame;
@@ -1102,9 +1101,7 @@ bool ObjectFileMachO::ParseHeader() {
if (can_parse) {
m_data.GetU32(&offset, &m_header.cputype, 6);
- ArchSpec mach_arch;
-
- if (GetArchitecture(mach_arch)) {
+ if (ArchSpec mach_arch = GetArchitecture()) {
// Check if the module has a required architecture
const ArchSpec &module_arch = module_sp->GetArchitecture();
if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch))
@@ -1191,21 +1188,28 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
+ case eSectionTypeDWARFDebugAbbrevDwo:
case eSectionTypeDWARFDebugAddr:
case eSectionTypeDWARFDebugAranges:
case eSectionTypeDWARFDebugCuIndex:
case eSectionTypeDWARFDebugFrame:
case eSectionTypeDWARFDebugInfo:
+ case eSectionTypeDWARFDebugInfoDwo:
case eSectionTypeDWARFDebugLine:
+ case eSectionTypeDWARFDebugLineStr:
case eSectionTypeDWARFDebugLoc:
+ case eSectionTypeDWARFDebugLocLists:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
case eSectionTypeDWARFDebugNames:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
case eSectionTypeDWARFDebugStr:
+ case eSectionTypeDWARFDebugStrDwo:
case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugStrOffsetsDwo:
case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
@@ -1455,6 +1459,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
static ConstString g_sect_name_dwarf_debug_info("__debug_info");
static ConstString g_sect_name_dwarf_debug_line("__debug_line");
static ConstString g_sect_name_dwarf_debug_loc("__debug_loc");
+ static ConstString g_sect_name_dwarf_debug_loclists("__debug_loclists");
static ConstString g_sect_name_dwarf_debug_macinfo("__debug_macinfo");
static ConstString g_sect_name_dwarf_debug_names("__debug_names");
static ConstString g_sect_name_dwarf_debug_pubnames("__debug_pubnames");
@@ -1484,6 +1489,8 @@ static lldb::SectionType GetSectionType(uint32_t flags,
return eSectionTypeDWARFDebugLine;
if (section_name == g_sect_name_dwarf_debug_loc)
return eSectionTypeDWARFDebugLoc;
+ if (section_name == g_sect_name_dwarf_debug_loclists)
+ return eSectionTypeDWARFDebugLocLists;
if (section_name == g_sect_name_dwarf_debug_macinfo)
return eSectionTypeDWARFDebugMacInfo;
if (section_name == g_sect_name_dwarf_debug_names)
@@ -1493,7 +1500,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
if (section_name == g_sect_name_dwarf_debug_pubtypes)
return eSectionTypeDWARFDebugPubTypes;
if (section_name == g_sect_name_dwarf_debug_ranges)
- return eSectionTypeDWARFDebugRanges;
+ return eSectionTypeDWARFDebugRanges;
if (section_name == g_sect_name_dwarf_debug_str)
return eSectionTypeDWARFDebugStr;
if (section_name == g_sect_name_dwarf_debug_types)
@@ -1668,7 +1675,7 @@ void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_,
} else if (unified_section_sp) {
if (is_dsym && unified_section_sp->GetFileAddress() != load_cmd.vmaddr) {
// Check to see if the module was read from memory?
- if (module_sp->GetObjectFile()->GetHeaderAddress().IsValid()) {
+ if (module_sp->GetObjectFile()->GetBaseAddress().IsValid()) {
// We have a module that is in memory and needs to have its file
// address adjusted. We need to do this because when we load a file
// from memory, its addresses will be slid already, yet the addresses
@@ -2177,7 +2184,7 @@ size_t ObjectFileMachO::ParseSymtab() {
uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
const char *path = m_data.PeekCStr(name_offset);
if (path) {
- FileSpec file_spec(path, false);
+ FileSpec file_spec(path);
// Strip the path if there is @rpath, @executable, etc so we just use
// the basename
if (path[0] == '@')
@@ -2331,14 +2338,6 @@ size_t ObjectFileMachO::ParseSymtab() {
if (nlist_data_sp)
nlist_data.SetData(nlist_data_sp, 0,
nlist_data_sp->GetByteSize());
- // Load strings individually from memory when loading from memory
- // since shared cache string tables contain strings for all symbols
- // from all shared cached libraries DataBufferSP strtab_data_sp
- // (ReadMemory (process_sp, strtab_addr,
- // strtab_data_byte_size));
- // if (strtab_data_sp)
- // strtab_data.SetData (strtab_data_sp, 0,
- // strtab_data_sp->GetByteSize());
if (m_dysymtab.nindirectsyms != 0) {
const addr_t indirect_syms_addr = linkedit_load_addr +
m_dysymtab.indirectsymoff -
@@ -2350,8 +2349,25 @@ size_t ObjectFileMachO::ParseSymtab() {
indirect_symbol_index_data.SetData(
indirect_syms_data_sp, 0,
indirect_syms_data_sp->GetByteSize());
+ // If this binary is outside the shared cache,
+ // cache the string table.
+ // Binaries in the shared cache all share a giant string table, and
+ // we can't share the string tables across multiple ObjectFileMachO's,
+ // so we'd end up re-reading this mega-strtab for every binary
+ // in the shared cache - it would be a big perf problem.
+ // For binaries outside the shared cache, it's faster to read the
+ // entire strtab at once instead of piece-by-piece as we process
+ // the nlist records.
+ if ((m_header.flags & 0x80000000u) == 0) {
+ DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr,
+ strtab_data_byte_size));
+ if (strtab_data_sp) {
+ strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
+ }
+ }
}
- } else if (memory_module_load_level >=
+ }
+ if (memory_module_load_level >=
eMemoryModuleLoadLevelPartial) {
if (function_starts_load_command.cmd) {
const addr_t func_start_addr =
@@ -2621,7 +2637,7 @@ size_t ObjectFileMachO::ParseSymtab() {
// shared cache UUID in the development or non-development shared caches
// on disk.
if (process_shared_cache_uuid.IsValid()) {
- if (dsc_development_filespec.Exists()) {
+ if (FileSystem::Instance().Exists(dsc_development_filespec)) {
UUID dsc_development_uuid = GetSharedCacheUUID(
dsc_development_filespec, byte_order, addr_byte_size);
if (dsc_development_uuid.IsValid() &&
@@ -2630,7 +2646,8 @@ size_t ObjectFileMachO::ParseSymtab() {
dsc_uuid = dsc_development_uuid;
}
}
- if (!dsc_uuid.IsValid() && dsc_nondevelopment_filespec.Exists()) {
+ if (!dsc_uuid.IsValid() &&
+ FileSystem::Instance().Exists(dsc_nondevelopment_filespec)) {
UUID dsc_nondevelopment_uuid = GetSharedCacheUUID(
dsc_nondevelopment_filespec, byte_order, addr_byte_size);
if (dsc_nondevelopment_uuid.IsValid() &&
@@ -2643,8 +2660,8 @@ size_t ObjectFileMachO::ParseSymtab() {
// Failing a UUID match, prefer the development dyld_shared cache if both
// are present.
- if (!dsc_filespec.Exists()) {
- if (dsc_development_filespec.Exists()) {
+ if (!FileSystem::Instance().Exists(dsc_filespec)) {
+ if (FileSystem::Instance().Exists(dsc_development_filespec)) {
dsc_filespec = dsc_development_filespec;
} else {
dsc_filespec = dsc_nondevelopment_filespec;
@@ -3052,11 +3069,11 @@ size_t ObjectFileMachO::ParseSymtab() {
// file so you end up with a path that looks
// like "/tmp/src//tmp/src/"
FileSpec so_dir(so_path, false);
- if (!so_dir.Exists()) {
+ if (!FileSystem::Instance().Exists(so_dir)) {
so_dir.SetFile(
&full_so_path[double_slash_pos + 1],
false);
- if (so_dir.Exists()) {
+ if (FileSystem::Instance().Exists(so_dir)) {
// Trim off the incorrect path
full_so_path.erase(0,
double_slash_pos + 1);
@@ -4001,11 +4018,11 @@ size_t ObjectFileMachO::ParseSymtab() {
// string in the DW_AT_comp_dir, and the second is the
// directory for the source file so you end up with a path
// that looks like "/tmp/src//tmp/src/"
- FileSpec so_dir(so_path, false);
- if (!so_dir.Exists()) {
- so_dir.SetFile(&full_so_path[double_slash_pos + 1], false,
+ FileSpec so_dir(so_path);
+ if (!FileSystem::Instance().Exists(so_dir)) {
+ so_dir.SetFile(&full_so_path[double_slash_pos + 1],
FileSpec::Style::native);
- if (so_dir.Exists()) {
+ if (FileSystem::Instance().Exists(so_dir)) {
// Trim off the incorrect path
full_so_path.erase(0, double_slash_pos + 1);
}
@@ -4453,7 +4470,7 @@ size_t ObjectFileMachO::ParseSymtab() {
symbol_value -= section_file_addr;
}
- if (is_debug == false) {
+ if (!is_debug) {
if (type == eSymbolTypeCode) {
// See if we can find a N_FUN entry for any code symbols. If we
// do find a match, and the name matches, then we can merge the
@@ -4600,7 +4617,7 @@ size_t ObjectFileMachO::ParseSymtab() {
if (function_starts_count > 0) {
uint32_t num_synthetic_function_symbols = 0;
for (i = 0; i < function_starts_count; ++i) {
- if (function_starts.GetEntryRef(i).data == false)
+ if (!function_starts.GetEntryRef(i).data)
++num_synthetic_function_symbols;
}
@@ -4612,7 +4629,7 @@ size_t ObjectFileMachO::ParseSymtab() {
for (i = 0; i < function_starts_count; ++i) {
const FunctionStarts::Entry *func_start_entry =
function_starts.GetEntryAtIndex(i);
- if (func_start_entry->data == false) {
+ if (!func_start_entry->data) {
addr_t symbol_file_addr = func_start_entry->addr;
uint32_t symbol_flags = 0;
if (is_arm) {
@@ -4817,8 +4834,7 @@ void ObjectFileMachO::Dump(Stream *s) {
else
s->PutCString("ObjectFileMachO32");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', triple = " << header_arch.GetTriple().getTriple() << "\n";
@@ -4869,25 +4885,83 @@ bool ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header,
return false;
}
-static const char *GetOSName(uint32_t cmd) {
+static llvm::StringRef GetOSName(uint32_t cmd) {
switch (cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
- return "ios";
+ return llvm::Triple::getOSTypeName(llvm::Triple::IOS);
case llvm::MachO::LC_VERSION_MIN_MACOSX:
- return "macosx";
+ return llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
case llvm::MachO::LC_VERSION_MIN_TVOS:
- return "tvos";
+ return llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
case llvm::MachO::LC_VERSION_MIN_WATCHOS:
- return "watchos";
+ return llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
default:
llvm_unreachable("unexpected LC_VERSION load command");
}
}
-bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
- const lldb_private::DataExtractor &data,
- lldb::offset_t lc_offset,
- ArchSpec &arch) {
+namespace {
+ struct OSEnv {
+ llvm::StringRef os_type;
+ llvm::StringRef environment;
+ OSEnv(uint32_t cmd) {
+ switch (cmd) {
+ case PLATFORM_MACOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
+ return;
+ case PLATFORM_IOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
+ return;
+ case PLATFORM_TVOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
+ return;
+ case PLATFORM_WATCHOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
+ return;
+// NEED_BRIDGEOS_TRIPLE case PLATFORM_BRIDGEOS:
+// NEED_BRIDGEOS_TRIPLE os_type = llvm::Triple::getOSTypeName(llvm::Triple::BridgeOS);
+// NEED_BRIDGEOS_TRIPLE return;
+#if defined (PLATFORM_IOSSIMULATOR) && defined (PLATFORM_TVOSSIMULATOR) && defined (PLATFORM_WATCHOSSIMULATOR)
+ case PLATFORM_IOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+ case PLATFORM_TVOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+ case PLATFORM_WATCHOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+#endif
+ default: {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS |
+ LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("unsupported platform in LC_BUILD_VERSION");
+ }
+ }
+ }
+ };
+
+ struct MinOS {
+ uint32_t major_version, minor_version, patch_version;
+ MinOS(uint32_t version)
+ : major_version(version >> 16),
+ minor_version((version >> 8) & 0xffu),
+ patch_version(version & 0xffu) {}
+ };
+} // namespace
+
+ArchSpec
+ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset) {
+ ArchSpec arch;
arch.SetArchitecture(eArchTypeMachO, header.cputype, header.cpusubtype);
if (arch.IsValid()) {
@@ -4912,39 +4986,37 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
triple.setVendor(llvm::Triple::UnknownVendor);
triple.setVendorName(llvm::StringRef());
}
- return true;
+ return arch;
} else {
struct load_command load_cmd;
+ llvm::SmallString<16> os_name;
+ llvm::raw_svector_ostream os(os_name);
+ // See if there is an LC_VERSION_MIN_* load command that can give
+ // us the OS type.
lldb::offset_t offset = lc_offset;
for (uint32_t i = 0; i < header.ncmds; ++i) {
const lldb::offset_t cmd_offset = offset;
if (data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
- uint32_t major, minor, patch;
struct version_min_command version_min;
-
- llvm::SmallString<16> os_name;
- llvm::raw_svector_ostream os(os_name);
-
switch (load_cmd.cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
case llvm::MachO::LC_VERSION_MIN_MACOSX:
case llvm::MachO::LC_VERSION_MIN_TVOS:
- case llvm::MachO::LC_VERSION_MIN_WATCHOS:
+ case llvm::MachO::LC_VERSION_MIN_WATCHOS: {
if (load_cmd.cmdsize != sizeof(version_min))
break;
- data.ExtractBytes(cmd_offset,
- sizeof(version_min), data.GetByteOrder(),
- &version_min);
- major = version_min.version >> 16;
- minor = (version_min.version >> 8) & 0xffu;
- patch = version_min.version & 0xffu;
- os << GetOSName(load_cmd.cmd) << major << '.' << minor << '.'
- << patch;
+ if (data.ExtractBytes(cmd_offset, sizeof(version_min),
+ data.GetByteOrder(), &version_min) == 0)
+ break;
+ MinOS min_os(version_min.version);
+ os << GetOSName(load_cmd.cmd) << min_os.major_version << '.'
+ << min_os.minor_version << '.' << min_os.patch_version;
triple.setOSName(os.str());
- return true;
+ return arch;
+ }
default:
break;
}
@@ -4952,6 +5024,39 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
offset = cmd_offset + load_cmd.cmdsize;
}
+ // See if there is an LC_BUILD_VERSION load command that can give
+ // us the OS type.
+
+ offset = lc_offset;
+ for (uint32_t i = 0; i < header.ncmds; ++i) {
+ const lldb::offset_t cmd_offset = offset;
+ if (data.GetU32(&offset, &load_cmd, 2) == NULL)
+ break;
+ do {
+ if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ struct build_version_command build_version;
+ if (load_cmd.cmdsize < sizeof(build_version)) {
+ // Malformed load command.
+ break;
+ }
+ if (data.ExtractBytes(cmd_offset, sizeof(build_version),
+ data.GetByteOrder(), &build_version) == 0)
+ break;
+ MinOS min_os(build_version.minos);
+ OSEnv os_env(build_version.platform);
+ if (os_env.os_type.empty())
+ break;
+ os << os_env.os_type << min_os.major_version << '.'
+ << min_os.minor_version << '.' << min_os.patch_version;
+ triple.setOSName(os.str());
+ if (!os_env.environment.empty())
+ triple.setEnvironmentName(os_env.environment);
+ return arch;
+ }
+ } while (0);
+ offset = cmd_offset + load_cmd.cmdsize;
+ }
+
if (header.filetype != MH_KEXT_BUNDLE) {
// We didn't find a LC_VERSION_MIN load command and this isn't a KEXT
// so lets not say our Vendor is Apple, leave it as an unspecified
@@ -4961,7 +5066,7 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
}
}
}
- return arch.IsValid();
+ return arch;
}
bool ObjectFileMachO::GetUUID(lldb_private::UUID *uuid) {
@@ -4984,9 +5089,6 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
std::vector<std::string> rpath_paths;
std::vector<std::string> rpath_relative_paths;
std::vector<std::string> at_exec_relative_paths;
- const bool resolve_path = false; // Don't resolve the dependent file paths
- // since they may not reside on this
- // system
uint32_t i;
for (i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
@@ -5015,7 +5117,7 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
at_exec_relative_paths.push_back(path
+ strlen("@executable_path"));
} else {
- FileSpec file_spec(path, resolve_path);
+ FileSpec file_spec(path);
if (files.AppendIfUnique(file_spec))
count++;
}
@@ -5030,8 +5132,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
}
FileSpec this_file_spec(m_file);
- this_file_spec.ResolvePath();
-
+ FileSystem::Instance().Resolve(this_file_spec);
+
if (!rpath_paths.empty()) {
// Fixup all LC_RPATH values to be absolute paths
std::string loader_path("@loader_path");
@@ -5052,8 +5154,10 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
path += rpath_relative_path;
// It is OK to resolve this path because we must find a file on disk
// for us to accept it anyway if it is rpath relative.
- FileSpec file_spec(path, true);
- if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
+ if (FileSystem::Instance().Exists(file_spec) &&
+ files.AppendIfUnique(file_spec)) {
count++;
break;
}
@@ -5070,7 +5174,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
FileSpec file_spec =
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
- if (file_spec.Exists() && files.AppendIfUnique(file_spec))
+ if (FileSystem::Instance().Exists(file_spec) &&
+ files.AppendIfUnique(file_spec))
count++;
}
}
@@ -5235,7 +5340,7 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
return m_entry_point_address;
}
-lldb_private::Address ObjectFileMachO::GetHeaderAddress() {
+lldb_private::Address ObjectFileMachO::GetBaseAddress() {
lldb_private::Address header_addr;
SectionList *section_list = GetSectionList();
if (section_list) {
@@ -5583,14 +5688,16 @@ llvm::VersionTuple ObjectFileMachO::GetVersion() {
return llvm::VersionTuple();
}
-bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFileMachO::GetArchitecture() {
ModuleSP module_sp(GetModule());
+ ArchSpec arch;
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+
return GetArchitecture(m_header, m_data,
- MachHeaderSizeFromMagic(m_header.magic), arch);
+ MachHeaderSizeFromMagic(m_header.magic));
}
- return false;
+ return arch;
}
void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, addr_t &base_addr, UUID &uuid) {
@@ -5716,8 +5823,30 @@ llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() {
m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
break;
}
+ }
+ } else if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ // struct build_version_command {
+ // uint32_t cmd; /* LC_BUILD_VERSION */
+ // uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
+ // /* ntools * sizeof(struct build_tool_version) */
+ // uint32_t platform; /* platform */
+ // uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ // uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ // uint32_t ntools; /* number of tool entries following this */
+ // };
+
+ offset += 4; // skip platform
+ uint32_t minos = m_data.GetU32(&offset);
+
+ const uint32_t xxxx = minos >> 16;
+ const uint32_t yy = (minos >> 8) & 0xffu;
+ const uint32_t zz = minos & 0xffu;
+ if (xxxx) {
+ m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
+ break;
}
}
+
offset = load_cmd_offset + lc.cmdsize;
}
@@ -5735,7 +5864,7 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
if (m_sdk_versions.empty()) {
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
bool success = false;
- for (uint32_t i = 0; success == false && i < m_header.ncmds; ++i) {
+ for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
version_min_command lc;
@@ -5764,7 +5893,46 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
offset = load_cmd_offset + lc.cmdsize;
}
- if (success == false) {
+ if (!success) {
+ offset = MachHeaderSizeFromMagic(m_header.magic);
+ for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) {
+ const lldb::offset_t load_cmd_offset = offset;
+
+ version_min_command lc;
+ if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
+ break;
+ if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ // struct build_version_command {
+ // uint32_t cmd; /* LC_BUILD_VERSION */
+ // uint32_t cmdsize; /* sizeof(struct
+ // build_version_command) plus */
+ // /* ntools * sizeof(struct
+ // build_tool_version) */
+ // uint32_t platform; /* platform */
+ // uint32_t minos; /* X.Y.Z is encoded in nibbles
+ // xxxx.yy.zz */ uint32_t sdk; /* X.Y.Z is encoded
+ // in nibbles xxxx.yy.zz */ uint32_t ntools; /* number
+ // of tool entries following this */
+ // };
+
+ offset += 4; // skip platform
+ uint32_t minos = m_data.GetU32(&offset);
+
+ const uint32_t xxxx = minos >> 16;
+ const uint32_t yy = (minos >> 8) & 0xffu;
+ const uint32_t zz = minos & 0xffu;
+ if (xxxx) {
+ m_sdk_versions.push_back(xxxx);
+ m_sdk_versions.push_back(yy);
+ m_sdk_versions.push_back(zz);
+ success = true;
+ }
+ }
+ offset = load_cmd_offset + lc.cmdsize;
+ }
+ }
+
+ if (!success) {
// Push an invalid value so we don't try to find
// the version # again on the next call to this
// method.
@@ -5814,52 +5982,52 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
// the mach-o file which can be subtracted from the vmaddr of the other
// segments found in memory and added to the load address
ModuleSP module_sp = GetModule();
- if (module_sp) {
- SectionList *section_list = GetSectionList();
- if (section_list) {
- lldb::addr_t mach_base_file_addr = LLDB_INVALID_ADDRESS;
- const size_t num_sections = section_list->GetSize();
-
- for (size_t sect_idx = 0; sect_idx < num_sections &&
- mach_base_file_addr == LLDB_INVALID_ADDRESS;
- ++sect_idx) {
- Section *section = section_list->GetSectionAtIndex(sect_idx).get();
- if (section && section->GetFileSize() > 0 &&
- section->GetFileOffset() == 0 &&
- section->IsThreadSpecific() == false &&
- module_sp.get() == section->GetModule().get()) {
- return section;
- }
- }
- }
+ if (!module_sp)
+ return nullptr;
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return nullptr;
+ const size_t num_sections = section_list->GetSize();
+ for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
+ Section *section = section_list->GetSectionAtIndex(sect_idx).get();
+ if (section->GetFileOffset() == 0 && SectionIsLoadable(section))
+ return section;
}
return nullptr;
}
+bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
+ if (!section)
+ return false;
+ const bool is_dsym = (m_header.filetype == MH_DSYM);
+ if (section->GetFileSize() == 0 && !is_dsym)
+ return false;
+ if (section->IsThreadSpecific())
+ return false;
+ if (GetModule().get() != section->GetModule().get())
+ return false;
+ // Be careful with __LINKEDIT and __DWARF segments
+ if (section->GetName() == GetSegmentNameLINKEDIT() ||
+ section->GetName() == GetSegmentNameDWARF()) {
+ // Only map __LINKEDIT and __DWARF if we have an in memory image and
+ // this isn't a kernel binary like a kext or mach_kernel.
+ const bool is_memory_image = (bool)m_process_wp.lock();
+ const Strata strata = GetStrata();
+ if (is_memory_image == false || strata == eStrataKernel)
+ return false;
+ }
+ return true;
+}
+
lldb::addr_t ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage(
- lldb::addr_t mach_header_load_address, const Section *mach_header_section,
+ lldb::addr_t header_load_address, const Section *header_section,
const Section *section) {
ModuleSP module_sp = GetModule();
- if (module_sp && mach_header_section && section &&
- mach_header_load_address != LLDB_INVALID_ADDRESS) {
- lldb::addr_t mach_header_file_addr = mach_header_section->GetFileAddress();
- if (mach_header_file_addr != LLDB_INVALID_ADDRESS) {
- if (section && section->GetFileSize() > 0 &&
- section->IsThreadSpecific() == false &&
- module_sp.get() == section->GetModule().get()) {
- // Ignore __LINKEDIT and __DWARF segments
- if (section->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this isn't a
- // kernel binary like a kext or mach_kernel.
- const bool is_memory_image = (bool)m_process_wp.lock();
- const Strata strata = GetStrata();
- if (is_memory_image == false || strata == eStrataKernel)
- return LLDB_INVALID_ADDRESS;
- }
- return section->GetFileAddress() - mach_header_file_addr +
- mach_header_load_address;
- }
- }
+ if (module_sp && header_section && section &&
+ header_load_address != LLDB_INVALID_ADDRESS) {
+ lldb::addr_t file_addr = header_section->GetFileAddress();
+ if (file_addr != LLDB_INVALID_ADDRESS && SectionIsLoadable(section))
+ return section->GetFileAddress() - file_addr + header_load_address;
}
return LLDB_INVALID_ADDRESS;
}
@@ -5879,22 +6047,10 @@ bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value,
// Iterate through the object file sections to find all of the
// sections that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
- if (section_sp && section_sp->GetFileSize() > 0 &&
- section_sp->IsThreadSpecific() == false &&
- module_sp.get() == section_sp->GetModule().get()) {
- // Ignore __LINKEDIT and __DWARF segments
- if (section_sp->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this
- // isn't a kernel binary like a kext or mach_kernel.
- const bool is_memory_image = (bool)m_process_wp.lock();
- const Strata strata = GetStrata();
- if (is_memory_image == false || strata == eStrataKernel)
- continue;
- }
+ if (SectionIsLoadable(section_sp.get()))
if (target.GetSectionLoadList().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress() + value))
++num_loaded_sections;
- }
}
} else {
// "value" is the new base address of the mach_header, adjust each
@@ -5933,6 +6089,7 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
target_triple.getOS() == llvm::Triple::IOS ||
target_triple.getOS() == llvm::Triple::WatchOS ||
target_triple.getOS() == llvm::Triple::TvOS)) {
+ // NEED_BRIDGEOS_TRIPLE target_triple.getOS() == llvm::Triple::BridgeOS)) {
bool make_core = false;
switch (target_arch.GetMachine()) {
case llvm::Triple::aarch64:
@@ -6161,10 +6318,10 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
File core_file;
std::string core_file_path(outfile.GetPath());
- error = core_file.Open(core_file_path.c_str(),
- File::eOpenOptionWrite |
- File::eOpenOptionTruncate |
- File::eOpenOptionCanCreate);
+ error = FileSystem::Instance().Open(core_file, outfile,
+ File::eOpenOptionWrite |
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCanCreate);
if (error.Success()) {
// Read 1 page at a time
uint8_t bytes[0x1000];
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index be64518064b5..196abae807e9 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -10,16 +10,12 @@
#ifndef liblldb_ObjectFileMachO_h_
#define liblldb_ObjectFileMachO_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/RangeMap.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/UUID.h"
//----------------------------------------------------------------------
@@ -96,7 +92,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -108,7 +104,7 @@ public:
lldb_private::Address GetEntryPointAddress() override;
- lldb_private::Address GetHeaderAddress() override;
+ lldb_private::Address GetBaseAddress() override;
uint32_t GetNumThreadContexts() override;
@@ -151,10 +147,10 @@ protected:
lldb::offset_t lc_offset, // Offset to the first load command
lldb_private::UUID &uuid);
- static bool GetArchitecture(const llvm::MachO::mach_header &header,
- const lldb_private::DataExtractor &data,
- lldb::offset_t lc_offset,
- lldb_private::ArchSpec &arch);
+ static lldb_private::ArchSpec
+ GetArchitecture(const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset);
// Intended for same-host arm device debugging where lldb needs to
// detect libraries in the shared cache and augment the nlist entries
@@ -196,6 +192,8 @@ protected:
void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd,
uint32_t cmd_idx);
+ bool SectionIsLoadable(const lldb_private::Section *section);
+
llvm::MachO::mach_header m_header;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();
@@ -203,6 +201,7 @@ protected:
static const lldb_private::ConstString &GetSegmentNameDATA_CONST();
static const lldb_private::ConstString &GetSegmentNameOBJC();
static const lldb_private::ConstString &GetSegmentNameLINKEDIT();
+ static const lldb_private::ConstString &GetSegmentNameDWARF();
static const lldb_private::ConstString &GetSectionNameEHFrame();
llvm::MachO::dysymtab_command m_dysymtab;
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index b2967f1532ab..d18ff617521f 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
@@ -23,11 +23,14 @@
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/Object/COFFImportFile.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#define IMAGE_DOS_SIGNATURE 0x5A4D // MZ
@@ -86,6 +89,10 @@ ObjectFile *ObjectFilePECOFF::CreateInstance(const lldb::ModuleSP &module_sp,
if (!objfile_ap || !objfile_ap->ParseHeader())
return nullptr;
+ // Cache coff binary.
+ if (!objfile_ap->CreateBinary())
+ return nullptr;
+
return objfile_ap.release();
}
@@ -131,9 +138,7 @@ size_t ObjectFilePECOFF::GetModuleSpecifications(
specs.Append(ModuleSpec(file, spec));
spec.SetTriple("i686-pc-windows");
specs.Append(ModuleSpec(file, spec));
- }
- else if (coff_header.machine == MachineArmNt)
- {
+ } else if (coff_header.machine == MachineArmNt) {
spec.SetTriple("arm-pc-windows");
specs.Append(ModuleSpec(file, spec));
}
@@ -168,6 +173,40 @@ lldb::SymbolType ObjectFilePECOFF::MapSymbolType(uint16_t coff_symbol_type) {
return lldb::eSymbolTypeInvalid;
}
+bool ObjectFilePECOFF::CreateBinary() {
+ if (m_owningbin)
+ return true;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+
+ auto binary = llvm::object::createBinary(m_file.GetPath());
+ if (!binary) {
+ if (log)
+ log->Printf("ObjectFilePECOFF::CreateBinary() - failed to create binary "
+ "for file (%s): %s",
+ m_file ? m_file.GetPath().c_str() : "<NULL>",
+ errorToErrorCode(binary.takeError()).message().c_str());
+ return false;
+ }
+
+ // Make sure we only handle COFF format.
+ if (!binary->getBinary()->isCOFF() &&
+ !binary->getBinary()->isCOFFImportFile())
+ return false;
+
+ m_owningbin = OWNBINType(std::move(*binary));
+ if (log)
+ log->Printf("%p ObjectFilePECOFF::CreateBinary() module = %p (%s), file = "
+ "%s, binary = %p (Bin = %p)",
+ static_cast<void *>(this),
+ static_cast<void *>(GetModule().get()),
+ GetModule()->GetSpecificationDescription().c_str(),
+ m_file ? m_file.GetPath().c_str() : "<NULL>",
+ static_cast<void *>(m_owningbin.getPointer()),
+ static_cast<void *>(m_owningbin->getBinary()));
+ return true;
+}
+
ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
DataBufferSP &data_sp,
lldb::offset_t data_offset,
@@ -176,7 +215,7 @@ ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
lldb::offset_t length)
: ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
- m_entry_point_address() {
+ m_entry_point_address(), m_deps_filespec(), m_owningbin() {
::memset(&m_dos_header, 0, sizeof(m_dos_header));
::memset(&m_coff_header, 0, sizeof(m_coff_header));
::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
@@ -188,7 +227,7 @@ ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp,
addr_t header_addr)
: ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(),
- m_entry_point_address() {
+ m_entry_point_address(), m_deps_filespec(), m_owningbin() {
::memset(&m_dos_header, 0, sizeof(m_dos_header));
::memset(&m_coff_header, 0, sizeof(m_coff_header));
::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt));
@@ -431,7 +470,7 @@ bool ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr) {
DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) {
if (m_file) {
- // A bit of a hack, but we intend to write to this buffer, so we can't
+ // A bit of a hack, but we intend to write to this buffer, so we can't
// mmap it.
auto buffer_sp = MapFileData(m_file, size, offset);
return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize());
@@ -488,25 +527,23 @@ bool ObjectFilePECOFF::ParseSectionHeaders(
}
}
- return m_sect_headers.empty() == false;
+ return !m_sect_headers.empty();
}
-bool ObjectFilePECOFF::GetSectionName(std::string &sect_name,
- const section_header_t &sect) {
- if (sect.name[0] == '/') {
- lldb::offset_t stroff = strtoul(&sect.name[1], NULL, 10);
+llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t &sect) {
+ llvm::StringRef hdr_name(sect.name, llvm::array_lengthof(sect.name));
+ hdr_name = hdr_name.split('\0').first;
+ if (hdr_name.consume_front("/")) {
+ lldb::offset_t stroff;
+ if (!to_integer(hdr_name, stroff, 10))
+ return "";
lldb::offset_t string_file_offset =
m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
- const char *name = m_data.GetCStr(&string_file_offset);
- if (name) {
- sect_name = name;
- return true;
- }
-
- return false;
+ if (const char *name = m_data.GetCStr(&string_file_offset))
+ return name;
+ return "";
}
- sect_name = sect.name;
- return true;
+ return hdr_name;
}
//----------------------------------------------------------------------
@@ -663,144 +700,213 @@ bool ObjectFilePECOFF::IsStripped() {
}
void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
- if (!m_sections_ap.get()) {
- m_sections_ap.reset(new SectionList());
+ if (m_sections_ap)
+ return;
+ m_sections_ap.reset(new SectionList());
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ const uint32_t nsects = m_sect_headers.size();
ModuleSP module_sp(GetModule());
- if (module_sp) {
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- const uint32_t nsects = m_sect_headers.size();
- ModuleSP module_sp(GetModule());
- for (uint32_t idx = 0; idx < nsects; ++idx) {
- std::string sect_name;
- GetSectionName(sect_name, m_sect_headers[idx]);
- ConstString const_sect_name(sect_name.c_str());
- static ConstString g_code_sect_name(".code");
- static ConstString g_CODE_sect_name("CODE");
- static ConstString g_data_sect_name(".data");
- static ConstString g_DATA_sect_name("DATA");
- static ConstString g_bss_sect_name(".bss");
- static ConstString g_BSS_sect_name("BSS");
- static ConstString g_debug_sect_name(".debug");
- static ConstString g_reloc_sect_name(".reloc");
- static ConstString g_stab_sect_name(".stab");
- static ConstString g_stabstr_sect_name(".stabstr");
- static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
- static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
- static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
- static ConstString g_sect_name_dwarf_debug_info(".debug_info");
- static ConstString g_sect_name_dwarf_debug_line(".debug_line");
- static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
- static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
- static ConstString g_sect_name_dwarf_debug_names(".debug_names");
- static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
- static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
- static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
- static ConstString g_sect_name_dwarf_debug_str(".debug_str");
- static ConstString g_sect_name_dwarf_debug_types(".debug_types");
- static ConstString g_sect_name_eh_frame(".eh_frame");
- static ConstString g_sect_name_go_symtab(".gosymtab");
- SectionType section_type = eSectionTypeOther;
- if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
- ((const_sect_name == g_code_sect_name) ||
- (const_sect_name == g_CODE_sect_name))) {
- section_type = eSectionTypeCode;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
- ((const_sect_name == g_data_sect_name) ||
- (const_sect_name == g_DATA_sect_name))) {
+ for (uint32_t idx = 0; idx < nsects; ++idx) {
+ ConstString const_sect_name(GetSectionName(m_sect_headers[idx]));
+ static ConstString g_code_sect_name(".code");
+ static ConstString g_CODE_sect_name("CODE");
+ static ConstString g_data_sect_name(".data");
+ static ConstString g_DATA_sect_name("DATA");
+ static ConstString g_bss_sect_name(".bss");
+ static ConstString g_BSS_sect_name("BSS");
+ static ConstString g_debug_sect_name(".debug");
+ static ConstString g_reloc_sect_name(".reloc");
+ static ConstString g_stab_sect_name(".stab");
+ static ConstString g_stabstr_sect_name(".stabstr");
+ static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
+ static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
+ static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
+ static ConstString g_sect_name_dwarf_debug_info(".debug_info");
+ static ConstString g_sect_name_dwarf_debug_line(".debug_line");
+ static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
+ static ConstString g_sect_name_dwarf_debug_loclists(".debug_loclists");
+ static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_names(".debug_names");
+ static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
+ static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
+ static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
+ static ConstString g_sect_name_dwarf_debug_str(".debug_str");
+ static ConstString g_sect_name_dwarf_debug_types(".debug_types");
+ static ConstString g_sect_name_eh_frame(".eh_frame");
+ static ConstString g_sect_name_go_symtab(".gosymtab");
+ SectionType section_type = eSectionTypeOther;
+ if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
+ ((const_sect_name == g_code_sect_name) ||
+ (const_sect_name == g_CODE_sect_name))) {
+ section_type = eSectionTypeCode;
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
+ ((const_sect_name == g_data_sect_name) ||
+ (const_sect_name == g_DATA_sect_name))) {
+ if (m_sect_headers[idx].size == 0 && m_sect_headers[idx].offset == 0)
+ section_type = eSectionTypeZeroFill;
+ else
section_type = eSectionTypeData;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
- ((const_sect_name == g_bss_sect_name) ||
- (const_sect_name == g_BSS_sect_name))) {
- if (m_sect_headers[idx].size == 0)
- section_type = eSectionTypeZeroFill;
- else
- section_type = eSectionTypeData;
- } else if (const_sect_name == g_debug_sect_name) {
- section_type = eSectionTypeDebug;
- } else if (const_sect_name == g_stabstr_sect_name) {
- section_type = eSectionTypeDataCString;
- } else if (const_sect_name == g_reloc_sect_name) {
- section_type = eSectionTypeOther;
- } else if (const_sect_name == g_sect_name_dwarf_debug_abbrev)
- section_type = eSectionTypeDWARFDebugAbbrev;
- else if (const_sect_name == g_sect_name_dwarf_debug_aranges)
- section_type = eSectionTypeDWARFDebugAranges;
- else if (const_sect_name == g_sect_name_dwarf_debug_frame)
- section_type = eSectionTypeDWARFDebugFrame;
- else if (const_sect_name == g_sect_name_dwarf_debug_info)
- section_type = eSectionTypeDWARFDebugInfo;
- else if (const_sect_name == g_sect_name_dwarf_debug_line)
- section_type = eSectionTypeDWARFDebugLine;
- else if (const_sect_name == g_sect_name_dwarf_debug_loc)
- section_type = eSectionTypeDWARFDebugLoc;
- else if (const_sect_name == g_sect_name_dwarf_debug_macinfo)
- section_type = eSectionTypeDWARFDebugMacInfo;
- else if (const_sect_name == g_sect_name_dwarf_debug_names)
- section_type = eSectionTypeDWARFDebugNames;
- else if (const_sect_name == g_sect_name_dwarf_debug_pubnames)
- section_type = eSectionTypeDWARFDebugPubNames;
- else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes)
- section_type = eSectionTypeDWARFDebugPubTypes;
- else if (const_sect_name == g_sect_name_dwarf_debug_ranges)
- section_type = eSectionTypeDWARFDebugRanges;
- else if (const_sect_name == g_sect_name_dwarf_debug_str)
- section_type = eSectionTypeDWARFDebugStr;
- else if (const_sect_name == g_sect_name_dwarf_debug_types)
- section_type = eSectionTypeDWARFDebugTypes;
- else if (const_sect_name == g_sect_name_eh_frame)
- section_type = eSectionTypeEHFrame;
- else if (const_sect_name == g_sect_name_go_symtab)
- section_type = eSectionTypeGoSymtab;
- else if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE) {
- section_type = eSectionTypeCode;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) {
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
+ ((const_sect_name == g_bss_sect_name) ||
+ (const_sect_name == g_BSS_sect_name))) {
+ if (m_sect_headers[idx].size == 0)
+ section_type = eSectionTypeZeroFill;
+ else
+ section_type = eSectionTypeData;
+ } else if (const_sect_name == g_debug_sect_name) {
+ section_type = eSectionTypeDebug;
+ } else if (const_sect_name == g_stabstr_sect_name) {
+ section_type = eSectionTypeDataCString;
+ } else if (const_sect_name == g_reloc_sect_name) {
+ section_type = eSectionTypeOther;
+ } else if (const_sect_name == g_sect_name_dwarf_debug_abbrev)
+ section_type = eSectionTypeDWARFDebugAbbrev;
+ else if (const_sect_name == g_sect_name_dwarf_debug_aranges)
+ section_type = eSectionTypeDWARFDebugAranges;
+ else if (const_sect_name == g_sect_name_dwarf_debug_frame)
+ section_type = eSectionTypeDWARFDebugFrame;
+ else if (const_sect_name == g_sect_name_dwarf_debug_info)
+ section_type = eSectionTypeDWARFDebugInfo;
+ else if (const_sect_name == g_sect_name_dwarf_debug_line)
+ section_type = eSectionTypeDWARFDebugLine;
+ else if (const_sect_name == g_sect_name_dwarf_debug_loc)
+ section_type = eSectionTypeDWARFDebugLoc;
+ else if (const_sect_name == g_sect_name_dwarf_debug_loclists)
+ section_type = eSectionTypeDWARFDebugLocLists;
+ else if (const_sect_name == g_sect_name_dwarf_debug_macinfo)
+ section_type = eSectionTypeDWARFDebugMacInfo;
+ else if (const_sect_name == g_sect_name_dwarf_debug_names)
+ section_type = eSectionTypeDWARFDebugNames;
+ else if (const_sect_name == g_sect_name_dwarf_debug_pubnames)
+ section_type = eSectionTypeDWARFDebugPubNames;
+ else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes)
+ section_type = eSectionTypeDWARFDebugPubTypes;
+ else if (const_sect_name == g_sect_name_dwarf_debug_ranges)
+ section_type = eSectionTypeDWARFDebugRanges;
+ else if (const_sect_name == g_sect_name_dwarf_debug_str)
+ section_type = eSectionTypeDWARFDebugStr;
+ else if (const_sect_name == g_sect_name_dwarf_debug_types)
+ section_type = eSectionTypeDWARFDebugTypes;
+ else if (const_sect_name == g_sect_name_eh_frame)
+ section_type = eSectionTypeEHFrame;
+ else if (const_sect_name == g_sect_name_go_symtab)
+ section_type = eSectionTypeGoSymtab;
+ else if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE) {
+ section_type = eSectionTypeCode;
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) {
+ section_type = eSectionTypeData;
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
+ if (m_sect_headers[idx].size == 0)
+ section_type = eSectionTypeZeroFill;
+ else
section_type = eSectionTypeData;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
- if (m_sect_headers[idx].size == 0)
- section_type = eSectionTypeZeroFill;
- else
- section_type = eSectionTypeData;
- }
-
- // Use a segment ID of the segment index shifted left by 8 so they
- // never conflict with any of the sections.
- SectionSP section_sp(new Section(
- module_sp, // Module to which this section belongs
- this, // Object file to which this section belongs
- idx + 1, // Section ID is the 1 based segment index shifted right by
- // 8 bits as not to collide with any of the 256 section IDs
- // that are possible
- const_sect_name, // Name of this section
- section_type, // This section is a container of other sections.
- m_coff_header_opt.image_base +
- m_sect_headers[idx].vmaddr, // File VM address == addresses as
- // they are found in the object file
- m_sect_headers[idx].vmsize, // VM size in bytes of this section
- m_sect_headers[idx]
- .offset, // Offset to the data for this section in the file
- m_sect_headers[idx]
- .size, // Size in bytes of this section as found in the file
- m_coff_header_opt.sect_alignment, // Section alignment
- m_sect_headers[idx].flags)); // Flags for this section
-
- // section_sp->SetIsEncrypted (segment_is_encrypted);
-
- unified_section_list.AddSection(section_sp);
- m_sections_ap->AddSection(section_sp);
}
+
+ // Use a segment ID of the segment index shifted left by 8 so they
+ // never conflict with any of the sections.
+ SectionSP section_sp(new Section(
+ module_sp, // Module to which this section belongs
+ this, // Object file to which this section belongs
+ idx + 1, // Section ID is the 1 based segment index shifted right by
+ // 8 bits as not to collide with any of the 256 section IDs
+ // that are possible
+ const_sect_name, // Name of this section
+ section_type, // This section is a container of other sections.
+ m_coff_header_opt.image_base +
+ m_sect_headers[idx].vmaddr, // File VM address == addresses as
+ // they are found in the object file
+ m_sect_headers[idx].vmsize, // VM size in bytes of this section
+ m_sect_headers[idx]
+ .offset, // Offset to the data for this section in the file
+ m_sect_headers[idx]
+ .size, // Size in bytes of this section as found in the file
+ m_coff_header_opt.sect_alignment, // Section alignment
+ m_sect_headers[idx].flags)); // Flags for this section
+
+ // section_sp->SetIsEncrypted (segment_is_encrypted);
+
+ unified_section_list.AddSection(section_sp);
+ m_sections_ap->AddSection(section_sp);
}
}
}
bool ObjectFilePECOFF::GetUUID(UUID *uuid) { return false; }
+uint32_t ObjectFilePECOFF::ParseDependentModules() {
+ ModuleSP module_sp(GetModule());
+ if (!module_sp)
+ return 0;
+
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ if (m_deps_filespec)
+ return m_deps_filespec->GetSize();
+
+ // Cache coff binary if it is not done yet.
+ if (!CreateBinary())
+ return 0;
+
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf("%p ObjectFilePECOFF::ParseDependentModules() module = %p "
+ "(%s), binary = %p (Bin = %p)",
+ static_cast<void *>(this), static_cast<void *>(module_sp.get()),
+ module_sp->GetSpecificationDescription().c_str(),
+ static_cast<void *>(m_owningbin.getPointer()),
+ m_owningbin ? static_cast<void *>(m_owningbin->getBinary())
+ : nullptr);
+
+ auto COFFObj =
+ llvm::dyn_cast<llvm::object::COFFObjectFile>(m_owningbin->getBinary());
+ if (!COFFObj)
+ return 0;
+
+ m_deps_filespec = FileSpecList();
+
+ for (const auto &entry : COFFObj->import_directories()) {
+ llvm::StringRef dll_name;
+ auto ec = entry.getName(dll_name);
+ // Report a bogus entry.
+ if (ec != std::error_code()) {
+ if (log)
+ log->Printf("ObjectFilePECOFF::ParseDependentModules() - failed to get "
+ "import directory entry name: %s",
+ ec.message().c_str());
+ continue;
+ }
+
+ // At this moment we only have the base name of the DLL. The full path can
+ // only be seen after the dynamic loading. Our best guess is Try to get it
+ // with the help of the object file's directory.
+ llvm::SmallString<128> dll_fullpath;
+ FileSpec dll_specs(dll_name);
+ dll_specs.GetDirectory().SetString(m_file.GetDirectory().GetCString());
+
+ if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath))
+ m_deps_filespec->Append(FileSpec(dll_fullpath));
+ else {
+ // Known DLLs or DLL not found in the object file directory.
+ m_deps_filespec->Append(FileSpec(dll_name));
+ }
+ }
+ return m_deps_filespec->GetSize();
+}
+
uint32_t ObjectFilePECOFF::GetDependentModules(FileSpecList &files) {
- return 0;
+ auto num_modules = ParseDependentModules();
+ auto original_size = files.GetSize();
+
+ for (unsigned i = 0; i < num_modules; ++i)
+ files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i));
+
+ return files.GetSize() - original_size;
}
lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() {
@@ -811,12 +917,12 @@ lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() {
return m_entry_point_address;
SectionList *section_list = GetSectionList();
- addr_t offset = m_coff_header_opt.entry;
+ addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
if (!section_list)
- m_entry_point_address.SetOffset(offset);
+ m_entry_point_address.SetOffset(file_addr);
else
- m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
+ m_entry_point_address.ResolveAddressUsingFileSections(file_addr, section_list);
return m_entry_point_address;
}
@@ -834,8 +940,7 @@ void ObjectFilePECOFF::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFilePECOFF");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', arch = " << header_arch.GetArchitectureName() << "\n";
@@ -857,6 +962,9 @@ void ObjectFilePECOFF::Dump(Stream *s) {
s->EOL();
DumpSectionHeaders(s);
s->EOL();
+
+ DumpDependentModules(s);
+ s->EOL();
}
}
@@ -974,8 +1082,7 @@ void ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s,
//----------------------------------------------------------------------
void ObjectFilePECOFF::DumpSectionHeader(Stream *s,
const section_header_t &sh) {
- std::string name;
- GetSectionName(name, sh);
+ std::string name = GetSectionName(sh);
s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
"0x%4.4x 0x%8.8x\n",
name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
@@ -1004,6 +1111,22 @@ void ObjectFilePECOFF::DumpSectionHeaders(Stream *s) {
}
}
+//----------------------------------------------------------------------
+// DumpDependentModules
+//
+// Dump all of the dependent modules to the specified output stream
+//----------------------------------------------------------------------
+void ObjectFilePECOFF::DumpDependentModules(lldb_private::Stream *s) {
+ auto num_modules = ParseDependentModules();
+ if (num_modules > 0) {
+ s->PutCString("Dependent Modules\n");
+ for (unsigned i = 0; i < num_modules; ++i) {
+ auto spec = m_deps_filespec->GetFileSpecAtIndex(i);
+ s->Printf(" %s\n", spec.GetFilename().GetCString());
+ }
+ }
+}
+
bool ObjectFilePECOFF::IsWindowsSubsystem() {
switch (m_coff_header_opt.subsystem) {
case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE:
@@ -1019,9 +1142,11 @@ bool ObjectFilePECOFF::IsWindowsSubsystem() {
}
}
-bool ObjectFilePECOFF::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFilePECOFF::GetArchitecture() {
uint16_t machine = m_coff_header.machine;
switch (machine) {
+ default:
+ break;
case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
case llvm::COFF::IMAGE_FILE_MACHINE_I386:
case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
@@ -1029,14 +1154,13 @@ bool ObjectFilePECOFF::GetArchitecture(ArchSpec &arch) {
case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
+ ArchSpec arch;
arch.SetArchitecture(eArchTypeCOFF, machine, LLDB_INVALID_CPUTYPE,
IsWindowsSubsystem() ? llvm::Triple::Win32
: llvm::Triple::UnknownOS);
- return true;
- default:
- break;
+ return arch;
}
- return false;
+ return ArchSpec();
}
ObjectFile::Type ObjectFilePECOFF::CalculateType() {
@@ -1050,6 +1174,7 @@ ObjectFile::Type ObjectFilePECOFF::CalculateType() {
}
ObjectFile::Strata ObjectFilePECOFF::CalculateStrata() { return eStrataUser; }
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index d8a94e19d34f..9fd313f26a0a 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -10,13 +10,10 @@
#ifndef liblldb_ObjectFilePECOFF_h_
#define liblldb_ObjectFilePECOFF_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/ObjectFile.h"
+#include "llvm/Object/Binary.h"
class ObjectFilePECOFF : public lldb_private::ObjectFile {
public:
@@ -113,7 +110,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -261,6 +258,8 @@ protected:
bool ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr);
bool ParseSectionHeaders(uint32_t offset);
+ uint32_t ParseDependentModules();
+
static void DumpDOSHeader(lldb_private::Stream *s,
const dos_header_t &header);
static void DumpCOFFHeader(lldb_private::Stream *s,
@@ -269,19 +268,27 @@ protected:
const coff_opt_header_t &header);
void DumpSectionHeaders(lldb_private::Stream *s);
void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh);
- bool GetSectionName(std::string &sect_name, const section_header_t &sect);
+ void DumpDependentModules(lldb_private::Stream *s);
+
+ llvm::StringRef GetSectionName(const section_header_t &sect);
typedef std::vector<section_header_t> SectionHeaderColl;
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;
private:
+ bool CreateBinary();
+
+private:
dos_header_t m_dos_header;
coff_header_t m_coff_header;
coff_opt_header_t m_coff_header_opt;
SectionHeaderColl m_sect_headers;
lldb::addr_t m_image_base;
lldb_private::Address m_entry_point_address;
+ llvm::Optional<lldb_private::FileSpecList> m_deps_filespec;
+ typedef llvm::object::OwningBinary<llvm::object::Binary> OWNBINType;
+ llvm::Optional<OWNBINType> m_owningbin;
};
#endif // liblldb_ObjectFilePECOFF_h_
diff --git a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp b/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
index d6553f6e5142..e77888c871b5 100644
--- a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
@@ -16,7 +16,7 @@
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
-#include <dbghelp.h> // for MiniDumpWriteDump
+#include <dbghelp.h>
#endif
namespace lldb_private {
diff --git a/source/Plugins/OperatingSystem/CMakeLists.txt b/source/Plugins/OperatingSystem/CMakeLists.txt
index 1f017adcd02b..655007a0aab9 100644
--- a/source/Plugins/OperatingSystem/CMakeLists.txt
+++ b/source/Plugins/OperatingSystem/CMakeLists.txt
@@ -1,2 +1 @@
-add_subdirectory(Go)
add_subdirectory(Python)
diff --git a/source/Plugins/OperatingSystem/Go/CMakeLists.txt b/source/Plugins/OperatingSystem/Go/CMakeLists.txt
deleted file mode 100644
index 27e952a84dfc..000000000000
--- a/source/Plugins/OperatingSystem/Go/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-add_lldb_library(lldbPluginOSGo PLUGIN
- OperatingSystemGo.cpp
-
- LINK_LIBS
- lldbCore
- lldbInterpreter
- lldbSymbol
- lldbTarget
- lldbPluginProcessUtility
- )
diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
deleted file mode 100644
index 3f6083931513..000000000000
--- a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.cpp
+++ /dev/null
@@ -1,498 +0,0 @@
-//===-- OperatingSystemGo.cpp -----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-// C++ Includes
-#include <unordered_map>
-
-// Other libraries and framework includes
-// Project includes
-#include "OperatingSystemGo.h"
-
-#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
-#include "Plugins/Process/Utility/RegisterContextMemory.h"
-#include "Plugins/Process/Utility/ThreadMemory.h"
-#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Section.h"
-#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Interpreter/CommandInterpreter.h"
-#include "lldb/Interpreter/OptionGroupBoolean.h"
-#include "lldb/Interpreter/OptionGroupUInt64.h"
-#include "lldb/Interpreter/OptionValueProperties.h"
-#include "lldb/Interpreter/Options.h"
-#include "lldb/Interpreter/Property.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/VariableList.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/StopInfo.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Target/Thread.h"
-#include "lldb/Target/ThreadList.h"
-#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/StreamString.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-namespace {
-
-static PropertyDefinition g_properties[] = {
- {"enable", OptionValue::eTypeBoolean, true, true, nullptr, nullptr,
- "Specify whether goroutines should be treated as threads."},
- {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
-
-enum {
- ePropertyEnableGoroutines,
-};
-
-class PluginProperties : public Properties {
-public:
- PluginProperties() : Properties() {
- m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
- m_collection_sp->Initialize(g_properties);
- }
-
- ~PluginProperties() override = default;
-
- static ConstString GetSettingName() {
- return OperatingSystemGo::GetPluginNameStatic();
- }
-
- bool GetEnableGoroutines() {
- const uint32_t idx = ePropertyEnableGoroutines;
- return m_collection_sp->GetPropertyAtIndexAsBoolean(
- NULL, idx, g_properties[idx].default_uint_value);
- }
-
- bool SetEnableGoroutines(bool enable) {
- const uint32_t idx = ePropertyEnableGoroutines;
- return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, enable);
- }
-};
-
-typedef std::shared_ptr<PluginProperties> OperatingSystemGoPropertiesSP;
-
-static const OperatingSystemGoPropertiesSP &GetGlobalPluginProperties() {
- static OperatingSystemGoPropertiesSP g_settings_sp;
- if (!g_settings_sp)
- g_settings_sp.reset(new PluginProperties());
- return g_settings_sp;
-}
-
-class RegisterContextGo : public RegisterContextMemory {
-public:
- RegisterContextGo(lldb_private::Thread &thread, uint32_t concrete_frame_idx,
- DynamicRegisterInfo &reg_info, lldb::addr_t reg_data_addr)
- : RegisterContextMemory(thread, concrete_frame_idx, reg_info,
- reg_data_addr) {
- const RegisterInfo *sp = reg_info.GetRegisterInfoAtIndex(
- reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
- LLDB_REGNUM_GENERIC_SP));
- const RegisterInfo *pc = reg_info.GetRegisterInfoAtIndex(
- reg_info.ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric,
- LLDB_REGNUM_GENERIC_PC));
- size_t byte_size = std::max(sp->byte_offset + sp->byte_size,
- pc->byte_offset + pc->byte_size);
-
- DataBufferSP reg_data_sp(new DataBufferHeap(byte_size, 0));
- m_reg_data.SetData(reg_data_sp);
- }
-
- ~RegisterContextGo() override = default;
-
- bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
- lldb_private::RegisterValue &reg_value) override {
- switch (reg_info->kinds[eRegisterKindGeneric]) {
- case LLDB_REGNUM_GENERIC_SP:
- case LLDB_REGNUM_GENERIC_PC:
- return RegisterContextMemory::ReadRegister(reg_info, reg_value);
- default:
- reg_value.SetValueToInvalid();
- return true;
- }
- }
-
- bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
- const lldb_private::RegisterValue &reg_value) override {
- switch (reg_info->kinds[eRegisterKindGeneric]) {
- case LLDB_REGNUM_GENERIC_SP:
- case LLDB_REGNUM_GENERIC_PC:
- return RegisterContextMemory::WriteRegister(reg_info, reg_value);
- default:
- return false;
- }
- }
-
-private:
- DISALLOW_COPY_AND_ASSIGN(RegisterContextGo);
-};
-
-} // anonymous namespace
-
-struct OperatingSystemGo::Goroutine {
- uint64_t m_lostack;
- uint64_t m_histack;
- uint64_t m_goid;
- addr_t m_gobuf;
- uint32_t m_status;
-};
-
-void OperatingSystemGo::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(), CreateInstance,
- DebuggerInitialize);
-}
-
-void OperatingSystemGo::DebuggerInitialize(Debugger &debugger) {
- if (!PluginManager::GetSettingForOperatingSystemPlugin(
- debugger, PluginProperties::GetSettingName())) {
- const bool is_global_setting = true;
- PluginManager::CreateSettingForOperatingSystemPlugin(
- debugger, GetGlobalPluginProperties()->GetValueProperties(),
- ConstString("Properties for the goroutine thread plug-in."),
- is_global_setting);
- }
-}
-
-void OperatingSystemGo::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-OperatingSystem *OperatingSystemGo::CreateInstance(Process *process,
- bool force) {
- if (!force) {
- TargetSP target_sp = process->CalculateTarget();
- if (!target_sp)
- return nullptr;
- ModuleList &module_list = target_sp->GetImages();
- std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
- const size_t num_modules = module_list.GetSize();
- bool found_go_runtime = false;
- for (size_t i = 0; i < num_modules; ++i) {
- Module *module = module_list.GetModulePointerAtIndexUnlocked(i);
- const SectionList *section_list = module->GetSectionList();
- if (section_list) {
- SectionSP section_sp(
- section_list->FindSectionByType(eSectionTypeGoSymtab, true));
- if (section_sp) {
- found_go_runtime = true;
- break;
- }
- }
- }
- if (!found_go_runtime)
- return nullptr;
- }
- return new OperatingSystemGo(process);
-}
-
-OperatingSystemGo::OperatingSystemGo(lldb_private::Process *process)
- : OperatingSystem(process), m_reginfo(new DynamicRegisterInfo) {}
-
-OperatingSystemGo::~OperatingSystemGo() = default;
-
-ConstString OperatingSystemGo::GetPluginNameStatic() {
- static ConstString g_name("goroutines");
- return g_name;
-}
-
-const char *OperatingSystemGo::GetPluginDescriptionStatic() {
- return "Operating system plug-in that reads runtime data-structures for "
- "goroutines.";
-}
-
-bool OperatingSystemGo::Init(ThreadList &threads) {
- if (threads.GetSize(false) < 1)
- return false;
- TargetSP target_sp = m_process->CalculateTarget();
- if (!target_sp)
- return false;
- // Go 1.6 stores goroutines in a slice called runtime.allgs
- ValueObjectSP allgs_sp = FindGlobal(target_sp, "runtime.allgs");
- if (allgs_sp) {
- m_allg_sp = allgs_sp->GetChildMemberWithName(ConstString("array"), true);
- m_allglen_sp = allgs_sp->GetChildMemberWithName(ConstString("len"), true);
- } else {
- // Go 1.4 stores goroutines in the variable runtime.allg.
- m_allg_sp = FindGlobal(target_sp, "runtime.allg");
- m_allglen_sp = FindGlobal(target_sp, "runtime.allglen");
- }
-
- if (m_allg_sp && !m_allglen_sp) {
- StreamSP error_sp = target_sp->GetDebugger().GetAsyncErrorStream();
- error_sp->Printf("Unsupported Go runtime version detected.");
- return false;
- }
-
- if (!m_allg_sp)
- return false;
-
- RegisterContextSP real_registers_sp =
- threads.GetThreadAtIndex(0, false)->GetRegisterContext();
-
- std::unordered_map<size_t, ConstString> register_sets;
- for (size_t set_idx = 0; set_idx < real_registers_sp->GetRegisterSetCount();
- ++set_idx) {
- const RegisterSet *set = real_registers_sp->GetRegisterSet(set_idx);
- ConstString name(set->name);
- for (size_t reg_idx = 0; reg_idx < set->num_registers; ++reg_idx) {
- register_sets[reg_idx] = name;
- }
- }
- TypeSP gobuf_sp = FindType(target_sp, "runtime.gobuf");
- if (!gobuf_sp) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
-
- if (log)
- log->Printf("OperatingSystemGo unable to find struct Gobuf");
- return false;
- }
- CompilerType gobuf_type(gobuf_sp->GetLayoutCompilerType());
- for (size_t idx = 0; idx < real_registers_sp->GetRegisterCount(); ++idx) {
- RegisterInfo reg = *real_registers_sp->GetRegisterInfoAtIndex(idx);
- int field_index = -1;
- if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_SP) {
- field_index = 0;
- } else if (reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC) {
- field_index = 1;
- }
- if (field_index == -1) {
- reg.byte_offset = ~0;
- } else {
- std::string field_name;
- uint64_t bit_offset = 0;
- CompilerType field_type = gobuf_type.GetFieldAtIndex(
- field_index, field_name, &bit_offset, nullptr, nullptr);
- reg.byte_size = field_type.GetByteSize(nullptr);
- reg.byte_offset = bit_offset / 8;
- }
- ConstString name(reg.name);
- ConstString alt_name(reg.alt_name);
- m_reginfo->AddRegister(reg, name, alt_name, register_sets[idx]);
- }
- return true;
-}
-
-//------------------------------------------------------------------
-// PluginInterface protocol
-//------------------------------------------------------------------
-ConstString OperatingSystemGo::GetPluginName() { return GetPluginNameStatic(); }
-
-uint32_t OperatingSystemGo::GetPluginVersion() { return 1; }
-
-bool OperatingSystemGo::UpdateThreadList(ThreadList &old_thread_list,
- ThreadList &real_thread_list,
- ThreadList &new_thread_list) {
- new_thread_list = real_thread_list;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
-
- if (!(m_allg_sp || Init(real_thread_list)) || (m_allg_sp && !m_allglen_sp) ||
- !GetGlobalPluginProperties()->GetEnableGoroutines()) {
- return new_thread_list.GetSize(false) > 0;
- }
-
- if (log)
- log->Printf("OperatingSystemGo::UpdateThreadList(%d, %d, %d) fetching "
- "thread data from Go for pid %" PRIu64,
- old_thread_list.GetSize(false), real_thread_list.GetSize(false),
- new_thread_list.GetSize(0), m_process->GetID());
- uint64_t allglen = m_allglen_sp->GetValueAsUnsigned(0);
- if (allglen == 0) {
- return new_thread_list.GetSize(false) > 0;
- }
- std::vector<Goroutine> goroutines;
- // The threads that are in "new_thread_list" upon entry are the threads from
- // the lldb_private::Process subclass, no memory threads will be in this
- // list.
-
- Status err;
- for (uint64_t i = 0; i < allglen; ++i) {
- goroutines.push_back(CreateGoroutineAtIndex(i, err));
- if (err.Fail()) {
- LLDB_LOG(log, "error: {0}", err);
- return new_thread_list.GetSize(false) > 0;
- }
- }
- // Make a map so we can match goroutines with backing threads.
- std::map<uint64_t, ThreadSP> stack_map;
- for (uint32_t i = 0; i < real_thread_list.GetSize(false); ++i) {
- ThreadSP thread = real_thread_list.GetThreadAtIndex(i, false);
- stack_map[thread->GetRegisterContext()->GetSP()] = thread;
- }
- for (const Goroutine &goroutine : goroutines) {
- if (0 /* Gidle */ == goroutine.m_status ||
- 6 /* Gdead */ == goroutine.m_status) {
- continue;
- }
- ThreadSP memory_thread =
- old_thread_list.FindThreadByID(goroutine.m_goid, false);
- if (memory_thread && IsOperatingSystemPluginThread(memory_thread) &&
- memory_thread->IsValid()) {
- memory_thread->ClearBackingThread();
- } else {
- memory_thread.reset(new ThreadMemory(*m_process, goroutine.m_goid, "", "",
- goroutine.m_gobuf));
- }
- // Search for the backing thread if the goroutine is running.
- if (2 == (goroutine.m_status & 0xfff)) {
- auto backing_it = stack_map.lower_bound(goroutine.m_lostack);
- if (backing_it != stack_map.end()) {
- if (goroutine.m_histack >= backing_it->first) {
- if (log)
- log->Printf(
- "OperatingSystemGo::UpdateThreadList found backing thread "
- "%" PRIx64 " (%" PRIx64 ") for thread %" PRIx64 "",
- backing_it->second->GetID(),
- backing_it->second->GetProtocolID(), memory_thread->GetID());
- memory_thread->SetBackingThread(backing_it->second);
- new_thread_list.RemoveThreadByID(backing_it->second->GetID(), false);
- }
- }
- }
- new_thread_list.AddThread(memory_thread);
- }
-
- return new_thread_list.GetSize(false) > 0;
-}
-
-void OperatingSystemGo::ThreadWasSelected(Thread *thread) {}
-
-RegisterContextSP
-OperatingSystemGo::CreateRegisterContextForThread(Thread *thread,
- addr_t reg_data_addr) {
- RegisterContextSP reg_ctx_sp;
- if (!thread)
- return reg_ctx_sp;
-
- if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
- return reg_ctx_sp;
-
- reg_ctx_sp.reset(
- new RegisterContextGo(*thread, 0, *m_reginfo, reg_data_addr));
- return reg_ctx_sp;
-}
-
-StopInfoSP
-OperatingSystemGo::CreateThreadStopReason(lldb_private::Thread *thread) {
- StopInfoSP stop_info_sp;
- return stop_info_sp;
-}
-
-lldb::ThreadSP OperatingSystemGo::CreateThread(lldb::tid_t tid,
- addr_t context) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
-
- if (log)
- log->Printf("OperatingSystemGo::CreateThread (tid = 0x%" PRIx64
- ", context = 0x%" PRIx64 ") not implemented",
- tid, context);
-
- return ThreadSP();
-}
-
-ValueObjectSP OperatingSystemGo::FindGlobal(TargetSP target, const char *name) {
- VariableList variable_list;
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
-
- if (log) {
- log->Printf(
- "exe: %s",
- target->GetExecutableModule()->GetSpecificationDescription().c_str());
- log->Printf("modules: %zu", target->GetImages().GetSize());
- }
-
- uint32_t match_count = target->GetImages().FindGlobalVariables(
- ConstString(name), 1, variable_list);
- if (match_count > 0) {
- ExecutionContextScope *exe_scope = target->GetProcessSP().get();
- if (exe_scope == NULL)
- exe_scope = target.get();
- return ValueObjectVariable::Create(exe_scope,
- variable_list.GetVariableAtIndex(0));
- }
- return ValueObjectSP();
-}
-
-TypeSP OperatingSystemGo::FindType(TargetSP target_sp, const char *name) {
- ConstString const_typename(name);
- SymbolContext sc;
- const bool exact_match = false;
-
- const ModuleList &module_list = target_sp->GetImages();
- size_t count = module_list.GetSize();
- for (size_t idx = 0; idx < count; idx++) {
- ModuleSP module_sp(module_list.GetModuleAtIndex(idx));
- if (module_sp) {
- TypeSP type_sp(module_sp->FindFirstType(sc, const_typename, exact_match));
- if (type_sp)
- return type_sp;
- }
- }
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OS));
-
- if (log)
- log->Printf("OperatingSystemGo::FindType(%s): not found", name);
- return TypeSP();
-}
-
-OperatingSystemGo::Goroutine
-OperatingSystemGo::CreateGoroutineAtIndex(uint64_t idx, Status &err) {
- err.Clear();
- Goroutine result = {};
- ValueObjectSP g =
- m_allg_sp->GetSyntheticArrayMember(idx, true)->Dereference(err);
- if (err.Fail()) {
- return result;
- }
-
- ConstString name("goid");
- ValueObjectSP val = g->GetChildMemberWithName(name, true);
- bool success = false;
- result.m_goid = val->GetValueAsUnsigned(0, &success);
- if (!success) {
- err.SetErrorToGenericError();
- err.SetErrorString("unable to read goid");
- return result;
- }
- name.SetCString("atomicstatus");
- val = g->GetChildMemberWithName(name, true);
- result.m_status = (uint32_t)val->GetValueAsUnsigned(0, &success);
- if (!success) {
- err.SetErrorToGenericError();
- err.SetErrorString("unable to read atomicstatus");
- return result;
- }
- name.SetCString("sched");
- val = g->GetChildMemberWithName(name, true);
- result.m_gobuf = val->GetAddressOf(false);
- name.SetCString("stack");
- val = g->GetChildMemberWithName(name, true);
- name.SetCString("lo");
- ValueObjectSP child = val->GetChildMemberWithName(name, true);
- result.m_lostack = child->GetValueAsUnsigned(0, &success);
- if (!success) {
- err.SetErrorToGenericError();
- err.SetErrorString("unable to read stack.lo");
- return result;
- }
- name.SetCString("hi");
- child = val->GetChildMemberWithName(name, true);
- result.m_histack = child->GetValueAsUnsigned(0, &success);
- if (!success) {
- err.SetErrorToGenericError();
- err.SetErrorString("unable to read stack.hi");
- return result;
- }
- return result;
-}
diff --git a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h b/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h
deleted file mode 100644
index 5d255a348a63..000000000000
--- a/source/Plugins/OperatingSystem/Go/OperatingSystemGo.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//===-- OperatingSystemGo.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_OperatingSystemGo_h_
-#define _liblldb_OperatingSystemGo_h_
-
-// C Includes
-// C++ Includes
-#include <memory>
-
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Target/OperatingSystem.h"
-
-class DynamicRegisterInfo;
-
-class OperatingSystemGo : public lldb_private::OperatingSystem {
-public:
- OperatingSystemGo(lldb_private::Process *process);
-
- ~OperatingSystemGo() override;
-
- //------------------------------------------------------------------
- // Static Functions
- //------------------------------------------------------------------
- static lldb_private::OperatingSystem *
- CreateInstance(lldb_private::Process *process, bool force);
-
- static void Initialize();
-
- static void DebuggerInitialize(lldb_private::Debugger &debugger);
-
- static void Terminate();
-
- static lldb_private::ConstString GetPluginNameStatic();
-
- static const char *GetPluginDescriptionStatic();
-
- //------------------------------------------------------------------
- // lldb_private::PluginInterface Methods
- //------------------------------------------------------------------
- lldb_private::ConstString GetPluginName() override;
-
- uint32_t GetPluginVersion() override;
-
- //------------------------------------------------------------------
- // lldb_private::OperatingSystem Methods
- //------------------------------------------------------------------
- bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
- lldb_private::ThreadList &real_thread_list,
- lldb_private::ThreadList &new_thread_list) override;
-
- void ThreadWasSelected(lldb_private::Thread *thread) override;
-
- lldb::RegisterContextSP
- CreateRegisterContextForThread(lldb_private::Thread *thread,
- lldb::addr_t reg_data_addr) override;
-
- lldb::StopInfoSP
- CreateThreadStopReason(lldb_private::Thread *thread) override;
-
- //------------------------------------------------------------------
- // Method for lazy creation of threads on demand
- //------------------------------------------------------------------
- lldb::ThreadSP CreateThread(lldb::tid_t tid, lldb::addr_t context) override;
-
-private:
- struct Goroutine;
-
- static lldb::ValueObjectSP FindGlobal(lldb::TargetSP target,
- const char *name);
-
- static lldb::TypeSP FindType(lldb::TargetSP target_sp, const char *name);
-
- bool Init(lldb_private::ThreadList &threads);
-
- Goroutine CreateGoroutineAtIndex(uint64_t idx, lldb_private::Status &err);
-
- std::unique_ptr<DynamicRegisterInfo> m_reginfo;
- lldb::ValueObjectSP m_allg_sp;
- lldb::ValueObjectSP m_allglen_sp;
-};
-
-#endif // liblldb_OperatingSystemGo_h_
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index d6252c473270..89a0f2253936 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -10,9 +10,6 @@
#ifndef LLDB_DISABLE_PYTHON
#include "OperatingSystemPython.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
#include "Plugins/Process/Utility/RegisterContextDummy.h"
#include "Plugins/Process/Utility/RegisterContextMemory.h"
@@ -20,7 +17,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
@@ -32,6 +28,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadList.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StructuredData.h"
@@ -53,7 +50,8 @@ OperatingSystem *OperatingSystemPython::CreateInstance(Process *process,
// Python OperatingSystem plug-ins must be requested by name, so force must
// be true
FileSpec python_os_plugin_spec(process->GetPythonOSPluginPath());
- if (python_os_plugin_spec && python_os_plugin_spec.Exists()) {
+ if (python_os_plugin_spec &&
+ FileSystem::Instance().Exists(python_os_plugin_spec)) {
std::unique_ptr<OperatingSystemPython> os_ap(
new OperatingSystemPython(process, python_os_plugin_spec));
if (os_ap.get() && os_ap->IsValid())
@@ -215,7 +213,7 @@ bool OperatingSystemPython::UpdateThreadList(ThreadList &old_thread_list,
// beginning of the list
uint32_t insert_idx = 0;
for (uint32_t core_idx = 0; core_idx < num_cores; ++core_idx) {
- if (core_used_map[core_idx] == false) {
+ if (!core_used_map[core_idx]) {
new_thread_list.InsertThread(
core_thread_list.GetThreadAtIndex(core_idx, false), insert_idx);
++insert_idx;
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index 2e1680410962..c812464fa747 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -12,10 +12,6 @@
#ifndef LLDB_DISABLE_PYTHON
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/source/Plugins/Platform/Android/AdbClient.cpp b/source/Plugins/Platform/Android/AdbClient.cpp
index 4cd8c645dd76..0ad30a528954 100644
--- a/source/Plugins/Platform/Android/AdbClient.cpp
+++ b/source/Plugins/Platform/Android/AdbClient.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// Other libraries and framework includes
#include "AdbClient.h"
#include "llvm/ADT/STLExtras.h"
@@ -484,7 +483,7 @@ Status AdbClient::SyncService::internalPushFile(const FileSpec &local_file,
return Status("Failed to send file chunk: %s", error.AsCString());
}
error = SendSyncRequest(
- kDONE, llvm::sys::toTimeT(FileSystem::GetModificationTime(local_file)),
+ kDONE, llvm::sys::toTimeT(FileSystem::Instance().GetModificationTime(local_file)),
nullptr);
if (error.Fail())
return error;
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.cpp b/source/Plugins/Platform/Android/PlatformAndroid.cpp
index 4477fe371d34..a56ab0e30153 100644
--- a/source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ b/source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -9,15 +9,14 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/UriParser.h"
-// Project includes
#include "AdbClient.h"
#include "PlatformAndroid.h"
#include "PlatformAndroidRemoteGDBServer.h"
@@ -75,7 +74,7 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
}
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::PC:
@@ -193,7 +192,7 @@ Status PlatformAndroid::GetFile(const FileSpec &source,
if (IsHost() || !m_remote_platform_sp)
return PlatformLinux::GetFile(source, destination);
- FileSpec source_spec(source.GetPath(false), false, FileSpec::Style::posix);
+ FileSpec source_spec(source.GetPath(false), FileSpec::Style::posix);
if (source_spec.IsRelative())
source_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
source_spec.GetCString(false));
@@ -237,8 +236,7 @@ Status PlatformAndroid::PutFile(const FileSpec &source,
if (IsHost() || !m_remote_platform_sp)
return PlatformLinux::PutFile(source, destination, uid, gid);
- FileSpec destination_spec(destination.GetPath(false), false,
- FileSpec::Style::posix);
+ FileSpec destination_spec(destination.GetPath(false), FileSpec::Style::posix);
if (destination_spec.IsRelative())
destination_spec = GetRemoteWorkingDirectory().CopyByAppendingPathComponent(
destination_spec.GetCString(false));
@@ -343,7 +341,7 @@ Status PlatformAndroid::DownloadSymbolFile(const lldb::ModuleSP &module_sp,
log->Printf("Failed to remove temp directory: %s", error.AsCString());
});
- FileSpec symfile_platform_filespec(tmpdir, false);
+ FileSpec symfile_platform_filespec(tmpdir);
symfile_platform_filespec.AppendPathComponent("symbolized.oat");
// Execute oatdump on the remote device to generate a file with symtab
diff --git a/source/Plugins/Platform/Android/PlatformAndroid.h b/source/Plugins/Platform/Android/PlatformAndroid.h
index 4c12eb8c016d..2e7706cc246e 100644
--- a/source/Plugins/Platform/Android/PlatformAndroid.h
+++ b/source/Plugins/Platform/Android/PlatformAndroid.h
@@ -10,13 +10,9 @@
#ifndef liblldb_PlatformAndroid_h_
#define liblldb_PlatformAndroid_h_
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Platform/Linux/PlatformLinux.h"
#include "AdbClient.h"
diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
index 2415da31daf0..bbb03369d63c 100644
--- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// Other libraries and framework includes
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Utility/Log.h"
diff --git a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
index 1bd13ffe89fe..40356293b589 100644
--- a/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
+++ b/source/Plugins/Platform/Android/PlatformAndroidRemoteGDBServer.h
@@ -10,13 +10,9 @@
#ifndef liblldb_PlatformAndroidRemoteGDBServer_h_
#define liblldb_PlatformAndroidRemoteGDBServer_h_
-// C Includes
-// C++ Includes
#include <map>
#include <utility>
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h"
#include "llvm/ADT/Optional.h"
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index bc8111d1078b..59cce3a6bc2b 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -10,25 +10,21 @@
#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
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -52,7 +48,7 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) {
arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::FreeBSD:
@@ -274,9 +270,9 @@ lldb::ProcessSP PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
TargetSP new_target_sp;
ArchSpec emptyArchSpec;
- error = debugger.GetTargetList().CreateTarget(debugger, "", emptyArchSpec,
- false, m_remote_platform_sp,
- new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", emptyArchSpec, eLoadDependentsNo, m_remote_platform_sp,
+ new_target_sp);
target = new_target_sp.get();
} else
error.Clear();
diff --git a/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp b/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp
index 00327e485bf3..cc902b7f7ad5 100644
--- a/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp
+++ b/source/Plugins/Platform/Kalimba/PlatformKalimba.cpp
@@ -11,9 +11,6 @@
#include "PlatformKalimba.h"
#include "lldb/Host/Config.h"
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -33,7 +30,7 @@ static uint32_t g_initialize_count = 0;
PlatformSP PlatformKalimba::CreateInstance(bool force, const ArchSpec *arch) {
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::CSR:
diff --git a/source/Plugins/Platform/Kalimba/PlatformKalimba.h b/source/Plugins/Platform/Kalimba/PlatformKalimba.h
index 53a8e5594aaa..efa78457d585 100644
--- a/source/Plugins/Platform/Kalimba/PlatformKalimba.h
+++ b/source/Plugins/Platform/Kalimba/PlatformKalimba.h
@@ -10,10 +10,6 @@
#ifndef liblldb_PlatformKalimba_h_
#define liblldb_PlatformKalimba_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Platform.h"
namespace lldb_private {
diff --git a/source/Plugins/Platform/Linux/PlatformLinux.cpp b/source/Plugins/Platform/Linux/PlatformLinux.cpp
index dbde91d7ab2d..7498c648d6e4 100644
--- a/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -10,23 +10,19 @@
#include "PlatformLinux.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
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -50,7 +46,7 @@ PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) {
arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::Linux:
@@ -302,8 +298,8 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
if (target == nullptr) {
LLDB_LOG(log, "creating new target");
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- nullptr, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
if (error.Fail()) {
LLDB_LOG(log, "failed to create new target: {0}", error);
return process_sp;
@@ -322,8 +318,8 @@ PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
// Now create the gdb-remote process.
LLDB_LOG(log, "having target create process with gdb-remote plugin");
- process_sp = target->CreateProcess(
- launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
+ process_sp =
+ target->CreateProcess(launch_info.GetListener(), "gdb-remote", nullptr);
if (!process_sp) {
error.SetErrorString("CreateProcess() failed for gdb-remote process");
diff --git a/source/Plugins/Platform/MacOSX/CMakeLists.txt b/source/Plugins/Platform/MacOSX/CMakeLists.txt
index f9663559069a..6f0d952c35fb 100644
--- a/source/Plugins/Platform/MacOSX/CMakeLists.txt
+++ b/source/Plugins/Platform/MacOSX/CMakeLists.txt
@@ -6,6 +6,7 @@ list(APPEND PLUGIN_PLATFORM_MACOSX_SOURCES
PlatformRemoteAppleTV.cpp
PlatformRemoteAppleWatch.cpp
PlatformRemoteDarwinDevice.cpp
+ PlatformRemoteAppleBridge.cpp
)
list(APPEND PLUGIN_PLATFORM_MACOSX_DARWIN_ONLY_SOURCES
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
index 6852097117a1..a2f74a5fc8bc 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.cpp
@@ -9,16 +9,12 @@
#include "PlatformAppleSimulator.h"
-// C Includes
#if defined(__APPLE__)
#include <dlfcn.h>
#endif
-// C++ Includes
#include <mutex>
#include <thread>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -229,9 +225,8 @@ FileSpec PlatformAppleSimulator::GetCoreSimulatorPath() {
cs_path.Printf(
"%s/Library/PrivateFrameworks/CoreSimulator.framework/CoreSimulator",
developer_dir);
- const bool resolve_path = true;
- m_core_simulator_framework_path =
- FileSpec(cs_path.GetData(), resolve_path);
+ m_core_simulator_framework_path = FileSpec(cs_path.GetData());
+ FileSystem::Instance().Resolve(*m_core_simulator_framework_path);
}
}
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
index 2536854e9630..daae376cc00b 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleSimulator.h
@@ -10,12 +10,8 @@
#ifndef liblldb_PlatformAppleSimulator_h_
#define liblldb_PlatformAppleSimulator_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Platform/MacOSX/PlatformDarwin.h"
#include "Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h"
#include "lldb/Utility/FileSpec.h"
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
index e55cc0f4f6a4..62bd3c3ed1f8 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.cpp
@@ -9,10 +9,6 @@
#include "PlatformAppleTVSimulator.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -80,7 +76,7 @@ PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force,
}
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
switch (arch->GetMachine()) {
case llvm::Triple::x86_64: {
const llvm::Triple &triple = arch->GetTriple();
@@ -93,7 +89,7 @@ PlatformSP PlatformAppleTVSimulator::CreateInstance(bool force,
// Only accept "unknown" for the vendor if the host is Apple and it
// "unknown" wasn't specified (it was just returned because it was NOT
// specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
#endif
@@ -190,7 +186,7 @@ Status PlatformAppleTVSimulator::ResolveExecutable(
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
if (resolved_module_spec.GetArchitecture().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
@@ -228,7 +224,7 @@ Status PlatformAppleTVSimulator::ResolveExecutable(
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -247,19 +243,20 @@ Status PlatformAppleTVSimulator::ResolveExecutable(
return error;
}
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &file_spec) {
+ llvm::StringRef path) {
if (ft == llvm::sys::fs::file_type::directory_file) {
+ FileSpec file_spec(path);
const char *filename = file_spec.GetFilename().GetCString();
if (filename &&
strncmp(filename, "AppleTVSimulator", strlen("AppleTVSimulator")) ==
0) {
::snprintf((char *)baton, PATH_MAX, "%s", filename);
- return FileSpec::eEnumerateDirectoryResultQuit;
+ return FileSystem::eEnumerateDirectoryResultQuit;
}
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() {
@@ -277,9 +274,9 @@ const char *PlatformAppleTVSimulator::GetSDKDirectoryAsCString() {
bool find_directories = true;
bool find_files = false;
bool find_other = false;
- FileSpec::EnumerateDirectory(sdks_directory, find_directories, find_files,
- find_other, EnumerateDirectoryCallback,
- sdk_dirname);
+ FileSystem::Instance().EnumerateDirectory(
+ sdks_directory, find_directories, find_files, find_other,
+ EnumerateDirectoryCallback, sdk_dirname);
if (sdk_dirname[0]) {
m_sdk_directory = sdks_directory;
@@ -315,13 +312,15 @@ Status PlatformAppleTVSimulator::GetSymbolFile(const FileSpec &platform_file,
platform_file_path);
// First try in the SDK and see if the file is in there
- local_file.SetFile(resolved_path, true, FileSpec::Style::native);
- if (local_file.Exists())
+ local_file.SetFile(resolved_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file))
return error;
// Else fall back to the actual path itself
- local_file.SetFile(platform_file_path, true, FileSpec::Style::native);
- if (local_file.Exists())
+ local_file.SetFile(platform_file_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file))
return error;
}
error.SetErrorStringWithFormat(
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
index 8cecb4d496ab..9a4da589c7ea 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleTVSimulator.h
@@ -10,10 +10,6 @@
#ifndef liblldb_PlatformAppleTVSimulator_h_
#define liblldb_PlatformAppleTVSimulator_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "PlatformDarwin.h"
class PlatformAppleTVSimulator : public PlatformDarwin {
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
index 8bbe0af0aec2..ec112cc0b9c5 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.cpp
@@ -9,10 +9,6 @@
#include "PlatformAppleWatchSimulator.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -79,7 +75,7 @@ PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force,
}
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
switch (arch->GetMachine()) {
case llvm::Triple::x86_64: {
const llvm::Triple &triple = arch->GetTriple();
@@ -92,7 +88,7 @@ PlatformSP PlatformAppleWatchSimulator::CreateInstance(bool force,
// Only accept "unknown" for the vendor if the host is Apple and it
// "unknown" wasn't specified (it was just returned because it was NOT
// specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
#endif
@@ -190,7 +186,7 @@ Status PlatformAppleWatchSimulator::ResolveExecutable(
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
if (resolved_module_spec.GetArchitecture().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
@@ -228,7 +224,7 @@ Status PlatformAppleWatchSimulator::ResolveExecutable(
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -247,19 +243,20 @@ Status PlatformAppleWatchSimulator::ResolveExecutable(
return error;
}
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &file_spec) {
+ llvm::StringRef path) {
if (ft == llvm::sys::fs::file_type::directory_file) {
+ FileSpec file_spec(path);
const char *filename = file_spec.GetFilename().GetCString();
if (filename &&
strncmp(filename, "AppleWatchSimulator",
strlen("AppleWatchSimulator")) == 0) {
::snprintf((char *)baton, PATH_MAX, "%s", filename);
- return FileSpec::eEnumerateDirectoryResultQuit;
+ return FileSystem::eEnumerateDirectoryResultQuit;
}
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
const char *PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() {
@@ -277,9 +274,9 @@ const char *PlatformAppleWatchSimulator::GetSDKDirectoryAsCString() {
bool find_directories = true;
bool find_files = false;
bool find_other = false;
- FileSpec::EnumerateDirectory(sdks_directory, find_directories, find_files,
- find_other, EnumerateDirectoryCallback,
- sdk_dirname);
+ FileSystem::Instance().EnumerateDirectory(
+ sdks_directory, find_directories, find_files, find_other,
+ EnumerateDirectoryCallback, sdk_dirname);
if (sdk_dirname[0]) {
m_sdk_directory = sdks_directory;
@@ -315,13 +312,15 @@ Status PlatformAppleWatchSimulator::GetSymbolFile(const FileSpec &platform_file,
platform_file_path);
// First try in the SDK and see if the file is in there
- local_file.SetFile(resolved_path, true, FileSpec::Style::native);
- if (local_file.Exists())
+ local_file.SetFile(resolved_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file))
return error;
// Else fall back to the actual path itself
- local_file.SetFile(platform_file_path, true, FileSpec::Style::native);
- if (local_file.Exists())
+ local_file.SetFile(platform_file_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file))
return error;
}
error.SetErrorStringWithFormat(
diff --git a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
index 30aa42c964a5..c240a09e3afd 100644
--- a/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
+++ b/source/Plugins/Platform/MacOSX/PlatformAppleWatchSimulator.h
@@ -10,10 +10,6 @@
#ifndef liblldb_PlatformAppleWatchSimulator_h_
#define liblldb_PlatformAppleWatchSimulator_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "PlatformDarwin.h"
class PlatformAppleWatchSimulator : public PlatformDarwin {
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 886e3b6d9a05..3868d97700e0 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -9,14 +9,11 @@
#include "PlatformDarwin.h"
-// C Includes
#include <string.h>
-// C++ Includes
#include <algorithm>
#include <mutex>
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Debugger.h"
@@ -33,7 +30,6 @@
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Timer.h"
@@ -43,7 +39,7 @@
#include "llvm/Support/VersionTuple.h"
#if defined(__APPLE__)
-#include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
+#include <TargetConditionals.h>
#endif
using namespace lldb;
@@ -88,7 +84,7 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
ObjectFile *objfile = symfile->GetObjectFile();
if (objfile) {
FileSpec symfile_spec(objfile->GetFileSpec());
- if (symfile_spec && symfile_spec.Exists()) {
+ if (symfile_spec && FileSystem::Instance().Exists(symfile_spec)) {
while (module_spec.GetFilename()) {
std::string module_basename(
module_spec.GetFilename().GetCString());
@@ -130,20 +126,21 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
"%s/../Python/%s.py",
symfile_spec.GetDirectory().GetCString(),
original_module_basename.c_str());
- FileSpec script_fspec(path_string.GetString(), true);
- FileSpec orig_script_fspec(original_path_string.GetString(),
- true);
+ FileSpec script_fspec(path_string.GetString());
+ FileSystem::Instance().Resolve(script_fspec);
+ FileSpec orig_script_fspec(original_path_string.GetString());
+ FileSystem::Instance().Resolve(orig_script_fspec);
// if we did some replacements of reserved characters, and a
// file with the untampered name exists, then warn the user
// that the file as-is shall not be loaded
if (feedback_stream) {
if (module_basename != original_module_basename &&
- orig_script_fspec.Exists()) {
+ FileSystem::Instance().Exists(orig_script_fspec)) {
const char *reason_for_complaint =
was_keyword ? "conflicts with a keyword"
: "contains reserved characters";
- if (script_fspec.Exists())
+ if (FileSystem::Instance().Exists(script_fspec))
feedback_stream->Printf(
"warning: the symbol file '%s' contains a debug "
"script. However, its name"
@@ -167,7 +164,7 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
}
}
- if (script_fspec.Exists()) {
+ if (FileSystem::Instance().Exists(script_fspec)) {
file_list.Append(script_fspec);
break;
}
@@ -193,25 +190,12 @@ FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
Status PlatformDarwin::ResolveSymbolFile(Target &target,
const ModuleSpec &sym_spec,
FileSpec &sym_file) {
- Status error;
sym_file = sym_spec.GetSymbolFileSpec();
-
- llvm::sys::fs::file_status st;
- if (status(sym_file.GetPath(), st, false)) {
- error.SetErrorString("Could not stat file!");
- return error;
- }
-
- if (exists(st)) {
- if (is_directory(st)) {
- sym_file = Symbols::FindSymbolFileInBundle(
- sym_file, sym_spec.GetUUIDPtr(), sym_spec.GetArchitecturePtr());
- }
- } else {
- if (sym_spec.GetUUID().IsValid()) {
- }
+ if (FileSystem::Instance().IsDirectory(sym_file)) {
+ sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(),
+ sym_spec.GetArchitecturePtr());
}
- return error;
+ return {};
}
static lldb_private::Status
@@ -261,7 +245,7 @@ lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
if (!cache_path.empty()) {
std::string module_path(module_spec.GetFileSpec().GetPath());
cache_path.append(module_path);
- FileSpec module_cache_spec(cache_path, false);
+ FileSpec module_cache_spec(cache_path);
// if rsync is supported, always bring in the file - rsync will be very
// efficient when files are the same on the local and remote end of the
@@ -270,7 +254,7 @@ lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
err = BringInRemoteFile(this, module_spec, module_cache_spec);
if (err.Fail())
return err;
- if (module_cache_spec.Exists()) {
+ if (FileSystem::Instance().Exists(module_cache_spec)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s was rsynced and is now there",
@@ -286,7 +270,7 @@ lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
}
// try to find the module in the cache
- if (module_cache_spec.Exists()) {
+ if (FileSystem::Instance().Exists(module_cache_spec)) {
// get the local and remote MD5 and compare
if (m_remote_platform_sp) {
// when going over the *slow* GDB remote transfer mechanism we first
@@ -337,7 +321,7 @@ lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
Status err = BringInRemoteFile(this, module_spec, module_cache_spec);
if (err.Fail())
return err;
- if (module_cache_spec.Exists()) {
+ if (FileSystem::Instance().Exists(module_cache_spec)) {
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s is now cached and fine",
@@ -412,8 +396,8 @@ Status PlatformDarwin::GetSharedModule(
snprintf(new_path + search_path_len,
sizeof(new_path) - search_path_len, "/%s",
platform_path + bundle_directory_len);
- FileSpec new_file_spec(new_path, false);
- if (new_file_spec.Exists()) {
+ FileSpec new_file_spec(new_path);
+ if (FileSystem::Instance().Exists(new_file_spec)) {
ModuleSpec new_module_spec(module_spec);
new_module_spec.GetFileSpec() = new_file_spec;
Status new_error(Platform::GetSharedModule(
@@ -505,10 +489,7 @@ bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches(
return false;
ObjectFile::Type obj_type = obj_file->GetType();
- if (obj_type == ObjectFile::eTypeDynamicLinker)
- return true;
- else
- return false;
+ return obj_type == ObjectFile::eTypeDynamicLinker;
}
bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx,
@@ -1167,9 +1148,9 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
if (xcode_select_prefix_dir)
xcode_dir_path.append(xcode_select_prefix_dir);
xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path");
- temp_file_spec.SetFile(xcode_dir_path, false, FileSpec::Style::native);
+ temp_file_spec.SetFile(xcode_dir_path, FileSpec::Style::native);
auto dir_buffer =
- DataBufferLLVM::CreateFromPath(temp_file_spec.GetPath());
+ FileSystem::Instance().CreateDataBuffer(temp_file_spec.GetPath());
if (dir_buffer && dir_buffer->GetByteSize() > 0) {
llvm::StringRef path_ref(dir_buffer->GetChars());
// Trim tailing newlines and make sure there is enough room for a null
@@ -1183,8 +1164,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
}
if (!developer_dir_path_valid) {
- FileSpec xcode_select_cmd("/usr/bin/xcode-select", false);
- if (xcode_select_cmd.Exists()) {
+ FileSpec xcode_select_cmd("/usr/bin/xcode-select");
+ if (FileSystem::Instance().Exists(xcode_select_cmd)) {
int exit_status = -1;
int signo = -1;
std::string command_output;
@@ -1206,8 +1187,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
}
developer_dir_path[i] = '\0';
- FileSpec devel_dir(developer_dir_path, false);
- if (llvm::sys::fs::is_directory(devel_dir.GetPath())) {
+ FileSpec devel_dir(developer_dir_path);
+ if (FileSystem::Instance().IsDirectory(devel_dir)) {
developer_dir_path_valid = true;
}
}
@@ -1215,9 +1196,8 @@ const char *PlatformDarwin::GetDeveloperDirectory() {
}
if (developer_dir_path_valid) {
- temp_file_spec.SetFile(developer_dir_path, false,
- FileSpec::Style::native);
- if (temp_file_spec.Exists()) {
+ temp_file_spec.SetFile(developer_dir_path, FileSpec::Style::native);
+ if (FileSystem::Instance().Exists(temp_file_spec)) {
m_developer_directory.assign(developer_dir_path);
return m_developer_directory.c_str();
}
@@ -1247,7 +1227,7 @@ BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
FileSpecList bp_modules;
for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) {
const char *bp_module = g_bp_modules[i];
- bp_modules.Append(FileSpec(bp_module, false));
+ bp_modules.Append(FileSpec(bp_module));
}
bool internal = true;
@@ -1300,20 +1280,20 @@ static const char *const sdk_strings[] = {
};
static FileSpec CheckPathForXcode(const FileSpec &fspec) {
- if (fspec.Exists()) {
+ if (FileSystem::Instance().Exists(fspec)) {
const char substr[] = ".app/Contents";
std::string path_to_shlib = fspec.GetPath();
size_t pos = path_to_shlib.rfind(substr);
if (pos != std::string::npos) {
path_to_shlib.erase(pos + strlen(substr));
- FileSpec ret(path_to_shlib, false);
+ FileSpec ret(path_to_shlib);
FileSpec xcode_binary_path = ret;
xcode_binary_path.AppendPathComponent("MacOS");
xcode_binary_path.AppendPathComponent("Xcode");
- if (xcode_binary_path.Exists()) {
+ if (FileSystem::Instance().Exists(xcode_binary_path)) {
return ret;
}
}
@@ -1348,8 +1328,9 @@ static FileSpec GetXcodeContentsPath() {
if (!g_xcode_filespec) {
const char *developer_dir_env_var = getenv("DEVELOPER_DIR");
if (developer_dir_env_var && developer_dir_env_var[0]) {
- g_xcode_filespec =
- CheckPathForXcode(FileSpec(developer_dir_env_var, true));
+ FileSpec developer_dir_spec = FileSpec(developer_dir_env_var);
+ FileSystem::Instance().Resolve(developer_dir_spec);
+ g_xcode_filespec = CheckPathForXcode(developer_dir_spec);
}
// Fall back to using "xcrun" to find the selected Xcode
@@ -1373,7 +1354,7 @@ static FileSpec GetXcodeContentsPath() {
}
output.append("/..");
- g_xcode_filespec = CheckPathForXcode(FileSpec(output, false));
+ g_xcode_filespec = CheckPathForXcode(FileSpec(output));
}
}
}
@@ -1402,14 +1383,11 @@ bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
if (last_path_component) {
const llvm::StringRef sdk_name = last_path_component.GetStringRef();
- llvm::StringRef version_part;
-
- if (sdk_name.startswith(sdk_strings[(int)desired_type])) {
- version_part =
- sdk_name.drop_front(strlen(sdk_strings[(int)desired_type]));
- } else {
+ if (!sdk_name.startswith(sdk_strings[desired_type]))
return false;
- }
+ auto version_part =
+ sdk_name.drop_front(strlen(sdk_strings[desired_type]));
+ version_part.consume_back(".sdk");
llvm::VersionTuple version;
if (version.tryParse(version_part))
@@ -1420,23 +1398,24 @@ bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
return false;
}
-FileSpec::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
- void *baton, llvm::sys::fs::file_type file_type, const FileSpec &spec) {
+FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
+ void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
+ FileSpec spec(path);
if (SDKSupportsModules(enumerator_info->sdk_type, spec)) {
enumerator_info->found_path = spec;
- return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
+ return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
}
- return FileSpec::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
+ return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
}
FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
const FileSpec &sdks_spec) {
// Look inside Xcode for the required installed iOS SDK version
- if (!llvm::sys::fs::is_directory(sdks_spec.GetPath())) {
+ if (!FileSystem::Instance().IsDirectory(sdks_spec)) {
return FileSpec();
}
@@ -1448,11 +1427,11 @@ FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
enumerator_info.sdk_type = sdk_type;
- FileSpec::EnumerateDirectory(sdks_spec.GetPath(), find_directories,
- find_files, find_other, DirectoryEnumerator,
- &enumerator_info);
+ FileSystem::Instance().EnumerateDirectory(
+ sdks_spec.GetPath(), find_directories, find_files, find_other,
+ DirectoryEnumerator, &enumerator_info);
- if (llvm::sys::fs::is_directory(enumerator_info.found_path.GetPath()))
+ if (FileSystem::Instance().IsDirectory(enumerator_info.found_path))
return enumerator_info.found_path;
else
return FileSpec();
@@ -1499,7 +1478,7 @@ FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
version.getMinor().getValueOr(0));
native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
- if (native_sdk_spec.Exists()) {
+ if (FileSystem::Instance().Exists(native_sdk_spec)) {
return native_sdk_spec;
}
}
@@ -1597,7 +1576,7 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
sysroot_spec = GetSDKDirectoryForModules(sdk_type);
}
- if (llvm::sys::fs::is_directory(sysroot_spec.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
options.push_back("-isysroot");
options.push_back(sysroot_spec.GetPath());
}
@@ -1661,7 +1640,7 @@ lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
xcode_lldb_resources.AppendPathComponent("LLDB.framework");
xcode_lldb_resources.AppendPathComponent("Resources");
- if (xcode_lldb_resources.Exists()) {
+ if (FileSystem::Instance().Exists(xcode_lldb_resources)) {
FileSpec dir;
dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
g_executable_dirs.push_back(dir);
@@ -1675,7 +1654,7 @@ lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
FileSpec executable_file;
executable_file.GetDirectory() = executable_dir.GetDirectory();
executable_file.GetFilename().SetCString(basename);
- if (executable_file.Exists())
+ if (FileSystem::Instance().Exists(executable_file))
return executable_file;
}
@@ -1759,7 +1738,7 @@ PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec
path_to_try.AppendPathComponent(path_parts[k]);
}
- if (path_to_try.Exists()) {
+ if (FileSystem::Instance().Exists(path_to_try)) {
ModuleSpec new_module_spec(module_spec);
new_module_spec.GetFileSpec() = path_to_try;
Status new_error(Platform::GetSharedModule(
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index 3ad29ec1a0b9..f2dd9b1bc778 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -10,12 +10,9 @@
#ifndef liblldb_PlatformDarwin_h_
#define liblldb_PlatformDarwin_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Platform/POSIX/PlatformPOSIX.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/FileSystem.h"
@@ -85,6 +82,12 @@ public:
static std::tuple<llvm::VersionTuple, llvm::StringRef>
ParseVersionBuildDir(llvm::StringRef str);
+ enum SDKType : unsigned {
+ MacOSX = 0,
+ iPhoneSimulator,
+ iPhoneOS,
+ };
+
protected:
void ReadLibdispatchOffsetsAddress(lldb_private::Process *process);
@@ -95,12 +98,6 @@ protected:
const lldb_private::FileSpecList *module_search_paths_ptr,
lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr);
- enum class SDKType {
- MacOSX = 0,
- iPhoneSimulator,
- iPhoneOS,
- };
-
static bool SDKSupportsModules(SDKType sdk_type, llvm::VersionTuple version);
static bool SDKSupportsModules(SDKType desired_type,
@@ -111,9 +108,9 @@ protected:
SDKType sdk_type;
};
- static lldb_private::FileSpec::EnumerateDirectoryResult
+ static lldb_private::FileSystem::EnumerateDirectoryResult
DirectoryEnumerator(void *baton, llvm::sys::fs::file_type file_type,
- const lldb_private::FileSpec &spec);
+ llvm::StringRef path);
static lldb_private::FileSpec
FindSDKInXcodeForModules(SDKType sdk_type,
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
index 1e3216c0af5a..4c6d9459e225 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -13,10 +13,6 @@
#if defined(__APPLE__) // This Plugin uses the Mac-specific
// source/Host/macosx/cfcpp utilities
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -95,7 +91,7 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
// ArchSpec for normal userland debugging. It is only useful in kernel debug
// sessions and the DynamicLoaderDarwinPlugin (or a user doing 'platform
// select') will force the creation of this Platform plugin.
- if (force == false) {
+ if (!force) {
if (log)
log->Printf("PlatformDarwinKernel::%s() aborting creation of platform "
"because force == false",
@@ -106,7 +102,7 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
bool create = force;
LazyBool is_ios_debug_session = eLazyBoolCalculate;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::Apple:
@@ -115,7 +111,7 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
// Only accept "unknown" for vendor if the host is Apple and it "unknown"
// wasn't specified (it was just returned because it was NOT specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
default:
@@ -129,6 +125,7 @@ PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
case llvm::Triple::IOS:
case llvm::Triple::WatchOS:
case llvm::Triple::TvOS:
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
break;
// Only accept "vendor" for vendor if the host is Apple and it "unknown"
// wasn't specified (it was just returned because it was NOT specified)
@@ -186,14 +183,13 @@ const char *PlatformDarwinKernel::GetDescriptionStatic() {
/// Code to handle the PlatformDarwinKernel settings
//------------------------------------------------------------------
-static PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"search-locally-for-kexts", OptionValue::eTypeBoolean, true, true, NULL,
- NULL, "Automatically search for kexts on the local system when doing "
+ {}, "Automatically search for kexts on the local system when doing "
"kernel debugging."},
- {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL,
+ {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, {},
"Directories/KDKs to search for kexts in when starting a kernel debug "
- "session."},
- {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
+ "session."}};
enum { ePropertySearchForKexts = 0, ePropertyKextDirectories };
@@ -354,6 +350,8 @@ void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
"/Platforms/AppleTVOS.platform/Developer/SDKs");
AddSDKSubdirsToSearchPaths(developer_dir +
"/Platforms/WatchOS.platform/Developer/SDKs");
+ AddSDKSubdirsToSearchPaths(developer_dir +
+ "/Platforms/BridgeOS.platform/Developer/SDKs");
}
if (m_ios_debug_session != eLazyBoolYes) {
AddSDKSubdirsToSearchPaths(developer_dir +
@@ -375,12 +373,15 @@ void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
GetUserSpecifiedDirectoriesToSearch();
// Add simple directory /Applications/Xcode.app/Contents/Developer/../Symbols
- FileSpec possible_dir(developer_dir + "/../Symbols", true);
- if (llvm::sys::fs::is_directory(possible_dir.GetPath()))
+ FileSpec possible_dir(developer_dir + "/../Symbols");
+ FileSystem::Instance().Resolve(possible_dir);
+ if (FileSystem::Instance().IsDirectory(possible_dir))
m_search_directories.push_back(possible_dir);
// Add simple directory of the current working directory
- m_search_directories_no_recursing.push_back(FileSpec(".", true));
+ FileSpec cwd(".");
+ FileSystem::Instance().Resolve(cwd);
+ m_search_directories_no_recursing.push_back(cwd);
}
void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch() {
@@ -390,8 +391,8 @@ void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch() {
const uint32_t user_dirs_count = user_dirs.GetSize();
for (uint32_t i = 0; i < user_dirs_count; i++) {
FileSpec dir = user_dirs.GetFileSpecAtIndex(i);
- dir.ResolvePath();
- if (llvm::sys::fs::is_directory(dir.GetPath())) {
+ FileSystem::Instance().Resolve(dir);
+ if (FileSystem::Instance().IsDirectory(dir)) {
m_search_directories.push_back(dir);
}
}
@@ -406,14 +407,14 @@ void PlatformDarwinKernel::AddRootSubdirsToSearchPaths(
// /AppleInternal/Developer/KDKs/*.kdk/...
nullptr};
for (int i = 0; subdirs[i] != nullptr; i++) {
- FileSpec testdir(dir + subdirs[i], true);
- if (llvm::sys::fs::is_directory(testdir.GetPath()))
+ FileSpec testdir(dir + subdirs[i]);
+ FileSystem::Instance().Resolve(testdir);
+ if (FileSystem::Instance().IsDirectory(testdir))
thisp->m_search_directories.push_back(testdir);
}
// Look for kernel binaries in the top level directory, without any recursion
- thisp->m_search_directories_no_recursing.push_back(
- FileSpec(dir + "/", false));
+ thisp->m_search_directories_no_recursing.push_back(FileSpec(dir + "/"));
}
// Given a directory path dir, look for any subdirs named *.kdk and *.sdk
@@ -422,25 +423,26 @@ void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) {
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
- FileSpec::EnumerateDirectory(dir.c_str(), find_directories, find_files,
- find_other, FindKDKandSDKDirectoriesInDirectory,
- this);
+ FileSystem::Instance().EnumerateDirectory(
+ dir.c_str(), find_directories, find_files, find_other,
+ FindKDKandSDKDirectoriesInDirectory, this);
}
// Helper function to find *.sdk and *.kdk directories in a given directory.
-FileSpec::EnumerateDirectoryResult
+FileSystem::EnumerateDirectoryResult
PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory(
- void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
+ void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
static ConstString g_sdk_suffix = ConstString(".sdk");
static ConstString g_kdk_suffix = ConstString(".kdk");
PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
+ FileSpec file_spec(path);
if (ft == llvm::sys::fs::file_type::directory_file &&
(file_spec.GetFileNameExtension() == g_sdk_suffix ||
file_spec.GetFileNameExtension() == g_kdk_suffix)) {
AddRootSubdirsToSearchPaths(thisp, file_spec.GetPath());
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
// Recursively search trough m_search_directories looking for kext and kernel
@@ -452,7 +454,7 @@ void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
const bool find_directories = true;
const bool find_files = true;
const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
- FileSpec::EnumerateDirectory(
+ FileSystem::Instance().EnumerateDirectory(
dir.GetPath().c_str(), find_directories, find_files, find_other,
GetKernelsAndKextsInDirectoryWithRecursion, this);
}
@@ -462,7 +464,7 @@ void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
const bool find_directories = true;
const bool find_files = true;
const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
- FileSpec::EnumerateDirectory(
+ FileSystem::Instance().EnumerateDirectory(
dir.GetPath().c_str(), find_directories, find_files, find_other,
GetKernelsAndKextsInDirectoryNoRecursion, this);
}
@@ -476,25 +478,27 @@ void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
//
// Recurse into any subdirectories found.
-FileSpec::EnumerateDirectoryResult
+FileSystem::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryWithRecursion(
- void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
- return GetKernelsAndKextsInDirectoryHelper(baton, ft, file_spec, true);
+ void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
+ return GetKernelsAndKextsInDirectoryHelper(baton, ft, path, true);
}
-FileSpec::EnumerateDirectoryResult
+FileSystem::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryNoRecursion(
- void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
- return GetKernelsAndKextsInDirectoryHelper(baton, ft, file_spec, false);
+ void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
+ return GetKernelsAndKextsInDirectoryHelper(baton, ft, path, false);
}
-FileSpec::EnumerateDirectoryResult
+FileSystem::EnumerateDirectoryResult
PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
- void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec,
+ void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path,
bool recurse) {
static ConstString g_kext_suffix = ConstString(".kext");
static ConstString g_dsym_suffix = ConstString(".dSYM");
static ConstString g_bundle_suffix = ConstString("Bundle");
+
+ FileSpec file_spec(path);
ConstString file_spec_extension = file_spec.GetFileNameExtension();
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
@@ -526,19 +530,19 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
}
thisp->m_kernel_binaries_without_dsyms.push_back(file_spec);
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
} else if (ft == llvm::sys::fs::file_type::directory_file &&
file_spec_extension == g_kext_suffix) {
AddKextToMap(thisp, file_spec);
// Look to see if there is a PlugIns subdir with more kexts
- FileSpec contents_plugins(file_spec.GetPath() + "/Contents/PlugIns", false);
+ FileSpec contents_plugins(file_spec.GetPath() + "/Contents/PlugIns");
std::string search_here_too;
- if (llvm::sys::fs::is_directory(contents_plugins.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(contents_plugins)) {
search_here_too = contents_plugins.GetPath();
} else {
- FileSpec plugins(file_spec.GetPath() + "/PlugIns", false);
- if (llvm::sys::fs::is_directory(plugins.GetPath())) {
+ FileSpec plugins(file_spec.GetPath() + "/PlugIns");
+ if (FileSystem::Instance().IsDirectory(plugins)) {
search_here_too = plugins.GetPath();
}
}
@@ -547,13 +551,13 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
const bool find_directories = true;
const bool find_files = false;
const bool find_other = false;
- FileSpec::EnumerateDirectory(
+ FileSystem::Instance().EnumerateDirectory(
search_here_too.c_str(), find_directories, find_files, find_other,
recurse ? GetKernelsAndKextsInDirectoryWithRecursion
: GetKernelsAndKextsInDirectoryNoRecursion,
baton);
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
// Don't recurse into dSYM/kext/bundle directories
if (recurse && file_spec_extension != g_dsym_suffix &&
@@ -561,9 +565,9 @@ PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
file_spec_extension != g_bundle_suffix) {
if (log_verbose)
log_verbose->Printf ("PlatformDarwinKernel descending into directory '%s'", file_spec.GetPath().c_str());
- return FileSpec::eEnumerateDirectoryResultEnter;
+ return FileSystem::eEnumerateDirectoryResultEnter;
} else {
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
}
@@ -610,7 +614,7 @@ bool PlatformDarwinKernel::KextHasdSYMSibling(
std::string filename = dsym_fspec.GetFilename().AsCString();
filename += ".dSYM";
dsym_fspec.GetFilename() = ConstString(filename);
- if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) {
+ if (FileSystem::Instance().IsDirectory(dsym_fspec)) {
return true;
}
// Should probably get the CFBundleExecutable here or call
@@ -623,8 +627,9 @@ bool PlatformDarwinKernel::KextHasdSYMSibling(
kext_bundle_filepath.GetPath() + "/Contents/MacOS/";
deep_bundle_str += executable_name.AsCString();
deep_bundle_str += ".dSYM";
- dsym_fspec.SetFile(deep_bundle_str, true, FileSpec::Style::native);
- if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) {
+ dsym_fspec.SetFile(deep_bundle_str, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dsym_fspec);
+ if (FileSystem::Instance().IsDirectory(dsym_fspec)) {
return true;
}
@@ -633,11 +638,9 @@ bool PlatformDarwinKernel::KextHasdSYMSibling(
std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/";
shallow_bundle_str += executable_name.AsCString();
shallow_bundle_str += ".dSYM";
- dsym_fspec.SetFile(shallow_bundle_str, true, FileSpec::Style::native);
- if (llvm::sys::fs::is_directory(dsym_fspec.GetPath())) {
- return true;
- }
- return false;
+ dsym_fspec.SetFile(shallow_bundle_str, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dsym_fspec);
+ return FileSystem::Instance().IsDirectory(dsym_fspec);
}
// Given a FileSpec of /dir/dir/mach.development.t7004 Return true if a dSYM
@@ -648,10 +651,7 @@ bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) {
std::string filename = kernel_binary.GetFilename().AsCString();
filename += ".dSYM";
kernel_dsym.GetFilename() = ConstString(filename);
- if (llvm::sys::fs::is_directory(kernel_dsym.GetPath())) {
- return true;
- }
- return false;
+ return FileSystem::Instance().IsDirectory(kernel_dsym);
}
Status PlatformDarwinKernel::GetSharedModule(
@@ -710,11 +710,10 @@ Status PlatformDarwinKernel::GetSharedModule(
}
}
- if (kext_bundle_id.compare("mach_kernel") == 0 &&
- module_spec.GetUUID().IsValid()) {
+ if (kext_bundle_id == "mach_kernel" && module_spec.GetUUID().IsValid()) {
// First try all kernel binaries that have a dSYM next to them
for (auto possible_kernel : m_kernel_binaries_with_dsyms) {
- if (possible_kernel.Exists()) {
+ if (FileSystem::Instance().Exists(possible_kernel)) {
ModuleSpec kern_spec(possible_kernel);
kern_spec.GetUUID() = module_spec.GetUUID();
ModuleSP module_sp(new Module(kern_spec));
@@ -750,7 +749,7 @@ Status PlatformDarwinKernel::GetSharedModule(
// Next try all kernel binaries that don't have a dSYM
for (auto possible_kernel : m_kernel_binaries_without_dsyms) {
- if (possible_kernel.Exists()) {
+ if (FileSystem::Instance().Exists(possible_kernel)) {
ModuleSpec kern_spec(possible_kernel);
kern_spec.GetUUID() = module_spec.GetUUID();
ModuleSP module_sp(new Module(kern_spec));
@@ -791,7 +790,7 @@ PlatformDarwinKernel::SearchForExecutablesRecursively(const std::string &dir) {
break;
if (llvm::sys::fs::is_regular_file(*status) &&
llvm::sys::fs::can_execute(it->path()))
- executables.emplace_back(it->path(), false);
+ executables.emplace_back(it->path());
}
return executables;
}
@@ -801,7 +800,7 @@ Status PlatformDarwinKernel::ExamineKextForMatchingUUID(
const ArchSpec &arch, ModuleSP &exe_module_sp) {
for (const auto &exe_file :
SearchForExecutablesRecursively(kext_bundle_path.GetPath())) {
- if (exe_file.Exists()) {
+ if (FileSystem::Instance().Exists(exe_file)) {
ModuleSpec exe_spec(exe_file);
exe_spec.GetUUID() = uuid;
if (!uuid.IsValid()) {
diff --git a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
index 7f603cac2bec..201c3dff1795 100644
--- a/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
+++ b/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.h
@@ -15,14 +15,10 @@
#if defined(__APPLE__) // This Plugin uses the Mac-specific
// source/Host/macosx/cfcpp utilities
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/FileSystem.h"
-// Project includes
#include "PlatformDarwin.h"
class PlatformDarwinKernel : public PlatformDarwin {
@@ -106,26 +102,25 @@ protected:
void AddSDKSubdirsToSearchPaths(const std::string &dir);
- static lldb_private::FileSpec::EnumerateDirectoryResult
+ static lldb_private::FileSystem::EnumerateDirectoryResult
FindKDKandSDKDirectoriesInDirectory(void *baton, llvm::sys::fs::file_type ft,
- const lldb_private::FileSpec &file_spec);
+ llvm::StringRef path);
void SearchForKextsAndKernelsRecursively();
- static lldb_private::FileSpec::EnumerateDirectoryResult
- GetKernelsAndKextsInDirectoryWithRecursion(
- void *baton, llvm::sys::fs::file_type ft,
- const lldb_private::FileSpec &file_spec);
+ static lldb_private::FileSystem::EnumerateDirectoryResult
+ GetKernelsAndKextsInDirectoryWithRecursion(void *baton,
+ llvm::sys::fs::file_type ft,
+ llvm::StringRef path);
- static lldb_private::FileSpec::EnumerateDirectoryResult
- GetKernelsAndKextsInDirectoryNoRecursion(
- void *baton, llvm::sys::fs::file_type ft,
- const lldb_private::FileSpec &file_spec);
+ static lldb_private::FileSystem::EnumerateDirectoryResult
+ GetKernelsAndKextsInDirectoryNoRecursion(void *baton,
+ llvm::sys::fs::file_type ft,
+ llvm::StringRef path);
- static lldb_private::FileSpec::EnumerateDirectoryResult
+ static lldb_private::FileSystem::EnumerateDirectoryResult
GetKernelsAndKextsInDirectoryHelper(void *baton, llvm::sys::fs::file_type ft,
- const lldb_private::FileSpec &file_spec,
- bool recurse);
+ llvm::StringRef path, bool recurse);
static std::vector<lldb_private::FileSpec>
SearchForExecutablesRecursively(const std::string &dir);
@@ -148,7 +143,7 @@ protected:
const lldb_private::ArchSpec &arch,
lldb::ModuleSP &exe_module_sp);
- // Most of the ivars are assembled under FileSpec::EnumerateDirectory calls
+ // Most of the ivars are assembled under FileSystem::EnumerateDirectory calls
// where the
// function being called for each file/directory must be static. We'll pass a
// this pointer
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
index 99f603b01f43..4117231c308a 100644
--- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp
@@ -10,12 +10,9 @@
#include "PlatformMacOSX.h"
#include "lldb/Host/Config.h"
-// C++ Includes
#include <sstream>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -83,7 +80,7 @@ PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) {
const bool is_host = false;
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::Apple:
@@ -93,7 +90,7 @@ PlatformSP PlatformMacOSX::CreateInstance(bool force, const ArchSpec *arch) {
#if defined(__APPLE__)
// Only accept "unknown" for vendor if the host is Apple and it "unknown"
// wasn't specified (it was just returned because it was NOT specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
#endif
@@ -218,14 +215,14 @@ ConstString PlatformMacOSX::GetSDKDirectory(lldb_private::Target &target) {
"SDKs/MacOSX%u.%u.sdk",
xcode_contents_path.c_str(), versions[0],
versions[1]);
- fspec.SetFile(sdk_path.GetString(), false, FileSpec::Style::native);
- if (fspec.Exists())
+ fspec.SetFile(sdk_path.GetString(), FileSpec::Style::native);
+ if (FileSystem::Instance().Exists(fspec))
return ConstString(sdk_path.GetString());
}
if (!default_xcode_sdk.empty()) {
- fspec.SetFile(default_xcode_sdk, false, FileSpec::Style::native);
- if (fspec.Exists())
+ fspec.SetFile(default_xcode_sdk, FileSpec::Style::native);
+ if (FileSystem::Instance().Exists(fspec))
return ConstString(default_xcode_sdk);
}
}
@@ -259,7 +256,7 @@ PlatformMacOSX::GetFileWithUUID(const lldb_private::FileSpec &platform_file,
#endif
std::string remote_os_build;
m_remote_platform_sp->GetOSBuildString(remote_os_build);
- if (local_os_build.compare(remote_os_build) == 0) {
+ if (local_os_build == remote_os_build) {
// same OS version: the local file is good enough
local_file = platform_file;
return Status();
@@ -268,8 +265,8 @@ PlatformMacOSX::GetFileWithUUID(const lldb_private::FileSpec &platform_file,
std::string cache_path(GetLocalCacheDirectory());
std::string module_path(platform_file.GetPath());
cache_path.append(module_path);
- FileSpec module_cache_spec(cache_path, false);
- if (module_cache_spec.Exists()) {
+ FileSpec module_cache_spec(cache_path);
+ if (FileSystem::Instance().Exists(module_cache_spec)) {
local_file = module_cache_spec;
return Status();
}
@@ -284,7 +281,7 @@ PlatformMacOSX::GetFileWithUUID(const lldb_private::FileSpec &platform_file,
err = GetFile(platform_file, module_cache_spec);
if (err.Fail())
return err;
- if (module_cache_spec.Exists()) {
+ if (FileSystem::Instance().Exists(module_cache_spec)) {
local_file = module_cache_spec;
return Status();
} else
diff --git a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
index d1e609258d4d..d08029a29f31 100644
--- a/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
+++ b/source/Plugins/Platform/MacOSX/PlatformMacOSX.h
@@ -10,10 +10,6 @@
#ifndef liblldb_PlatformMacOSX_h_
#define liblldb_PlatformMacOSX_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "PlatformDarwin.h"
class PlatformMacOSX : public PlatformDarwin {
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp
new file mode 100644
index 000000000000..fd804d0aaeed
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.cpp
@@ -0,0 +1,186 @@
+//===-- PlatformRemoteAppleBridge.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string>
+#include <vector>
+
+#include "PlatformRemoteAppleBridge.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformRemoteAppleBridge::PlatformRemoteAppleBridge()
+ : PlatformRemoteDarwinDevice () {}
+
+//------------------------------------------------------------------
+// Static Variables
+//------------------------------------------------------------------
+static uint32_t g_initialize_count = 0;
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+void PlatformRemoteAppleBridge::Initialize() {
+ PlatformDarwin::Initialize();
+
+ if (g_initialize_count++ == 0) {
+ PluginManager::RegisterPlugin(PlatformRemoteAppleBridge::GetPluginNameStatic(),
+ PlatformRemoteAppleBridge::GetDescriptionStatic(),
+ PlatformRemoteAppleBridge::CreateInstance);
+ }
+}
+
+void PlatformRemoteAppleBridge::Terminate() {
+ if (g_initialize_count > 0) {
+ if (--g_initialize_count == 0) {
+ PluginManager::UnregisterPlugin(PlatformRemoteAppleBridge::CreateInstance);
+ }
+ }
+
+ PlatformDarwin::Terminate();
+}
+
+PlatformSP PlatformRemoteAppleBridge::CreateInstance(bool force,
+ const ArchSpec *arch) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log) {
+ const char *arch_name;
+ if (arch && arch->GetArchitectureName())
+ arch_name = arch->GetArchitectureName();
+ else
+ arch_name = "<null>";
+
+ const char *triple_cstr =
+ arch ? arch->GetTriple().getTriple().c_str() : "<null>";
+
+ log->Printf("PlatformRemoteAppleBridge::%s(force=%s, arch={%s,%s})",
+ __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
+ }
+
+ bool create = force;
+ if (!create && arch && arch->IsValid()) {
+ switch (arch->GetMachine()) {
+ case llvm::Triple::aarch64: {
+ const llvm::Triple &triple = arch->GetTriple();
+ llvm::Triple::VendorType vendor = triple.getVendor();
+ switch (vendor) {
+ case llvm::Triple::Apple:
+ create = true;
+ break;
+
+#if defined(__APPLE__)
+ // Only accept "unknown" for the vendor if the host is Apple and
+ // it "unknown" wasn't specified (it was just returned because it
+ // was NOT specified)
+ case llvm::Triple::UnknownVendor:
+ create = !arch->TripleVendorWasSpecified();
+ break;
+
+#endif
+ default:
+ break;
+ }
+ if (create) {
+ switch (triple.getOS()) {
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
+ break;
+
+ default:
+ create = false;
+ break;
+ }
+ }
+ } break;
+ default:
+ break;
+ }
+ }
+
+ if (create) {
+ if (log)
+ log->Printf("PlatformRemoteAppleBridge::%s() creating platform",
+ __FUNCTION__);
+
+ return lldb::PlatformSP(new PlatformRemoteAppleBridge());
+ }
+
+ if (log)
+ log->Printf("PlatformRemoteAppleBridge::%s() aborting creation of platform",
+ __FUNCTION__);
+
+ return lldb::PlatformSP();
+}
+
+lldb_private::ConstString PlatformRemoteAppleBridge::GetPluginNameStatic() {
+ static ConstString g_name("remote-bridgeos");
+ return g_name;
+}
+
+const char *PlatformRemoteAppleBridge::GetDescriptionStatic() {
+ return "Remote BridgeOS platform plug-in.";
+}
+
+bool PlatformRemoteAppleBridge::GetSupportedArchitectureAtIndex(uint32_t idx,
+ ArchSpec &arch) {
+ ArchSpec system_arch(GetSystemArchitecture());
+
+ const ArchSpec::Core system_core = system_arch.GetCore();
+ switch (system_core) {
+ default:
+ switch (idx) {
+ case 0:
+ arch.SetTriple("arm64-apple-bridgeos");
+ return true;
+ default:
+ break;
+ }
+ break;
+
+ case ArchSpec::eCore_arm_arm64:
+ switch (idx) {
+ case 0:
+ arch.SetTriple("arm64-apple-bridgeos");
+ return true;
+ default:
+ break;
+ }
+ break;
+ }
+ arch.Clear();
+ return false;
+}
+
+
+void PlatformRemoteAppleBridge::GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames)
+{
+ dirnames.clear();
+ dirnames.push_back("BridgeOS DeviceSupport");
+}
+
+std::string PlatformRemoteAppleBridge::GetPlatformName ()
+{
+ return "BridgeOS.platform";
+}
+
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h
new file mode 100644
index 000000000000..48f06eee3f01
--- /dev/null
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleBridge.h
@@ -0,0 +1,73 @@
+//===-- PlatformRemoteAppleBridge.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_PlatformRemoteAppleBridge_h_
+#define liblldb_PlatformRemoteAppleBridge_h_
+
+#include <string>
+
+#include "lldb/Utility/FileSpec.h"
+
+#include "llvm/Support/FileSystem.h"
+
+#include "PlatformRemoteDarwinDevice.h"
+
+class PlatformRemoteAppleBridge : public PlatformRemoteDarwinDevice {
+public:
+ PlatformRemoteAppleBridge();
+
+ ~PlatformRemoteAppleBridge() override = default;
+
+ //------------------------------------------------------------
+ // Class Functions
+ //------------------------------------------------------------
+ static lldb::PlatformSP CreateInstance(bool force,
+ const lldb_private::ArchSpec *arch);
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static lldb_private::ConstString GetPluginNameStatic();
+
+ static const char *GetDescriptionStatic();
+
+ //------------------------------------------------------------
+ // lldb_private::PluginInterface functions
+ //------------------------------------------------------------
+ lldb_private::ConstString GetPluginName() override {
+ return GetPluginNameStatic();
+ }
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ //------------------------------------------------------------
+ // lldb_private::Platform functions
+ //------------------------------------------------------------
+
+ const char *GetDescription() override { return GetDescriptionStatic(); }
+
+ bool GetSupportedArchitectureAtIndex(uint32_t idx,
+ lldb_private::ArchSpec &arch) override;
+
+protected:
+
+ //------------------------------------------------------------
+ // lldb_private::PlatformRemoteDarwinDevice functions
+ //------------------------------------------------------------
+
+ void GetDeviceSupportDirectoryNames (std::vector<std::string> &dirnames) override;
+
+ std::string GetPlatformName () override;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(PlatformRemoteAppleBridge);
+};
+
+#endif // liblldb_PlatformRemoteAppleBridge_h_
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
index be4c829a981c..593e888898c4 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.cpp
@@ -7,13 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "PlatformRemoteAppleTV.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -101,7 +97,7 @@ PlatformSP PlatformRemoteAppleTV::CreateInstance(bool force,
// Only accept "unknown" for the vendor if the host is Apple and
// "unknown" wasn't specified (it was just returned because it was NOT
// specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h
index 08dd231e85ee..d8860a90a460 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleTV.h
@@ -10,12 +10,8 @@
#ifndef liblldb_PlatformRemoteAppleTV_h_
#define liblldb_PlatformRemoteAppleTV_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/FileSpec.h"
#include "llvm/Support/FileSystem.h"
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
index 6159511d4a18..59e6e19fbffc 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.cpp
@@ -7,13 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "PlatformRemoteAppleWatch.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -96,7 +92,7 @@ PlatformSP PlatformRemoteAppleWatch::CreateInstance(bool force,
// Only accept "unknown" for the vendor if the host is Apple and
// "unknown" wasn't specified (it was just returned because it was NOT
// specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h
index 93be55b595f8..ed1cbea62e92 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteAppleWatch.h
@@ -10,13 +10,9 @@
#ifndef liblldb_PlatformRemoteAppleWatch_h_
#define liblldb_PlatformRemoteAppleWatch_h_
-// C Includes
-// C++ Includes
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/FileSpec.h"
#include "PlatformRemoteDarwinDevice.h"
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
index 930d062fe41e..511bfc20376b 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
@@ -9,15 +9,12 @@
#include "PlatformRemoteDarwinDevice.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -85,7 +82,7 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable(
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
@@ -119,7 +116,7 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable(
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -139,12 +136,12 @@ Status PlatformRemoteDarwinDevice::ResolveExecutable(
return error;
}
-FileSpec::EnumerateDirectoryResult
+FileSystem::EnumerateDirectoryResult
PlatformRemoteDarwinDevice::GetContainedFilesIntoVectorOfStringsCallback(
- void *baton, llvm::sys::fs::file_type ft, const FileSpec &file_spec) {
+ void *baton, llvm::sys::fs::file_type ft, llvm::StringRef path) {
((PlatformRemoteDarwinDevice::SDKDirectoryInfoCollection *)baton)
- ->push_back(PlatformRemoteDarwinDevice::SDKDirectoryInfo(file_spec));
- return FileSpec::eEnumerateDirectoryResultNext;
+ ->push_back(PlatformRemoteDarwinDevice::SDKDirectoryInfo(FileSpec(path)));
+ return FileSystem::eEnumerateDirectoryResultNext;
}
bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
@@ -153,7 +150,8 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
if (m_sdk_directory_infos.empty()) {
// A --sysroot option was supplied - add it to our list of SDKs to check
if (m_sdk_sysroot) {
- FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString(), true);
+ FileSpec sdk_sysroot_fspec(m_sdk_sysroot.GetCString());
+ FileSystem::Instance().Resolve(sdk_sysroot_fspec);
const SDKDirectoryInfo sdk_sysroot_directory_info(sdk_sysroot_fspec);
m_sdk_directory_infos.push_back(sdk_sysroot_directory_info);
if (log) {
@@ -175,10 +173,10 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
const bool find_other = false;
SDKDirectoryInfoCollection builtin_sdk_directory_infos;
- FileSpec::EnumerateDirectory(m_device_support_directory, find_directories,
- find_files, find_other,
- GetContainedFilesIntoVectorOfStringsCallback,
- &builtin_sdk_directory_infos);
+ FileSystem::Instance().EnumerateDirectory(
+ m_device_support_directory, find_directories, find_files, find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &builtin_sdk_directory_infos);
// Only add SDK directories that have symbols in them, some SDKs only
// contain developer disk images and no symbols, so they aren't useful to
@@ -187,7 +185,7 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
for (const auto &sdk_directory_info : builtin_sdk_directory_infos) {
sdk_symbols_symlink_fspec = sdk_directory_info.directory;
sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
- if (sdk_symbols_symlink_fspec.Exists()) {
+ if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) {
m_sdk_directory_infos.push_back(sdk_directory_info);
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
@@ -205,22 +203,23 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
const uint32_t num_installed = m_sdk_directory_infos.size();
std::string local_sdk_cache_str = "~/Library/Developer/Xcode/";
local_sdk_cache_str += dirname;
- FileSpec local_sdk_cache(local_sdk_cache_str.c_str(), true);
- if (local_sdk_cache.Exists()) {
- if (log) {
+ FileSpec local_sdk_cache(local_sdk_cache_str.c_str());
+ FileSystem::Instance().Resolve(local_sdk_cache);
+ if (FileSystem::Instance().Exists(local_sdk_cache)) {
+ if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
"searching %s for additional SDKs",
local_sdk_cache.GetPath().c_str());
- }
+ }
char path[PATH_MAX];
if (local_sdk_cache.GetPath(path, sizeof(path))) {
- FileSpec::EnumerateDirectory(
- path, find_directories, find_files, find_other,
- GetContainedFilesIntoVectorOfStringsCallback,
- &m_sdk_directory_infos);
- const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
- // First try for an exact match of major, minor and update
- for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
+ FileSystem::Instance().EnumerateDirectory(
+ path, find_directories, find_files, find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &m_sdk_directory_infos);
+ const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
+ // First try for an exact match of major, minor and update
+ for (uint32_t i = num_installed; i < num_sdk_infos; ++i) {
m_sdk_directory_infos[i].user_cached = true;
if (log) {
log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
@@ -231,6 +230,29 @@ bool PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded() {
}
}
}
+
+ const char *addtional_platform_dirs = getenv("PLATFORM_SDK_DIRECTORY");
+ if (addtional_platform_dirs) {
+ SDKDirectoryInfoCollection env_var_sdk_directory_infos;
+ FileSystem::Instance().EnumerateDirectory(
+ addtional_platform_dirs, find_directories, find_files, find_other,
+ GetContainedFilesIntoVectorOfStringsCallback,
+ &env_var_sdk_directory_infos);
+ FileSpec sdk_symbols_symlink_fspec;
+ for (const auto &sdk_directory_info : env_var_sdk_directory_infos) {
+ sdk_symbols_symlink_fspec = sdk_directory_info.directory;
+ sdk_symbols_symlink_fspec.AppendPathComponent("Symbols");
+ if (FileSystem::Instance().Exists(sdk_symbols_symlink_fspec)) {
+ m_sdk_directory_infos.push_back(sdk_directory_info);
+ if (log) {
+ log->Printf("PlatformRemoteDarwinDevice::UpdateSDKDirectoryInfosIfNeeded "
+ "added env var SDK directory %s",
+ sdk_symbols_symlink_fspec.GetPath().c_str());
+ }
+ }
+ }
+ }
+
}
}
return !m_sdk_directory_infos.empty();
@@ -395,12 +417,12 @@ bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
- local_file.SetFile(sdkroot_path, false, FileSpec::Style::native);
+ local_file.SetFile(sdkroot_path, FileSpec::Style::native);
if (paths_to_try[i][0] != '\0')
local_file.AppendPathComponent(paths_to_try[i]);
local_file.AppendPathComponent(platform_file_path);
- local_file.ResolvePath();
- if (local_file.Exists()) {
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file)) {
if (log)
log->Printf("Found a copy of %s in the SDK dir %s/%s",
platform_file_path, sdkroot_path.c_str(),
@@ -428,8 +450,9 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
::snprintf(resolved_path, sizeof(resolved_path), "%s/%s", os_version_dir,
platform_file_path);
- local_file.SetFile(resolved_path, true, FileSpec::Style::native);
- if (local_file.Exists()) {
+ local_file.SetFile(resolved_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file)) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s",
platform_file_path, os_version_dir);
@@ -440,8 +463,9 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols.Internal/%s",
os_version_dir, platform_file_path);
- local_file.SetFile(resolved_path, true, FileSpec::Style::native);
- if (local_file.Exists()) {
+ local_file.SetFile(resolved_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file)) {
if (log) {
log->Printf(
"Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
@@ -452,8 +476,9 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
::snprintf(resolved_path, sizeof(resolved_path), "%s/Symbols/%s",
os_version_dir, platform_file_path);
- local_file.SetFile(resolved_path, true, FileSpec::Style::native);
- if (local_file.Exists()) {
+ local_file.SetFile(resolved_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file)) {
if (log) {
log->Printf("Found a copy of %s in the DeviceSupport dir %s/Symbols",
platform_file_path, os_version_dir);
@@ -462,7 +487,7 @@ Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
}
}
local_file = platform_file;
- if (local_file.Exists())
+ if (FileSystem::Instance().Exists(local_file))
return error;
error.SetErrorStringWithFormat(
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
index 8ddfd51600fd..d32179d6c98e 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.h
@@ -10,12 +10,8 @@
#ifndef liblldb_PlatformRemoteDarwinDevice_h_
#define liblldb_PlatformRemoteDarwinDevice_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "PlatformDarwin.h"
#include "lldb/Utility/FileSpec.h"
@@ -84,10 +80,10 @@ protected:
const SDKDirectoryInfo *GetSDKDirectoryForCurrentOSVersion();
- static lldb_private::FileSpec::EnumerateDirectoryResult
- GetContainedFilesIntoVectorOfStringsCallback(
- void *baton, llvm::sys::fs::file_type ft,
- const lldb_private::FileSpec &file_spec);
+ static lldb_private::FileSystem::EnumerateDirectoryResult
+ GetContainedFilesIntoVectorOfStringsCallback(void *baton,
+ llvm::sys::fs::file_type ft,
+ llvm::StringRef path);
uint32_t FindFileInAllSDKs(const char *platform_file_path,
lldb_private::FileSpecList &file_list);
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
index 150bfdbfc118..b69d7ea36abf 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
@@ -9,10 +9,6 @@
#include "PlatformRemoteiOS.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -75,7 +71,7 @@ PlatformSP PlatformRemoteiOS::CreateInstance(bool force, const ArchSpec *arch) {
}
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
switch (arch->GetMachine()) {
case llvm::Triple::arm:
case llvm::Triple::aarch64:
@@ -91,7 +87,7 @@ PlatformSP PlatformRemoteiOS::CreateInstance(bool force, const ArchSpec *arch) {
// Only accept "unknown" for the vendor if the host is Apple and
// "unknown" wasn't specified (it was just returned because it was NOT
// specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
diff --git a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
index 975f50b421f1..7e45dc3c2889 100644
--- a/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
+++ b/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
@@ -10,12 +10,8 @@
#ifndef liblldb_PlatformRemoteiOS_h_
#define liblldb_PlatformRemoteiOS_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "PlatformRemoteDarwinDevice.h"
#include "lldb/Utility/FileSpec.h"
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
index 26feec282322..b1d5960bb682 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.cpp
@@ -10,10 +10,6 @@
#include "PlatformiOSSimulator.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -80,7 +76,7 @@ PlatformSP PlatformiOSSimulator::CreateInstance(bool force,
}
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
switch (arch->GetMachine()) {
case llvm::Triple::x86_64:
case llvm::Triple::x86: {
@@ -94,7 +90,7 @@ PlatformSP PlatformiOSSimulator::CreateInstance(bool force,
// Only accept "unknown" for the vendor if the host is Apple and it
// "unknown" wasn't specified (it was just returned because it was NOT
// specified)
- case llvm::Triple::UnknownArch:
+ case llvm::Triple::UnknownVendor:
create = !arch->TripleVendorWasSpecified();
break;
#endif
@@ -196,7 +192,7 @@ Status PlatformiOSSimulator::ResolveExecutable(
// ourselves
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
if (resolved_module_spec.GetArchitecture().IsValid()) {
error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
NULL, NULL, NULL);
@@ -234,7 +230,7 @@ Status PlatformiOSSimulator::ResolveExecutable(
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -253,18 +249,19 @@ Status PlatformiOSSimulator::ResolveExecutable(
return error;
}
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
EnumerateDirectoryCallback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &file_spec) {
+ llvm::StringRef path) {
if (ft == llvm::sys::fs::file_type::directory_file) {
+ FileSpec file_spec(path);
const char *filename = file_spec.GetFilename().GetCString();
if (filename &&
strncmp(filename, "iPhoneSimulator", strlen("iPhoneSimulator")) == 0) {
::snprintf((char *)baton, PATH_MAX, "%s", filename);
- return FileSpec::eEnumerateDirectoryResultQuit;
+ return FileSystem::eEnumerateDirectoryResultQuit;
}
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
}
const char *PlatformiOSSimulator::GetSDKDirectoryAsCString() {
@@ -282,9 +279,9 @@ const char *PlatformiOSSimulator::GetSDKDirectoryAsCString() {
bool find_directories = true;
bool find_files = false;
bool find_other = false;
- FileSpec::EnumerateDirectory(sdks_directory, find_directories, find_files,
- find_other, EnumerateDirectoryCallback,
- sdk_dirname);
+ FileSystem::Instance().EnumerateDirectory(
+ sdks_directory, find_directories, find_files, find_other,
+ EnumerateDirectoryCallback, sdk_dirname);
if (sdk_dirname[0]) {
m_sdk_directory = sdks_directory;
@@ -320,13 +317,15 @@ Status PlatformiOSSimulator::GetSymbolFile(const FileSpec &platform_file,
platform_file_path);
// First try in the SDK and see if the file is in there
- local_file.SetFile(resolved_path, true, FileSpec::Style::native);
- if (local_file.Exists())
+ local_file.SetFile(resolved_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file))
return error;
// Else fall back to the actual path itself
- local_file.SetFile(platform_file_path, true, FileSpec::Style::native);
- if (local_file.Exists())
+ local_file.SetFile(platform_file_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(local_file);
+ if (FileSystem::Instance().Exists(local_file))
return error;
}
error.SetErrorStringWithFormat(
diff --git a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
index 2d81d6229f73..4ac43a4dde28 100644
--- a/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
+++ b/source/Plugins/Platform/MacOSX/PlatformiOSSimulator.h
@@ -10,13 +10,9 @@
#ifndef liblldb_PlatformiOSSimulator_h_
#define liblldb_PlatformiOSSimulator_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "PlatformAppleSimulator.h"
class PlatformiOSSimulator : public PlatformAppleSimulator {
diff --git a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
index 083e2d6c5687..bec35aaaf33b 100644
--- a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
+++ b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.h
@@ -11,19 +11,15 @@
#ifndef liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_
#define liblldb_PlatformiOSSimulatorCoreSimulatorSupport_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <ostream>
#include <string>
#include <vector>
-// Other libraries and framework includes
#ifdef __APPLE__
#include <objc/objc.h>
#else
typedef void *id;
#endif
-// Project includes
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
diff --git a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
index 4516a66ee8ca..a601e27dc8a1 100644
--- a/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
+++ b/source/Plugins/Platform/MacOSX/objcxx/PlatformiOSSimulatorCoreSimulatorSupport.mm
@@ -409,7 +409,7 @@ static Status HandleFileAction(ProcessLaunchInfo &launch_info,
// Check in case our file action open wants to open the slave
const char *slave_path = launch_info.GetPTY().GetSlaveName(NULL, 0);
if (slave_path) {
- FileSpec slave_spec(slave_path, false);
+ FileSpec slave_spec(slave_path);
if (file_spec == slave_spec) {
int slave_fd = launch_info.GetPTY().GetSlaveFileDescriptor();
if (slave_fd == PseudoTerminal::invalid_fd)
@@ -591,7 +591,7 @@ void CoreSimulatorSupport::DeviceSet::ForEach(
std::function<bool(const Device &)> f) {
const size_t n = GetNumDevices();
for (NSUInteger i = 0; i < n; ++i) {
- if (f(GetDeviceAtIndex(i)) == false)
+ if (!f(GetDeviceAtIndex(i)))
break;
}
}
diff --git a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
index 3aa8ecb4c228..aadcf961c729 100644
--- a/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
+++ b/source/Plugins/Platform/NetBSD/PlatformNetBSD.cpp
@@ -10,23 +10,19 @@
#include "PlatformNetBSD.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
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -50,7 +46,7 @@ PlatformSP PlatformNetBSD::CreateInstance(bool force, const ArchSpec *arch) {
arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::NetBSD:
@@ -271,8 +267,8 @@ PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
if (target == nullptr) {
LLDB_LOG(log, "creating new target");
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- nullptr, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
if (error.Fail()) {
LLDB_LOG(log, "failed to create new target: {0}", error);
return process_sp;
@@ -291,8 +287,8 @@ PlatformNetBSD::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger,
// Now create the gdb-remote process.
LLDB_LOG(log, "having target create process with gdb-remote plugin");
- process_sp = target->CreateProcess(
- launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr);
+ process_sp =
+ target->CreateProcess(launch_info.GetListener(), "gdb-remote", nullptr);
if (!process_sp) {
error.SetErrorString("CreateProcess() failed for gdb-remote process");
diff --git a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
index 10ca8fbfbdd7..7358acb61f79 100644
--- a/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
+++ b/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
@@ -10,23 +10,19 @@
#include "PlatformOpenBSD.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
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
@@ -50,7 +46,7 @@ PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) {
arch ? arch->GetTriple().getTriple() : "<null>");
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::OpenBSD:
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index 5e7ffe71918e..bfa1376d3151 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -9,10 +9,6 @@
#include "PlatformPOSIX.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -128,23 +124,25 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
if (IsHost()) {
// If we have "ls" as the exe_file, resolve the executable location based
// on the current path variables
- if (!resolved_module_spec.GetFileSpec().Exists()) {
+ if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
- resolved_module_spec.GetFileSpec().SetFile(exe_path, true,
+ resolved_module_spec.GetFileSpec().SetFile(exe_path,
FileSpec::Style::native);
+ FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec());
}
- if (!resolved_module_spec.GetFileSpec().Exists())
- resolved_module_spec.GetFileSpec().ResolveExecutableLocation();
+ if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
+ FileSystem::Instance().ResolveExecutableLocation(
+ resolved_module_spec.GetFileSpec());
// Resolve any executable within a bundle on MacOSX
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists())
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
error.Clear();
else {
- const uint32_t permissions =
- resolved_module_spec.GetFileSpec().GetPermissions();
+ const uint32_t permissions = FileSystem::Instance().GetPermissions(
+ resolved_module_spec.GetFileSpec());
if (permissions && (permissions & eFilePermissionsEveryoneR) == 0)
error.SetErrorStringWithFormat(
"executable '%s' is not readable",
@@ -166,7 +164,7 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
// Resolve any executable within a bundle on MacOSX
Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists())
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
error.Clear();
else
error.SetErrorStringWithFormat("the platform is not currently "
@@ -237,7 +235,8 @@ PlatformPOSIX::ResolveExecutable(const ModuleSpec &module_spec,
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(
+ resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -455,7 +454,7 @@ lldb::user_id_t PlatformPOSIX::GetFileSize(const FileSpec &file_spec) {
Status PlatformPOSIX::CreateSymlink(const FileSpec &src, const FileSpec &dst) {
if (IsHost())
- return FileSystem::Symlink(src, dst);
+ return FileSystem::Instance().Symlink(src, dst);
else if (m_remote_platform_sp)
return m_remote_platform_sp->CreateSymlink(src, dst);
else
@@ -464,7 +463,7 @@ Status PlatformPOSIX::CreateSymlink(const FileSpec &src, const FileSpec &dst) {
bool PlatformPOSIX::GetFileExists(const FileSpec &file_spec) {
if (IsHost())
- return file_spec.Exists();
+ return FileSystem::Instance().Exists(file_spec);
else if (m_remote_platform_sp)
return m_remote_platform_sp->GetFileExists(file_spec);
else
@@ -813,8 +812,8 @@ lldb::ProcessSP PlatformPOSIX::Attach(ProcessAttachInfo &attach_info,
if (target == NULL) {
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- NULL, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", "", eLoadDependentsNo, NULL, new_target_sp);
target = new_target_sp.get();
if (log)
log->Printf("PlatformPOSIX::%s created new target", __FUNCTION__);
@@ -1244,7 +1243,8 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
options.SetTrapExceptions(false); // dlopen can't throw exceptions, so
// don't do the work to trap them.
options.SetTimeout(std::chrono::seconds(2));
-
+ options.SetIsForUtilityExpr(true);
+
Value return_value;
// Fetch the clang types we will need:
ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext();
@@ -1281,8 +1281,7 @@ uint32_t PlatformPOSIX::DoLoadImage(lldb_private::Process *process,
std::string name_string;
process->ReadCStringFromMemory(buffer_addr, name_string, utility_error);
if (utility_error.Success())
- loaded_image->SetFile(name_string, false,
- llvm::sys::path::Style::posix);
+ loaded_image->SetFile(name_string, llvm::sys::path::Style::posix);
}
return process->AddImageToken(token);
}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index cc6f7299c194..97333ef1eb7c 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -10,13 +10,9 @@
#ifndef liblldb_PlatformPOSIX_h_
#define liblldb_PlatformPOSIX_h_
-// C Includes
-// C++ Includes
#include <map>
#include <memory>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/Options.h"
#include "lldb/Target/Platform.h"
diff --git a/source/Plugins/Platform/Windows/PlatformWindows.cpp b/source/Plugins/Platform/Windows/PlatformWindows.cpp
index 45e906f88e00..685d49a73a77 100644
--- a/source/Plugins/Platform/Windows/PlatformWindows.cpp
+++ b/source/Plugins/Platform/Windows/PlatformWindows.cpp
@@ -9,16 +9,12 @@
#include "PlatformWindows.h"
-// C Includes
#include <stdio.h>
#if defined(_WIN32)
#include "lldb/Host/windows/windows.h"
#include <winsock2.h>
#endif
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
#include "lldb/Core/Debugger.h"
@@ -71,7 +67,7 @@ PlatformSP PlatformWindows::CreateInstance(bool force,
const bool is_host = false;
bool create = force;
- if (create == false && arch && arch->IsValid()) {
+ if (!create && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getVendor()) {
case llvm::Triple::PC:
@@ -192,16 +188,18 @@ Status PlatformWindows::ResolveExecutable(
if (IsHost()) {
// if we cant resolve the executable loation based on the current path
// variables
- if (!resolved_module_spec.GetFileSpec().Exists()) {
+ if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
- resolved_module_spec.GetFileSpec().SetFile(exe_path, true,
+ resolved_module_spec.GetFileSpec().SetFile(exe_path,
FileSpec::Style::native);
+ FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec());
}
- if (!resolved_module_spec.GetFileSpec().Exists())
- resolved_module_spec.GetFileSpec().ResolveExecutableLocation();
+ if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
+ FileSystem::Instance().ResolveExecutableLocation(
+ resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists())
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
error.Clear();
else {
ms.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
@@ -215,7 +213,7 @@ Status PlatformWindows::ResolveExecutable(
} else {
// We may connect to a process and use the provided executable (Don't use
// local $PATH).
- if (resolved_module_spec.GetFileSpec().Exists())
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
error.Clear();
else
error.SetErrorStringWithFormat("the platform is not currently "
@@ -262,7 +260,8 @@ Status PlatformWindows::ResolveExecutable(
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(
+ resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -438,9 +437,8 @@ ProcessSP PlatformWindows::DebugProcess(ProcessLaunchInfo &launch_info,
ProcessAttachInfo attach_info(launch_info);
return Attach(attach_info, debugger, target, error);
} else {
- ProcessSP process_sp =
- target->CreateProcess(launch_info.GetListenerForProcess(debugger),
- launch_info.GetProcessPluginName(), nullptr);
+ ProcessSP process_sp = target->CreateProcess(
+ launch_info.GetListener(), launch_info.GetProcessPluginName(), nullptr);
// We need to launch and attach to the process.
launch_info.GetFlags().Set(eLaunchFlagDebug);
@@ -470,8 +468,8 @@ lldb::ProcessSP PlatformWindows::Attach(ProcessAttachInfo &attach_info,
FileSpec emptyFileSpec;
ArchSpec emptyArchSpec;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- nullptr, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", "", eLoadDependentsNo, nullptr, new_target_sp);
target = new_target_sp.get();
}
diff --git a/source/Plugins/Platform/Windows/PlatformWindows.h b/source/Plugins/Platform/Windows/PlatformWindows.h
index 3a15271c5762..f7f55049e4e7 100644
--- a/source/Plugins/Platform/Windows/PlatformWindows.h
+++ b/source/Plugins/Platform/Windows/PlatformWindows.h
@@ -10,10 +10,6 @@
#ifndef liblldb_PlatformWindows_h_
#define liblldb_PlatformWindows_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Platform.h"
namespace lldb_private {
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 348bb825a5c5..f6ace706ca3f 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -10,9 +10,6 @@
#include "PlatformRemoteGDBServer.h"
#include "lldb/Host/Config.h"
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -43,7 +40,7 @@ static bool g_initialized = false;
void PlatformRemoteGDBServer::Initialize() {
Platform::Initialize();
- if (g_initialized == false) {
+ if (!g_initialized) {
g_initialized = true;
PluginManager::RegisterPlugin(
PlatformRemoteGDBServer::GetPluginNameStatic(),
@@ -107,7 +104,7 @@ Status PlatformRemoteGDBServer::ResolveExecutable(
// Resolve any executable within an apk on Android?
// Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
- if (resolved_module_spec.GetFileSpec().Exists() ||
+ if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) ||
module_spec.GetUUID().IsValid()) {
if (resolved_module_spec.GetArchitecture().IsValid() ||
resolved_module_spec.GetUUID().IsValid()) {
@@ -142,7 +139,7 @@ Status PlatformRemoteGDBServer::ResolveExecutable(
}
if (error.Fail() || !exe_module_sp) {
- if (resolved_module_spec.GetFileSpec().Readable()) {
+ if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
error.SetErrorStringWithFormat(
"'%s' doesn't contain any '%s' platform architectures: %s",
resolved_module_spec.GetFileSpec().GetPath().c_str(),
@@ -488,8 +485,8 @@ lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess(
if (target == NULL) {
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- NULL, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", "", eLoadDependentsNo, NULL, new_target_sp);
target = new_target_sp.get();
} else
error.Clear();
@@ -499,8 +496,8 @@ lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess(
// The darwin always currently uses the GDB remote debugger plug-in
// so even when debugging locally we are debugging remotely!
- process_sp = target->CreateProcess(
- launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
+ process_sp = target->CreateProcess(launch_info.GetListener(),
+ "gdb-remote", NULL);
if (process_sp) {
error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
@@ -574,8 +571,8 @@ lldb::ProcessSP PlatformRemoteGDBServer::Attach(
if (target == NULL) {
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- NULL, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", "", eLoadDependentsNo, NULL, new_target_sp);
target = new_target_sp.get();
} else
error.Clear();
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index a31933b5d9b0..7abb33423bc1 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -11,12 +11,8 @@
#ifndef liblldb_PlatformRemoteGDBServer_h_
#define liblldb_PlatformRemoteGDBServer_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "lldb/Target/Platform.h"
diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
index 3505443abcb0..70d9a5248fd9 100644
--- a/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
+++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
@@ -19,10 +19,10 @@
// C++ includes
// LLDB includes
-#include "lldb/Core/State.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "CFBundle.h"
@@ -63,12 +63,13 @@ Status NativeProcessProtocol::Launch(
// Verify the working directory is valid if one was specified.
FileSpec working_dir(launch_info.GetWorkingDirectory());
- if (working_dir &&
- (!working_dir.ResolvePath() ||
- !llvm::sys::fs::is_directory(working_dir.GetPath())) {
- error.SetErrorStringWithFormat("No such file or directory: %s",
+ if (working_dir) {
+ FileInstance::Instance().Resolve(working_dir);
+ if (!FileSystem::Instance().IsDirectory(working_dir)) {
+ error.SetErrorStringWithFormat("No such file or directory: %s",
working_dir.GetCString());
- return error;
+ return error;
+ }
}
// Launch the inferior.
diff --git a/source/Plugins/Process/Darwin/NativeProcessDarwin.h b/source/Plugins/Process/Darwin/NativeProcessDarwin.h
index 0b186fd7d80c..9abdd5360eba 100644
--- a/source/Plugins/Process/Darwin/NativeProcessDarwin.h
+++ b/source/Plugins/Process/Darwin/NativeProcessDarwin.h
@@ -21,7 +21,6 @@
#include <mutex>
#include <unordered_set>
-// Other libraries and framework includes
#include "lldb/Host/Debug.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/Pipe.h"
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
index 3576a7f26f86..fce0be22678e 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#include <pthread.h>
#include <pthread_np.h>
@@ -16,12 +15,9 @@
#include <sys/types.h>
#include <sys/user.h>
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/State.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/State.h"
-// Project includes
#include "FreeBSDThread.h"
#include "POSIXStopInfo.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
@@ -42,7 +38,6 @@
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostNativeThread.h"
@@ -50,6 +45,7 @@
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/State.h"
#include "llvm/ADT/SmallString.h"
using namespace lldb;
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
index c93cc4fbfd73..a8559fe8b2ca 100644
--- a/source/Plugins/Process/FreeBSD/FreeBSDThread.h
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -10,11 +10,9 @@
#ifndef liblldb_FreeBSDThread_H_
#define liblldb_FreeBSDThread_H_
-// C++ Includes
#include <memory>
#include <string>
-// Other libraries and framework includes
#include "RegisterContextPOSIX.h"
#include "lldb/Target/Thread.h"
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index fa0bcea8f6bd..a13d4bcc4ecb 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -8,7 +8,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#include <pthread.h>
#include <pthread_np.h>
@@ -18,18 +17,17 @@
#include <sys/user.h>
#include <machine/elf.h>
-// C++ Includes
#include <mutex>
#include <unordered_map>
-// Other libraries and framework includes
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/State.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/State.h"
#include "FreeBSDThread.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
@@ -38,13 +36,11 @@
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
-// Other libraries and framework includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
@@ -52,6 +48,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/State.h"
#include "lldb/Host/posix/Fcntl.h"
@@ -287,7 +284,7 @@ bool ProcessFreeBSD::CanDebug(lldb::TargetSP target_sp,
// For now we are just making sure the file exists for a given module
ModuleSP exe_module_sp(target_sp->GetExecutableModule());
if (exe_module_sp.get())
- return exe_module_sp->GetFileSpec().Exists();
+ return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
// If there is no executable module, we return true since we might be
// preparing to attach.
return true;
@@ -335,7 +332,7 @@ ProcessFreeBSD::DoAttachToProcessWithID(lldb::pid_t pid,
GetTarget().SetArchitecture(module_arch);
// Initialize the target module list
- GetTarget().SetExecutableModule(exe_module_sp, true);
+ GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsYes);
SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
@@ -373,12 +370,13 @@ Status ProcessFreeBSD::DoLaunch(Module *module,
assert(m_monitor == NULL);
FileSpec working_dir = launch_info.GetWorkingDirectory();
- namespace fs = llvm::sys::fs;
- if (working_dir && (!working_dir.ResolvePath() ||
- !fs::is_directory(working_dir.GetPath()))) {
- error.SetErrorStringWithFormat("No such file or directory: %s",
+ if (working_dir) {
+ FileSystem::Instance().Resolve(working_dir);
+ if (!FileSystem::Instance().IsDirectory(working_dir.GetPath())) {
+ error.SetErrorStringWithFormat("No such file or directory: %s",
working_dir.GetCString());
- return error;
+ return error;
+ }
}
SetPrivateState(eStateLaunching);
@@ -390,8 +388,7 @@ Status ProcessFreeBSD::DoLaunch(Module *module,
FileSpec stdout_file_spec{};
FileSpec stderr_file_spec{};
- const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL, 0),
- false};
+ const FileSpec dbg_pts_file_spec{launch_info.GetPTY().GetSlaveName(NULL, 0)};
file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
stdin_file_spec =
@@ -519,7 +516,7 @@ void ProcessFreeBSD::DoDidExec() {
executable_search_paths.GetSize() ? &executable_search_paths : NULL);
if (!error.Success())
return;
- target->SetExecutableModule(exe_module_sp, true);
+ target->SetExecutableModule(exe_module_sp, eLoadDependentsYes);
}
}
}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index 51fdf2e5ef33..617ae3030f10 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#include <poll.h>
#include <signal.h>
@@ -19,16 +18,14 @@
#include <sys/wait.h>
#include <unistd.h>
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "llvm/Support/Errno.h"
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 1d3e2d746fa9..ca7c4e03966c 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -10,14 +10,11 @@
#ifndef liblldb_ProcessMonitor_H_
#define liblldb_ProcessMonitor_H_
-// C Includes
#include <semaphore.h>
#include <signal.h>
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "lldb/Host/HostThread.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-types.h"
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
index b1b44e71de46..32973abd9207 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIX.h
@@ -10,9 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_H_
#define liblldb_RegisterContextPOSIX_H_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "Plugins/Process/Utility/RegisterInfoInterface.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/ArchSpec.h"
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
index 8ddc253aea5d..0642a30ade70 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm.cpp
@@ -7,9 +7,9 @@
//
//===---------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
index 93ffeb5ea79b..b35ee18d6a96 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_arm64.cpp
@@ -7,9 +7,9 @@
//
//===---------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
#include "ProcessFreeBSD.h"
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
index 734167e1fc98..17df44cf85ee 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_mips64.cpp
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
#include "ProcessFreeBSD.h"
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
index 5cc6cd290629..a8d75963ea6b 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
diff --git a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
index 7db7f803b371..68fd5ac13bb0 100644
--- a/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
+++ b/source/Plugins/Process/FreeBSD/RegisterContextPOSIXProcessMonitor_x86.cpp
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "Plugins/Process/FreeBSD/ProcessFreeBSD.h"
#include "Plugins/Process/FreeBSD/ProcessMonitor.h"
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 3fb886e1c7a3..8c6c95380e81 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -9,29 +9,23 @@
#include "NativeProcessLinux.h"
-// C Includes
#include <errno.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
-// C++ Includes
#include <fstream>
#include <mutex>
#include <sstream>
#include <string>
#include <unordered_map>
-// Other libraries and framework includes
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Host/common/NativeBreakpoint.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Host/linux/Uio.h"
@@ -41,6 +35,8 @@
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StringExtractor.h"
#include "llvm/Support/Errno.h"
@@ -49,6 +45,7 @@
#include "NativeThreadLinux.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/LinuxProcMaps.h"
#include "Procfs.h"
#include <linux/unistd.h>
@@ -759,9 +756,7 @@ void NativeProcessLinux::MonitorBreakpoint(NativeThreadLinux &thread) {
// Mark the thread as stopped at breakpoint.
thread.SetStoppedByBreakpoint();
- Status error = FixupBreakpointPCAsNeeded(thread);
- if (error.Fail())
- LLDB_LOG(log, "pid = {0} fixup: {1}", thread.GetID(), error);
+ FixupBreakpointPCAsNeeded(thread);
if (m_threads_stepping_with_breakpoint.find(thread.GetID()) !=
m_threads_stepping_with_breakpoint.end())
@@ -1238,90 +1233,6 @@ Status NativeProcessLinux::Kill() {
return error;
}
-static Status
-ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef &maps_line,
- MemoryRegionInfo &memory_region_info) {
- memory_region_info.Clear();
-
- StringExtractor line_extractor(maps_line);
-
- // Format: {address_start_hex}-{address_end_hex} perms offset dev inode
- // pathname perms: rwxp (letter is present if set, '-' if not, final
- // character is p=private, s=shared).
-
- // Parse out the starting address
- lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
-
- // Parse out hyphen separating start and end address from range.
- if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-'))
- return Status(
- "malformed /proc/{pid}/maps entry, missing dash between address range");
-
- // Parse out the ending address
- lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address);
-
- // Parse out the space after the address.
- if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' '))
- return Status(
- "malformed /proc/{pid}/maps entry, missing space after range");
-
- // Save the range.
- memory_region_info.GetRange().SetRangeBase(start_address);
- memory_region_info.GetRange().SetRangeEnd(end_address);
-
- // Any memory region in /proc/{pid}/maps is by definition mapped into the
- // process.
- memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
-
- // Parse out each permission entry.
- if (line_extractor.GetBytesLeft() < 4)
- return Status("malformed /proc/{pid}/maps entry, missing some portion of "
- "permissions");
-
- // Handle read permission.
- const char read_perm_char = line_extractor.GetChar();
- if (read_perm_char == 'r')
- memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
- else if (read_perm_char == '-')
- memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
- else
- return Status("unexpected /proc/{pid}/maps read permission char");
-
- // Handle write permission.
- const char write_perm_char = line_extractor.GetChar();
- if (write_perm_char == 'w')
- memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
- else if (write_perm_char == '-')
- memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
- else
- return Status("unexpected /proc/{pid}/maps write permission char");
-
- // Handle execute permission.
- const char exec_perm_char = line_extractor.GetChar();
- if (exec_perm_char == 'x')
- memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
- else if (exec_perm_char == '-')
- memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
- else
- return Status("unexpected /proc/{pid}/maps exec permission char");
-
- line_extractor.GetChar(); // Read the private bit
- line_extractor.SkipSpaces(); // Skip the separator
- line_extractor.GetHexMaxU64(false, 0); // Read the offset
- line_extractor.GetHexMaxU64(false, 0); // Read the major device number
- line_extractor.GetChar(); // Read the device id separator
- line_extractor.GetHexMaxU64(false, 0); // Read the major device number
- line_extractor.SkipSpaces(); // Skip the separator
- line_extractor.GetU64(0, 10); // Read the inode number
-
- line_extractor.SkipSpaces();
- const char *name = line_extractor.Peek();
- if (name)
- memory_region_info.SetName(name);
-
- return Status();
-}
-
Status NativeProcessLinux::GetMemoryRegionInfo(lldb::addr_t load_addr,
MemoryRegionInfo &range_info) {
// FIXME review that the final memory region returned extends to the end of
@@ -1407,22 +1318,23 @@ Status NativeProcessLinux::PopulateMemoryRegionCache() {
m_supports_mem_region = LazyBool::eLazyBoolNo;
return BufferOrError.getError();
}
- StringRef Rest = BufferOrError.get()->getBuffer();
- while (! Rest.empty()) {
- StringRef Line;
- std::tie(Line, Rest) = Rest.split('\n');
- MemoryRegionInfo info;
- const Status parse_error =
- ParseMemoryRegionInfoFromProcMapsLine(Line, info);
- if (parse_error.Fail()) {
- LLDB_LOG(log, "failed to parse proc maps line '{0}': {1}", Line,
- parse_error);
- m_supports_mem_region = LazyBool::eLazyBoolNo;
- return parse_error;
- }
- m_mem_region_cache.emplace_back(
- info, FileSpec(info.GetName().GetCString(), true));
- }
+ Status Result;
+ ParseLinuxMapRegions(BufferOrError.get()->getBuffer(),
+ [&](const MemoryRegionInfo &Info, const Status &ST) {
+ if (ST.Success()) {
+ FileSpec file_spec(Info.GetName().GetCString());
+ FileSystem::Instance().Resolve(file_spec);
+ m_mem_region_cache.emplace_back(Info, file_spec);
+ return true;
+ } else {
+ m_supports_mem_region = LazyBool::eLazyBoolNo;
+ LLDB_LOG(log, "failed to parse proc maps: {0}", ST);
+ Result = ST;
+ return false;
+ }
+ });
+ if (Result.Fail())
+ return Result;
if (m_mem_region_cache.empty()) {
// No entries after attempting to read them. This shouldn't happen if
@@ -1502,40 +1414,6 @@ size_t NativeProcessLinux::UpdateThreads() {
return m_threads.size();
}
-Status NativeProcessLinux::GetSoftwareBreakpointPCOffset(
- uint32_t &actual_opcode_size) {
- // FIXME put this behind a breakpoint protocol class that can be
- // set per architecture. Need ARM, MIPS support here.
- static const uint8_t g_i386_opcode[] = {0xCC};
- static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
-
- switch (m_arch.GetMachine()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode));
- return Status();
-
- case llvm::Triple::systemz:
- actual_opcode_size = static_cast<uint32_t>(sizeof(g_s390x_opcode));
- return Status();
-
- case llvm::Triple::arm:
- case llvm::Triple::aarch64:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::ppc64le:
- // On these architectures the PC don't get updated for breakpoint hits
- actual_opcode_size = 0;
- return Status();
-
- default:
- assert(false && "CPU type not supported!");
- return Status("CPU type not supported");
- }
-}
-
Status NativeProcessLinux::SetBreakpoint(lldb::addr_t addr, uint32_t size,
bool hardware) {
if (hardware)
@@ -1551,74 +1429,26 @@ Status NativeProcessLinux::RemoveBreakpoint(lldb::addr_t addr, bool hardware) {
return NativeProcessProtocol::RemoveBreakpoint(addr);
}
-Status NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(
- size_t trap_opcode_size_hint, size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes) {
- // FIXME put this behind a breakpoint protocol class that can be set per
- // architecture. Need MIPS support here.
- static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};
+llvm::Expected<llvm::ArrayRef<uint8_t>>
+NativeProcessLinux::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
// The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
// linux kernel does otherwise.
- static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
- static const uint8_t g_i386_opcode[] = {0xCC};
- static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d};
- static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00};
- static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
- static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};
- static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
-
- switch (m_arch.GetMachine()) {
- case llvm::Triple::aarch64:
- trap_opcode_bytes = g_aarch64_opcode;
- actual_opcode_size = sizeof(g_aarch64_opcode);
- return Status();
+ static const uint8_t g_arm_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};
+ static const uint8_t g_thumb_opcode[] = {0x01, 0xde};
+ switch (GetArchitecture().GetMachine()) {
case llvm::Triple::arm:
- switch (trap_opcode_size_hint) {
+ switch (size_hint) {
case 2:
- trap_opcode_bytes = g_thumb_breakpoint_opcode;
- actual_opcode_size = sizeof(g_thumb_breakpoint_opcode);
- return Status();
+ return llvm::makeArrayRef(g_thumb_opcode);
case 4:
- trap_opcode_bytes = g_arm_breakpoint_opcode;
- actual_opcode_size = sizeof(g_arm_breakpoint_opcode);
- return Status();
+ return llvm::makeArrayRef(g_arm_opcode);
default:
- assert(false && "Unrecognised trap opcode size hint!");
- return Status("Unrecognised trap opcode size hint!");
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Unrecognised trap opcode size hint!");
}
-
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- trap_opcode_bytes = g_i386_opcode;
- actual_opcode_size = sizeof(g_i386_opcode);
- return Status();
-
- case llvm::Triple::mips:
- case llvm::Triple::mips64:
- trap_opcode_bytes = g_mips64_opcode;
- actual_opcode_size = sizeof(g_mips64_opcode);
- return Status();
-
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64el:
- trap_opcode_bytes = g_mips64el_opcode;
- actual_opcode_size = sizeof(g_mips64el_opcode);
- return Status();
-
- case llvm::Triple::systemz:
- trap_opcode_bytes = g_s390x_opcode;
- actual_opcode_size = sizeof(g_s390x_opcode);
- return Status();
-
- case llvm::Triple::ppc64le:
- trap_opcode_bytes = g_ppc64le_opcode;
- actual_opcode_size = sizeof(g_ppc64le_opcode);
- return Status();
-
default:
- assert(false && "CPU type not supported!");
- return Status("CPU type not supported");
+ return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint);
}
}
@@ -1677,15 +1507,6 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
return Status();
}
-Status NativeProcessLinux::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
- size_t size,
- size_t &bytes_read) {
- Status error = ReadMemory(addr, buf, size, bytes_read);
- if (error.Fail())
- return error;
- return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
-}
-
Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
size_t size, size_t &bytes_written) {
const unsigned char *src = static_cast<const unsigned char *>(buf);
@@ -1810,90 +1631,14 @@ NativeThreadLinux &NativeProcessLinux::AddThread(lldb::tid_t thread_id) {
return static_cast<NativeThreadLinux &>(*m_threads.back());
}
-Status
-NativeProcessLinux::FixupBreakpointPCAsNeeded(NativeThreadLinux &thread) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
-
- Status error;
-
- // Find out the size of a breakpoint (might depend on where we are in the
- // code).
- NativeRegisterContext &context = thread.GetRegisterContext();
-
- uint32_t breakpoint_size = 0;
- error = GetSoftwareBreakpointPCOffset(breakpoint_size);
- if (error.Fail()) {
- LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error);
- return error;
- } else
- LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
-
- // First try probing for a breakpoint at a software breakpoint location: PC -
- // breakpoint size.
- const lldb::addr_t initial_pc_addr = context.GetPCfromBreakpointLocation();
- lldb::addr_t breakpoint_addr = initial_pc_addr;
- if (breakpoint_size > 0) {
- // Do not allow breakpoint probe to wrap around.
- if (breakpoint_addr >= breakpoint_size)
- breakpoint_addr -= breakpoint_size;
- }
-
- // Check if we stopped because of a breakpoint.
- NativeBreakpointSP breakpoint_sp;
- error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp);
- if (!error.Success() || !breakpoint_sp) {
- // We didn't find one at a software probe location. Nothing to do.
- LLDB_LOG(log,
- "pid {0} no lldb breakpoint found at current pc with "
- "adjustment: {1}",
- GetID(), breakpoint_addr);
- return Status();
- }
-
- // If the breakpoint is not a software breakpoint, nothing to do.
- if (!breakpoint_sp->IsSoftwareBreakpoint()) {
- LLDB_LOG(
- log,
- "pid {0} breakpoint found at {1:x}, not software, nothing to adjust",
- GetID(), breakpoint_addr);
- return Status();
- }
-
- //
- // We have a software breakpoint and need to adjust the PC.
- //
-
- // Sanity check.
- if (breakpoint_size == 0) {
- // Nothing to do! How did we get here?
- LLDB_LOG(log,
- "pid {0} breakpoint found at {1:x}, it is software, but the "
- "size is zero, nothing to do (unexpected)",
- GetID(), breakpoint_addr);
- return Status();
- }
-
- // Change the program counter.
- LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(),
- thread.GetID(), initial_pc_addr, breakpoint_addr);
-
- error = context.SetPC(breakpoint_addr);
- if (error.Fail()) {
- LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(),
- thread.GetID(), error);
- return error;
- }
-
- return error;
-}
-
Status NativeProcessLinux::GetLoadedModuleFileSpec(const char *module_path,
FileSpec &file_spec) {
Status error = PopulateMemoryRegionCache();
if (error.Fail())
return error;
- FileSpec module_file_spec(module_path, true);
+ FileSpec module_file_spec(module_path);
+ FileSystem::Instance().Resolve(module_file_spec);
file_spec.Clear();
for (const auto &it : m_mem_region_cache) {
@@ -1913,7 +1658,7 @@ Status NativeProcessLinux::GetFileLoadAddress(const llvm::StringRef &file_name,
if (error.Fail())
return error;
- FileSpec file(file_name, false);
+ FileSpec file(file_name);
for (const auto &it : m_mem_region_cache) {
if (it.second == file) {
load_addr = it.first.GetRange().GetRangeBase();
diff --git a/source/Plugins/Process/Linux/NativeProcessLinux.h b/source/Plugins/Process/Linux/NativeProcessLinux.h
index 1c2f786e8d69..69f2b528d330 100644
--- a/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -71,9 +71,6 @@ public:
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size,
size_t &bytes_read) override;
- Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
- size_t &bytes_read) override;
-
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
size_t &bytes_written) override;
@@ -134,13 +131,8 @@ public:
bool SupportHardwareSingleStepping() const;
protected:
- // ---------------------------------------------------------------------
- // NativeProcessProtocol protected interface
- // ---------------------------------------------------------------------
- Status
- GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes) override;
+ llvm::Expected<llvm::ArrayRef<uint8_t>>
+ GetSoftwareBreakpointTrapOpcode(size_t size_hint) override;
private:
MainLoop::SignalHandleUP m_sigchld_handle;
@@ -190,10 +182,6 @@ private:
NativeThreadLinux &AddThread(lldb::tid_t thread_id);
- Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size);
-
- Status FixupBreakpointPCAsNeeded(NativeThreadLinux &thread);
-
/// Writes a siginfo_t structure corresponding to the given thread ID to the
/// memory region pointed to by @p siginfo.
Status GetSignalInfo(lldb::tid_t tid, void *siginfo);
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
index c8a8355f9cb9..79f635c88985 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux.cpp
@@ -9,10 +9,10 @@
#include "NativeRegisterContextLinux.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
#include "lldb/Host/linux/Ptrace.h"
+#include "lldb/Utility/RegisterValue.h"
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 749291684620..09d3a12942f0 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -15,9 +15,9 @@
#include "Plugins/Process/Linux/Procfs.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include <elf.h>
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 41fe446f728c..9a392edbe9ef 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -12,14 +12,11 @@
#include "NativeRegisterContextLinux_arm.h"
#include "NativeRegisterContextLinux_arm64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Linux/NativeProcessLinux.h"
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index 69194b3c0663..d641056a0440 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -11,22 +11,19 @@
#include "NativeRegisterContextLinux_mips64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/Linux/Procfs.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private-enumerations.h"
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
index 6aa4af64ab51..da51fda1c80b 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_ppc64le.cpp
@@ -14,10 +14,10 @@
#include "NativeRegisterContextLinux_ppc64le.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Linux/NativeProcessLinux.h"
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
index 36da2b001054..1bc916b69bcd 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
@@ -11,10 +11,10 @@
#include "NativeRegisterContextLinux_s390x.h"
#include "Plugins/Process/Linux/NativeProcessLinux.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
index 87f4b8da053e..50bf29b094df 100755
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp
@@ -11,10 +11,10 @@
#include "NativeRegisterContextLinux_x86_64.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
diff --git a/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index 4ab2a9ae6245..b64689c9d17b 100644
--- a/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -16,12 +16,12 @@
#include "NativeRegisterContextLinux.h"
#include "SingleStepCheck.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostNativeThread.h"
#include "lldb/Host/linux/Ptrace.h"
#include "lldb/Host/linux/Support.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/lldb-enumerations.h"
#include "llvm/ADT/SmallString.h"
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
index 116155d9a232..8908108eff4b 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.cpp
@@ -9,25 +9,21 @@
#include "CommunicationKDP.h"
-// C Includes
#include <errno.h>
#include <limits.h>
#include <string.h>
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/UUID.h"
-// Project includes
#include "ProcessKDPLog.h"
using namespace lldb;
@@ -467,19 +463,13 @@ lldb_private::UUID CommunicationKDP::GetUUID() {
bool CommunicationKDP::RemoteIsEFI() {
if (GetKernelVersion() == NULL)
return false;
- if (strncmp(m_kernel_version.c_str(), "EFI", 3) == 0)
- return true;
- else
- return false;
+ return strncmp(m_kernel_version.c_str(), "EFI", 3) == 0;
}
bool CommunicationKDP::RemoteIsDarwinKernel() {
if (GetKernelVersion() == NULL)
return false;
- if (m_kernel_version.find("Darwin Kernel") != std::string::npos)
- return true;
- else
- return false;
+ return m_kernel_version.find("Darwin Kernel") != std::string::npos;
}
lldb::addr_t CommunicationKDP::GetLoadAddress() {
@@ -1262,9 +1252,7 @@ bool CommunicationKDP::SendRequestResume() {
request_packet.PutHex32(GetCPUMask());
DataExtractor reply_packet;
- if (SendRequestAndGetReply(command, request_packet, reply_packet))
- return true;
- return false;
+ return SendRequestAndGetReply(command, request_packet, reply_packet);
}
bool CommunicationKDP::SendRequestBreakpoint(bool set, addr_t addr) {
@@ -1297,7 +1285,5 @@ bool CommunicationKDP::SendRequestSuspend() {
const uint32_t command_length = 8;
MakeRequestPacketHeader(command, request_packet, command_length);
DataExtractor reply_packet;
- if (SendRequestAndGetReply(command, request_packet, reply_packet))
- return true;
- return false;
+ return SendRequestAndGetReply(command, request_packet, reply_packet);
}
diff --git a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
index afac6601a56b..64bfe5514735 100644
--- a/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/CommunicationKDP.h
@@ -10,18 +10,14 @@
#ifndef liblldb_CommunicationKDP_h_
#define liblldb_CommunicationKDP_h_
-// C Includes
-// C++ Includes
#include <list>
#include <mutex>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Communication.h"
-#include "lldb/Core/Listener.h"
#include "lldb/Core/StreamBuffer.h"
-#include "lldb/Host/Predicate.h"
+#include "lldb/Utility/Listener.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/lldb-private.h"
class CommunicationKDP : public lldb_private::Communication {
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 2e707ab2e363..c1c3678617c0 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -7,20 +7,15 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#include <stdlib.h>
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
-#include "lldb/Utility/UUID.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/Symbols.h"
@@ -37,13 +32,14 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StringExtractor.h"
+#include "lldb/Utility/UUID.h"
#include "llvm/Support/Threading.h"
#define USEC_PER_SEC 1000000
-// Project includes
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
#include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
#include "ProcessKDP.h"
@@ -55,10 +51,9 @@ using namespace lldb_private;
namespace {
-static PropertyDefinition g_properties[] = {
- {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, NULL,
- "Specify the default packet timeout in seconds."},
- {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
+static constexpr PropertyDefinition g_properties[] = {
+ {"packet-timeout", OptionValue::eTypeUInt64, true, 5, NULL, {},
+ "Specify the default packet timeout in seconds."}};
enum { ePropertyPacketTimeout };
@@ -301,7 +296,8 @@ Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) {
if (module_spec.GetSymbolFileSpec()) {
ModuleSpec executable_module_spec =
Symbols::LocateExecutableObjectFile(module_spec);
- if (executable_module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(
+ executable_module_spec.GetFileSpec())) {
module_spec.GetFileSpec() =
executable_module_spec.GetFileSpec();
}
@@ -310,7 +306,7 @@ Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) {
!module_spec.GetSymbolFileSpec())
Symbols::DownloadObjectAndSymbolFile(module_spec, true);
- if (module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
ModuleSP module_sp(new Module(module_spec));
if (module_sp.get() && module_sp->GetObjectFile()) {
// Get the current target executable
@@ -319,7 +315,7 @@ Status ProcessKDP::DoConnectRemote(Stream *strm, llvm::StringRef remote_url) {
// Make sure you don't already have the right module loaded
// and they will be uniqued
if (exe_module_sp.get() != module_sp.get())
- target.SetExecutableModule(module_sp, false);
+ target.SetExecutableModule(module_sp, eLoadDependentsNo);
}
}
}
diff --git a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
index b4eae58af83c..f9102442de93 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
+++ b/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.h
@@ -10,19 +10,16 @@
#ifndef liblldb_ProcessKDP_h_
#define liblldb_ProcessKDP_h_
-// C Includes
-// C++ Includes
#include <list>
#include <vector>
-// Other libraries and framework includes
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
index 159a046b617d..0f9e62ce355a 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.cpp
@@ -9,10 +9,6 @@
#include "RegisterContextKDP_arm.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "ProcessKDP.h"
#include "ThreadKDP.h"
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h
index fe02b0648221..1532f23207f4 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm.h
@@ -10,11 +10,7 @@
#ifndef liblldb_RegisterContextKDP_arm_h_
#define liblldb_RegisterContextKDP_arm_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
class ThreadKDP;
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp
index 44534a252568..e13a7f3ad907 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.cpp
@@ -10,10 +10,6 @@
#include "RegisterContextKDP_arm64.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "ProcessKDP.h"
#include "ThreadKDP.h"
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h
index 0922654de2cc..be4038ba96ea 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_arm64.h
@@ -11,11 +11,7 @@
#ifndef liblldb_RegisterContextKDP_arm64_h_
#define liblldb_RegisterContextKDP_arm64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
class ThreadKDP;
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
index e48232ad8dda..096aa0f95d00 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextKDP_i386.h"
#include "ProcessKDP.h"
#include "ThreadKDP.h"
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h
index 5803670a08b4..699d5fabe157 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_i386.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextKDP_i386_h_
#define liblldb_RegisterContextKDP_i386_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
class ThreadKDP;
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
index 50e11f381925..9d85145f2eaf 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextKDP_x86_64.h"
#include "ProcessKDP.h"
#include "ThreadKDP.h"
diff --git a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h
index 7a40bb626385..9841ad77b004 100644
--- a/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h
+++ b/source/Plugins/Process/MacOSX-Kernel/RegisterContextKDP_x86_64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextKDP_x86_64_h_
#define liblldb_RegisterContextKDP_x86_64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
class ThreadKDP;
diff --git a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
index 7fca0fc24fdb..6f26acd0b8aa 100644
--- a/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
+++ b/source/Plugins/Process/MacOSX-Kernel/ThreadKDP.cpp
@@ -9,10 +9,9 @@
#include "ThreadKDP.h"
-#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
@@ -20,6 +19,7 @@
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
diff --git a/source/Plugins/Process/NetBSD/CMakeLists.txt b/source/Plugins/Process/NetBSD/CMakeLists.txt
index 92a6014ced07..e131e6d70468 100644
--- a/source/Plugins/Process/NetBSD/CMakeLists.txt
+++ b/source/Plugins/Process/NetBSD/CMakeLists.txt
@@ -5,7 +5,6 @@ add_lldb_library(lldbPluginProcessNetBSD PLUGIN
NativeThreadNetBSD.cpp
LINK_LIBS
- lldbCore
lldbHost
lldbSymbol
lldbTarget
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
index 1a4cb21d000e..a1b7d7df4553 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp
@@ -9,18 +9,14 @@
#include "NativeProcessNetBSD.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostProcess.h"
-#include "lldb/Host/common/NativeBreakpoint.h"
#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/posix/ProcessLauncherPosixFork.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/State.h"
#include "llvm/Support/Errno.h"
// System includes - They have to be included after framework includes because
@@ -322,100 +318,6 @@ Status NativeProcessNetBSD::PtraceWrapper(int req, lldb::pid_t pid, void *addr,
return error;
}
-Status NativeProcessNetBSD::GetSoftwareBreakpointPCOffset(
- uint32_t &actual_opcode_size) {
- // FIXME put this behind a breakpoint protocol class that can be
- // set per architecture. Need ARM, MIPS support here.
- static const uint8_t g_i386_opcode[] = {0xCC};
- switch (m_arch.GetMachine()) {
- case llvm::Triple::x86_64:
- actual_opcode_size = static_cast<uint32_t>(sizeof(g_i386_opcode));
- return Status();
- default:
- assert(false && "CPU type not supported!");
- return Status("CPU type not supported");
- }
-}
-
-Status
-NativeProcessNetBSD::FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread) {
- Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_BREAKPOINTS));
- Status error;
- // Find out the size of a breakpoint (might depend on where we are in the
- // code).
- NativeRegisterContext& context = thread.GetRegisterContext();
- uint32_t breakpoint_size = 0;
- error = GetSoftwareBreakpointPCOffset(breakpoint_size);
- if (error.Fail()) {
- LLDB_LOG(log, "GetBreakpointSize() failed: {0}", error);
- return error;
- } else
- LLDB_LOG(log, "breakpoint size: {0}", breakpoint_size);
- // First try probing for a breakpoint at a software breakpoint location: PC -
- // breakpoint size.
- const lldb::addr_t initial_pc_addr =
- context.GetPCfromBreakpointLocation();
- lldb::addr_t breakpoint_addr = initial_pc_addr;
- if (breakpoint_size > 0) {
- // Do not allow breakpoint probe to wrap around.
- if (breakpoint_addr >= breakpoint_size)
- breakpoint_addr -= breakpoint_size;
- }
- // Check if we stopped because of a breakpoint.
- NativeBreakpointSP breakpoint_sp;
- error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp);
- if (!error.Success() || !breakpoint_sp) {
- // We didn't find one at a software probe location. Nothing to do.
- LLDB_LOG(log,
- "pid {0} no lldb breakpoint found at current pc with "
- "adjustment: {1}",
- GetID(), breakpoint_addr);
- return Status();
- }
- // If the breakpoint is not a software breakpoint, nothing to do.
- if (!breakpoint_sp->IsSoftwareBreakpoint()) {
- LLDB_LOG(
- log,
- "pid {0} breakpoint found at {1:x}, not software, nothing to adjust",
- GetID(), breakpoint_addr);
- return Status();
- }
- //
- // We have a software breakpoint and need to adjust the PC.
- //
- // Sanity check.
- if (breakpoint_size == 0) {
- // Nothing to do! How did we get here?
- LLDB_LOG(log,
- "pid {0} breakpoint found at {1:x}, it is software, but the "
- "size is zero, nothing to do (unexpected)",
- GetID(), breakpoint_addr);
- return Status();
- }
- //
- // We have a software breakpoint and need to adjust the PC.
- //
- // Sanity check.
- if (breakpoint_size == 0) {
- // Nothing to do! How did we get here?
- LLDB_LOG(log,
- "pid {0} breakpoint found at {1:x}, it is software, but the "
- "size is zero, nothing to do (unexpected)",
- GetID(), breakpoint_addr);
- return Status();
- }
- // Change the program counter.
- LLDB_LOG(log, "pid {0} tid {1}: changing PC from {2:x} to {3:x}", GetID(),
- thread.GetID(), initial_pc_addr, breakpoint_addr);
- error = context.SetPC(breakpoint_addr);
- if (error.Fail()) {
- LLDB_LOG(log, "pid {0} tid {1}: failed to set PC: {2}", GetID(),
- thread.GetID(), error);
- return error;
- }
- return error;
-}
-
Status NativeProcessNetBSD::Resume(const ResumeActionList &resume_actions) {
Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS));
LLDB_LOG(log, "pid {0}", GetID());
@@ -637,7 +539,7 @@ Status NativeProcessNetBSD::PopulateMemoryRegionCache() {
info.SetName(vm[i].kve_path);
m_mem_region_cache.emplace_back(
- info, FileSpec(info.GetName().GetCString(), true));
+ info, FileSpec(info.GetName().GetCString()));
}
free(vm);
@@ -682,23 +584,6 @@ Status NativeProcessNetBSD::SetBreakpoint(lldb::addr_t addr, uint32_t size,
return SetSoftwareBreakpoint(addr, size);
}
-Status NativeProcessNetBSD::GetSoftwareBreakpointTrapOpcode(
- size_t trap_opcode_size_hint, size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes) {
- static const uint8_t g_i386_opcode[] = {0xCC};
-
- switch (m_arch.GetMachine()) {
- case llvm::Triple::x86:
- case llvm::Triple::x86_64:
- trap_opcode_bytes = g_i386_opcode;
- actual_opcode_size = sizeof(g_i386_opcode);
- return Status();
- default:
- assert(false && "CPU type not supported!");
- return Status("CPU type not supported");
- }
-}
-
Status NativeProcessNetBSD::GetLoadedModuleFileSpec(const char *module_path,
FileSpec &file_spec) {
return Status("Unimplemented");
@@ -824,15 +709,6 @@ Status NativeProcessNetBSD::ReadMemory(lldb::addr_t addr, void *buf,
return Status();
}
-Status NativeProcessNetBSD::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
- size_t size,
- size_t &bytes_read) {
- Status error = ReadMemory(addr, buf, size, bytes_read);
- if (error.Fail())
- return error;
- return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size);
-}
-
Status NativeProcessNetBSD::WriteMemory(lldb::addr_t addr, const void *buf,
size_t size, size_t &bytes_written) {
const unsigned char *src = static_cast<const unsigned char *>(buf);
diff --git a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
index 142f74ecf194..a3f1c4c6a06a 100644
--- a/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
+++ b/source/Plugins/Process/NetBSD/NativeProcessNetBSD.h
@@ -58,9 +58,6 @@ public:
Status ReadMemory(lldb::addr_t addr, void *buf, size_t size,
size_t &bytes_read) override;
- Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size,
- size_t &bytes_read) override;
-
Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size,
size_t &bytes_written) override;
@@ -93,16 +90,6 @@ public:
static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr,
int data = 0, int *result = nullptr);
-protected:
- // ---------------------------------------------------------------------
- // NativeProcessProtocol protected interface
- // ---------------------------------------------------------------------
-
- Status
- GetSoftwareBreakpointTrapOpcode(size_t trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t *&trap_opcode_bytes) override;
-
private:
MainLoop::SignalHandleUP m_sigchld_handle;
ArchSpec m_arch;
@@ -125,8 +112,6 @@ private:
void MonitorSIGTRAP(lldb::pid_t pid);
void MonitorSignal(lldb::pid_t pid, int signal);
- Status GetSoftwareBreakpointPCOffset(uint32_t &actual_opcode_size);
- Status FixupBreakpointPCAsNeeded(NativeThreadNetBSD &thread);
Status PopulateMemoryRegionCache();
void SigchldHandler();
diff --git a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
index 16b6f2c52dd5..78da3527122f 100644
--- a/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
+++ b/source/Plugins/Process/NetBSD/NativeRegisterContextNetBSD_x86_64.cpp
@@ -11,10 +11,10 @@
#include "NativeRegisterContextNetBSD_x86_64.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
diff --git a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
index 83f1da78d01d..6f5d1120e40d 100644
--- a/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
+++ b/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
@@ -14,9 +14,9 @@
#include "Plugins/Process/POSIX/CrashReason.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/State.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/State.h"
#include <sstream>
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
index 134013517a11..3ac798b3d4b3 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
+++ b/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
@@ -11,11 +11,7 @@
#ifndef liblldb_ProcessPOSIXLog_h_
#define liblldb_ProcessPOSIXLog_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Log.h"
#define POSIX_LOG_PROCESS (1u << 1)
diff --git a/source/Plugins/Process/Utility/ARMUtils.h b/source/Plugins/Process/Utility/ARMUtils.h
index 2bbd519b246a..2c14dc936cbc 100644
--- a/source/Plugins/Process/Utility/ARMUtils.h
+++ b/source/Plugins/Process/Utility/ARMUtils.h
@@ -12,7 +12,7 @@
#include "ARMDefines.h"
#include "InstructionUtils.h"
-#include "llvm/Support/MathExtras.h" // for SignExtend64 template function
+#include "llvm/Support/MathExtras.h"
// Common utilities for the ARM/Thumb Instruction Set Architecture.
diff --git a/source/Plugins/Process/Utility/CMakeLists.txt b/source/Plugins/Process/Utility/CMakeLists.txt
index b43756acea63..e36ce4dec98a 100644
--- a/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/source/Plugins/Process/Utility/CMakeLists.txt
@@ -5,6 +5,7 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN
HistoryThread.cpp
HistoryUnwind.cpp
InferiorCallPOSIX.cpp
+ LinuxProcMaps.cpp
LinuxSignals.cpp
MipsLinuxSignals.cpp
NativeRegisterContextRegisterInfo.cpp
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
index 5f34e9915ede..dcbf474fa55a 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -464,7 +464,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
end = m_value_regs_map.end();
pos != end; ++pos) {
if (pos->second.size() > 1) {
- std::sort(pos->second.begin(), pos->second.end());
+ llvm::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())
@@ -514,7 +514,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) {
end = m_invalidate_regs_map.end();
pos != end; ++pos) {
if (pos->second.size() > 1) {
- std::sort(pos->second.begin(), pos->second.end());
+ llvm::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())
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
index acb3e3eb8a84..68f3902e0c96 100644
--- a/source/Plugins/Process/Utility/DynamicRegisterInfo.h
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -10,13 +10,9 @@
#ifndef lldb_DynamicRegisterInfo_h_
#define lldb_DynamicRegisterInfo_h_
-// C Includes
-// C++ Includes
#include <map>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.cpp b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
index f695a11c9759..0b56b6093559 100644
--- a/source/Plugins/Process/Utility/FreeBSDSignals.cpp
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "FreeBSDSignals.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/FreeBSDSignals.h b/source/Plugins/Process/Utility/FreeBSDSignals.h
index 8ec96e824f7a..174025cabb82 100644
--- a/source/Plugins/Process/Utility/FreeBSDSignals.h
+++ b/source/Plugins/Process/Utility/FreeBSDSignals.h
@@ -10,7 +10,6 @@
#ifndef liblldb_FreeBSDSignals_H_
#define liblldb_FreeBSDSignals_H_
-// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/GDBRemoteSignals.cpp b/source/Plugins/Process/Utility/GDBRemoteSignals.cpp
index abcc8a38669a..cc0537c2a8b3 100644
--- a/source/Plugins/Process/Utility/GDBRemoteSignals.cpp
+++ b/source/Plugins/Process/Utility/GDBRemoteSignals.cpp
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "GDBRemoteSignals.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/GDBRemoteSignals.h b/source/Plugins/Process/Utility/GDBRemoteSignals.h
index 5900fa75d6f2..79d8ec3fbbaf 100644
--- a/source/Plugins/Process/Utility/GDBRemoteSignals.h
+++ b/source/Plugins/Process/Utility/GDBRemoteSignals.h
@@ -10,10 +10,6 @@
#ifndef liblldb_GDBRemoteSignals_H_
#define liblldb_GDBRemoteSignals_H_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h
index 7675a95246a7..dc24922e7c17 100644
--- a/source/Plugins/Process/Utility/HistoryThread.h
+++ b/source/Plugins/Process/Utility/HistoryThread.h
@@ -10,18 +10,14 @@
#ifndef liblldb_HistoryThread_h_
#define liblldb_HistoryThread_h_
-// C Includes
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/StackFrameList.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/HistoryUnwind.h b/source/Plugins/Process/Utility/HistoryUnwind.h
index 3b64e38bfaa7..2cbfb680ef49 100644
--- a/source/Plugins/Process/Utility/HistoryUnwind.h
+++ b/source/Plugins/Process/Utility/HistoryUnwind.h
@@ -10,12 +10,8 @@
#ifndef liblldb_HistoryUnwind_h_
#define liblldb_HistoryUnwind_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Unwind.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/LinuxProcMaps.cpp b/source/Plugins/Process/Utility/LinuxProcMaps.cpp
new file mode 100644
index 000000000000..d45bf6dcd84f
--- /dev/null
+++ b/source/Plugins/Process/Utility/LinuxProcMaps.cpp
@@ -0,0 +1,113 @@
+//===-- LinuxProcMaps.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LinuxProcMaps.h"
+#include "llvm/ADT/StringRef.h"
+#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/Utility/StringExtractor.h"
+
+using namespace lldb_private;
+
+static Status
+ParseMemoryRegionInfoFromProcMapsLine(llvm::StringRef maps_line,
+ MemoryRegionInfo &memory_region_info) {
+ memory_region_info.Clear();
+
+ StringExtractor line_extractor(maps_line);
+
+ // Format: {address_start_hex}-{address_end_hex} perms offset dev inode
+ // pathname perms: rwxp (letter is present if set, '-' if not, final
+ // character is p=private, s=shared).
+
+ // Parse out the starting address
+ lldb::addr_t start_address = line_extractor.GetHexMaxU64(false, 0);
+
+ // Parse out hyphen separating start and end address from range.
+ if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != '-'))
+ return Status(
+ "malformed /proc/{pid}/maps entry, missing dash between address range");
+
+ // Parse out the ending address
+ lldb::addr_t end_address = line_extractor.GetHexMaxU64(false, start_address);
+
+ // Parse out the space after the address.
+ if (!line_extractor.GetBytesLeft() || (line_extractor.GetChar() != ' '))
+ return Status(
+ "malformed /proc/{pid}/maps entry, missing space after range");
+
+ // Save the range.
+ memory_region_info.GetRange().SetRangeBase(start_address);
+ memory_region_info.GetRange().SetRangeEnd(end_address);
+
+ // Any memory region in /proc/{pid}/maps is by definition mapped into the
+ // process.
+ memory_region_info.SetMapped(MemoryRegionInfo::OptionalBool::eYes);
+
+ // Parse out each permission entry.
+ if (line_extractor.GetBytesLeft() < 4)
+ return Status("malformed /proc/{pid}/maps entry, missing some portion of "
+ "permissions");
+
+ // Handle read permission.
+ const char read_perm_char = line_extractor.GetChar();
+ if (read_perm_char == 'r')
+ memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eYes);
+ else if (read_perm_char == '-')
+ memory_region_info.SetReadable(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ return Status("unexpected /proc/{pid}/maps read permission char");
+
+ // Handle write permission.
+ const char write_perm_char = line_extractor.GetChar();
+ if (write_perm_char == 'w')
+ memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eYes);
+ else if (write_perm_char == '-')
+ memory_region_info.SetWritable(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ return Status("unexpected /proc/{pid}/maps write permission char");
+
+ // Handle execute permission.
+ const char exec_perm_char = line_extractor.GetChar();
+ if (exec_perm_char == 'x')
+ memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eYes);
+ else if (exec_perm_char == '-')
+ memory_region_info.SetExecutable(MemoryRegionInfo::OptionalBool::eNo);
+ else
+ return Status("unexpected /proc/{pid}/maps exec permission char");
+
+ line_extractor.GetChar(); // Read the private bit
+ line_extractor.SkipSpaces(); // Skip the separator
+ line_extractor.GetHexMaxU64(false, 0); // Read the offset
+ line_extractor.GetHexMaxU64(false, 0); // Read the major device number
+ line_extractor.GetChar(); // Read the device id separator
+ line_extractor.GetHexMaxU64(false, 0); // Read the major device number
+ line_extractor.SkipSpaces(); // Skip the separator
+ line_extractor.GetU64(0, 10); // Read the inode number
+
+ line_extractor.SkipSpaces();
+ const char *name = line_extractor.Peek();
+ if (name)
+ memory_region_info.SetName(name);
+
+ return Status();
+}
+
+void lldb_private::ParseLinuxMapRegions(llvm::StringRef linux_map,
+ LinuxMapCallback const &callback) {
+ llvm::StringRef lines(linux_map);
+ llvm::StringRef line;
+ while (!lines.empty()) {
+ std::tie(line, lines) = lines.split('\n');
+ MemoryRegionInfo region;
+ Status error = ParseMemoryRegionInfoFromProcMapsLine(line, region);
+ if (!callback(region, error))
+ break;
+ }
+}
diff --git a/source/Plugins/Process/Utility/LinuxProcMaps.h b/source/Plugins/Process/Utility/LinuxProcMaps.h
new file mode 100644
index 000000000000..e6eabb28fc82
--- /dev/null
+++ b/source/Plugins/Process/Utility/LinuxProcMaps.h
@@ -0,0 +1,28 @@
+//===-- LinuxProcMaps.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_LinuxProcMaps_H_
+#define liblldb_LinuxProcMaps_H_
+
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/StringRef.h"
+#include <functional>
+
+
+namespace lldb_private {
+
+typedef std::function<bool(const lldb_private::MemoryRegionInfo &,
+ const lldb_private::Status &)> LinuxMapCallback;
+
+void ParseLinuxMapRegions(llvm::StringRef linux_map,
+ LinuxMapCallback const &callback);
+
+} // namespace lldb_private
+
+#endif // liblldb_LinuxProcMaps_H_
diff --git a/source/Plugins/Process/Utility/LinuxSignals.cpp b/source/Plugins/Process/Utility/LinuxSignals.cpp
index eb01075ed133..6f1f67ac3570 100644
--- a/source/Plugins/Process/Utility/LinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/LinuxSignals.cpp
@@ -7,9 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "LinuxSignals.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/LinuxSignals.h b/source/Plugins/Process/Utility/LinuxSignals.h
index e41126225cee..f93a9d2e36d1 100644
--- a/source/Plugins/Process/Utility/LinuxSignals.h
+++ b/source/Plugins/Process/Utility/LinuxSignals.h
@@ -10,10 +10,6 @@
#ifndef liblldb_LinuxSignals_H_
#define liblldb_LinuxSignals_H_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
index 36231023aa3a..b6f3b34893bf 100644
--- a/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
+++ b/source/Plugins/Process/Utility/MipsLinuxSignals.cpp
@@ -8,9 +8,6 @@
//
//===----------------------------------------------------------------------===//
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "MipsLinuxSignals.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/MipsLinuxSignals.h b/source/Plugins/Process/Utility/MipsLinuxSignals.h
index e48ea5943f2b..2796f6b8e4d7 100644
--- a/source/Plugins/Process/Utility/MipsLinuxSignals.h
+++ b/source/Plugins/Process/Utility/MipsLinuxSignals.h
@@ -11,10 +11,6 @@
#ifndef liblldb_MipsLinuxSignals_H_
#define liblldb_MipsLinuxSignals_H_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/NetBSDSignals.cpp b/source/Plugins/Process/Utility/NetBSDSignals.cpp
index 7ed7189d8048..a4baab9ac85f 100644
--- a/source/Plugins/Process/Utility/NetBSDSignals.cpp
+++ b/source/Plugins/Process/Utility/NetBSDSignals.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "NetBSDSignals.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/NetBSDSignals.h b/source/Plugins/Process/Utility/NetBSDSignals.h
index 4338f881645e..7bb57fa0c0d6 100644
--- a/source/Plugins/Process/Utility/NetBSDSignals.h
+++ b/source/Plugins/Process/Utility/NetBSDSignals.h
@@ -10,7 +10,6 @@
#ifndef liblldb_NetBSDSignals_H_
#define liblldb_NetBSDSignals_H_
-// Project includes
#include "lldb/Target/UnixSignals.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
index 5d9ff02fafdd..9ad896abd0b4 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -10,14 +10,12 @@
#include "RegisterContextDarwin_arm.h"
#include "RegisterContextDarwinConstants.h"
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "Plugins/Process/Utility/InstructionUtils.h"
@@ -28,7 +26,6 @@
#define LLVM_EXTENSION
#endif
-// Project includes
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
@@ -1673,7 +1670,7 @@ uint32_t RegisterContextDarwin_arm::SetHardwareWatchpoint(lldb::addr_t addr,
return LLDB_INVALID_INDEX32;
// We must watch for either read or write
- if (read == false && write == false)
+ if (!read && !write)
return LLDB_INVALID_INDEX32;
// Can't watch more than 4 bytes per WVR/WCR pair
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
index cdf3479dff69..b46946d608bc 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextDarwin_arm_h_
#define liblldb_RegisterContextDarwin_arm_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
index 03ce7ef9f524..b478645e035d 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.cpp
@@ -11,16 +11,14 @@
#include "RegisterContextDarwin_arm64.h"
#include "RegisterContextDarwinConstants.h"
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
@@ -32,7 +30,6 @@
#define LLVM_EXTENSION
#endif
-// Project includes
#include "Utility/ARM64_DWARF_Registers.h"
using namespace lldb;
@@ -341,12 +338,22 @@ bool RegisterContextDarwin_arm64::ReadRegister(const RegisterInfo *reg_info,
case gpr_x26:
case gpr_x27:
case gpr_x28:
+ value.SetUInt64(gpr.x[reg - gpr_x0]);
+ break;
case gpr_fp:
+ value.SetUInt64(gpr.fp);
+ break;
case gpr_sp:
+ value.SetUInt64(gpr.sp);
+ break;
case gpr_lr:
+ value.SetUInt64(gpr.lr);
+ break;
case gpr_pc:
+ value.SetUInt64(gpr.pc);
+ break;
case gpr_cpsr:
- value.SetUInt64(gpr.x[reg - gpr_x0]);
+ value.SetUInt64(gpr.cpsr);
break;
case gpr_w0:
@@ -949,7 +956,7 @@ uint32_t RegisterContextDarwin_arm64::SetHardwareWatchpoint(lldb::addr_t addr,
return LLDB_INVALID_INDEX32;
// We must watch for either read or write
- if (read == false && write == false)
+ if (!read && !write)
return LLDB_INVALID_INDEX32;
// Can't watch more than 4 bytes per WVR/WCR pair
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
index 4a0e50947ee7..9e826d85af08 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm64.h
@@ -11,10 +11,6 @@
#ifndef liblldb_RegisterContextDarwin_arm64_h_
#define liblldb_RegisterContextDarwin_arm64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
index 24414211d9aa..c9e4b37a17f3 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -7,17 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-#include <stddef.h> // offsetof
+#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
@@ -27,7 +24,6 @@
#define LLVM_EXTENSION
#endif
-// Project includes
#include "RegisterContextDarwin_i386.h"
using namespace lldb;
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
index aea8a2900911..ad6a1e48fc34 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextDarwin_i386_h_
#define liblldb_RegisterContextDarwin_i386_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
index ecad8240b294..95460308857a 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -7,19 +7,16 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-#include <inttypes.h> // PRIx64
+#include <inttypes.h>
#include <stdarg.h>
-#include <stddef.h> // offsetof
+#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Compiler.h"
@@ -29,7 +26,6 @@
#define LLVM_EXTENSION
#endif
-// Project includes
#include "RegisterContextDarwin_x86_64.h"
using namespace lldb;
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
index fdd5e8036dee..6d94bf75aad4 100644
--- a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextDarwin_x86_64_h_
#define liblldb_RegisterContextDarwin_x86_64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
index dd6ca92a74ee..c51c30f45a5d 100644
--- a/source/Plugins/Process/Utility/RegisterContextDummy.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
@@ -11,7 +11,6 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/FuncUnwinders.h"
@@ -28,6 +27,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/lldb-private.h"
#include "RegisterContextDummy.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.h b/source/Plugins/Process/Utility/RegisterContextDummy.h
index ea70288f3d69..d5608616c896 100644
--- a/source/Plugins/Process/Utility/RegisterContextDummy.h
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.h
@@ -11,12 +11,8 @@
#ifndef lldb_RegisterContextDummy_h_
#define lldb_RegisterContextDummy_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
index c9a65b1cacce..b74d0ea75469 100644
--- a/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
+++ b/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
@@ -11,10 +11,6 @@
#ifndef liblldb_RegisterContextFreeBSD_powerpc_h_
#define liblldb_RegisterContextFreeBSD_powerpc_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterInfoInterface.h"
class RegisterContextFreeBSD_powerpc
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.cpp b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
index cc0d696b338a..c9b77663a803 100644
--- a/source/Plugins/Process/Utility/RegisterContextHistory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.cpp
@@ -11,7 +11,6 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/FuncUnwinders.h"
@@ -28,6 +27,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/lldb-private.h"
#include "RegisterContextHistory.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextHistory.h b/source/Plugins/Process/Utility/RegisterContextHistory.h
index acaf8fe5c04a..01b3624f8c5b 100644
--- a/source/Plugins/Process/Utility/RegisterContextHistory.h
+++ b/source/Plugins/Process/Utility/RegisterContextHistory.h
@@ -11,12 +11,8 @@
#ifndef lldb_RegisterContextHistory_h_
#define lldb_RegisterContextHistory_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index ba9a8071bcfb..8c420a87e1b0 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -10,7 +10,6 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Symbol/ArmUnwindInfo.h"
@@ -31,6 +30,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/lldb-private.h"
#include "RegisterContextLLDB.h"
@@ -54,7 +54,8 @@ RegisterContextLLDB::RegisterContextLLDB(Thread &thread,
: RegisterContext(thread, frame_number), m_thread(thread),
m_fast_unwind_plan_sp(), m_full_unwind_plan_sp(),
m_fallback_unwind_plan_sp(), m_all_registers_available(false),
- m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS), m_start_pc(),
+ m_frame_type(-1), m_cfa(LLDB_INVALID_ADDRESS),
+ m_afa(LLDB_INVALID_ADDRESS), m_start_pc(),
m_current_pc(), m_current_offset(0), m_current_offset_backed_up_one(0),
m_sym_ctx(sym_ctx), m_sym_ctx_valid(false), m_frame_number(frame_number),
m_registers(), m_parent_unwind(unwind_lldb) {
@@ -150,7 +151,8 @@ void RegisterContextLLDB::InitializeZerothFrame() {
// We require either a symbol or function in the symbols context to be
// successfully filled in or this context is of no use to us.
- const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+ const SymbolContextItem resolve_scope =
+ eSymbolContextFunction | eSymbolContextSymbol;
if (pc_module_sp.get() && (pc_module_sp->ResolveSymbolContextForAddress(
m_current_pc, resolve_scope, m_sym_ctx) &
resolve_scope)) {
@@ -227,7 +229,7 @@ void RegisterContextLLDB::InitializeZerothFrame() {
return;
}
- if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) {
+ if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
// Try the fall back unwind plan since the
// full unwind plan failed.
FuncUnwindersSP func_unwinders_sp;
@@ -255,12 +257,14 @@ void RegisterContextLLDB::InitializeZerothFrame() {
m_frame_type = eNotAValidFrame;
return;
}
- }
+ } else
+ ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
UnwindLogMsg("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64
- " using %s UnwindPlan",
+ " afa is 0x%" PRIx64 " using %s UnwindPlan",
(uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
(uint64_t)m_cfa,
+ (uint64_t)m_afa,
m_full_unwind_plan_sp->GetSourceName().GetCString());
}
@@ -320,7 +324,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
above_trap_handler = true;
if (pc == 0 || pc == 0x1) {
- if (above_trap_handler == false) {
+ if (!above_trap_handler) {
m_frame_type = eNotAValidFrame;
UnwindLogMsg("this frame has a pc of 0x0");
return;
@@ -378,7 +382,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
RegisterKind row_register_kind = m_full_unwind_plan_sp->GetRegisterKind();
UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
if (row.get()) {
- if (!ReadCFAValueForRow(row_register_kind, row, m_cfa)) {
+ if (!ReadFrameAddress(row_register_kind, row->GetCFAValue(), m_cfa)) {
UnwindLogMsg("failed to get cfa value");
if (m_frame_type != eSkipFrame) // don't override eSkipFrame
{
@@ -387,6 +391,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
return;
}
+ ReadFrameAddress(row_register_kind, row->GetAFAValue(), m_afa);
+
// A couple of sanity checks..
if (m_cfa == LLDB_INVALID_ADDRESS || m_cfa == 0 || m_cfa == 1) {
UnwindLogMsg("could not find a valid cfa address");
@@ -419,7 +425,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
}
- UnwindLogMsg("initialized frame cfa is 0x%" PRIx64, (uint64_t)m_cfa);
+ UnwindLogMsg("initialized frame cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
+ (uint64_t)m_cfa, (uint64_t)m_afa);
return;
}
m_frame_type = eNotAValidFrame;
@@ -436,7 +443,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
// then we might not find the correct unwind information later. Instead, let
// ResolveSymbolContextForAddress fail, and handle the case via
// decr_pc_and_recompute_addr_range below.
- const uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+ const SymbolContextItem resolve_scope =
+ eSymbolContextFunction | eSymbolContextSymbol;
uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress(
m_current_pc, resolve_scope, m_sym_ctx, resolve_tail_call_address);
@@ -466,7 +474,7 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
bool decr_pc_and_recompute_addr_range = false;
// If the symbol lookup failed...
- if (m_sym_ctx_valid == false)
+ if (!m_sym_ctx_valid)
decr_pc_and_recompute_addr_range = true;
// Or if we're in the middle of the stack (and not "above" an asynchronous
@@ -494,7 +502,8 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
temporary_pc.SetLoadAddress(pc - 1, &process->GetTarget());
m_sym_ctx.Clear(false);
m_sym_ctx_valid = false;
- uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
+ SymbolContextItem resolve_scope =
+ eSymbolContextFunction | eSymbolContextSymbol;
ModuleSP temporary_module_sp = temporary_pc.GetModule();
if (temporary_module_sp &&
@@ -581,13 +590,15 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
return;
}
- if (!ReadCFAValueForRow(row_register_kind, active_row, m_cfa)) {
+ if (!ReadFrameAddress(row_register_kind, active_row->GetCFAValue(), m_cfa)) {
UnwindLogMsg("failed to get cfa");
m_frame_type = eNotAValidFrame;
return;
}
- UnwindLogMsg("m_cfa = 0x%" PRIx64, m_cfa);
+ ReadFrameAddress(row_register_kind, active_row->GetAFAValue(), m_afa);
+
+ UnwindLogMsg("m_cfa = 0x%" PRIx64 " m_afa = 0x%" PRIx64, m_cfa, m_afa);
if (CheckIfLoopingStack()) {
TryFallbackUnwindPlan();
@@ -600,9 +611,10 @@ void RegisterContextLLDB::InitializeNonZerothFrame() {
}
UnwindLogMsg("initialized frame current pc is 0x%" PRIx64
- " cfa is 0x%" PRIx64,
+ " cfa is 0x%" PRIx64 " afa is 0x%" PRIx64,
(uint64_t)m_current_pc.GetLoadAddress(exe_ctx.GetTargetPtr()),
- (uint64_t)m_cfa);
+ (uint64_t)m_cfa,
+ (uint64_t)m_afa);
}
bool RegisterContextLLDB::CheckIfLoopingStack() {
@@ -1238,7 +1250,7 @@ RegisterContextLLDB::SavedLocationForRegister(
// Address register and it hasn't been saved anywhere yet -- that is,
// it's still live in the actual register. Handle this specially.
- if (have_unwindplan_regloc == false && return_address_reg.IsValid() &&
+ if (!have_unwindplan_regloc && return_address_reg.IsValid() &&
IsFrameZero()) {
if (return_address_reg.GetAsKind(eRegisterKindLLDB) !=
LLDB_INVALID_REGNUM) {
@@ -1311,17 +1323,13 @@ RegisterContextLLDB::SavedLocationForRegister(
unwindplan_regloc)) {
can_fetch_pc_value = true;
}
- if (ReadCFAValueForRow(unwindplan_registerkind, active_row,
- cfa_value)) {
+ if (ReadFrameAddress(unwindplan_registerkind,
+ active_row->GetCFAValue(), cfa_value)) {
can_fetch_cfa = true;
}
}
- if (can_fetch_pc_value && can_fetch_cfa) {
- have_unwindplan_regloc = true;
- } else {
- have_unwindplan_regloc = false;
- }
+ have_unwindplan_regloc = can_fetch_pc_value && can_fetch_cfa;
} else {
// We were unable to fall back to another unwind plan
have_unwindplan_regloc = false;
@@ -1332,7 +1340,7 @@ RegisterContextLLDB::SavedLocationForRegister(
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
- if (have_unwindplan_regloc == false) {
+ if (!have_unwindplan_regloc) {
// If the UnwindPlan failed to give us an unwind location for this
// register, we may be able to fall back to some ABI-defined default. For
// example, some ABIs allow to determine the caller's SP via the CFA. Also,
@@ -1351,7 +1359,7 @@ RegisterContextLLDB::SavedLocationForRegister(
}
}
- if (have_unwindplan_regloc == false) {
+ if (!have_unwindplan_regloc) {
if (IsFrameZero()) {
// This is frame 0 - we should return the actual live register context
// value
@@ -1397,7 +1405,7 @@ RegisterContextLLDB::SavedLocationForRegister(
}
if (unwindplan_regloc.IsSame()) {
- if (IsFrameZero() == false &&
+ if (!IsFrameZero() &&
(regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_PC ||
regnum.GetAsKind(eRegisterKindGeneric) == LLDB_REGNUM_GENERIC_RA)) {
UnwindLogMsg("register %s (%d) is marked as 'IsSame' - it is a pc or "
@@ -1441,6 +1449,36 @@ RegisterContextLLDB::SavedLocationForRegister(
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
+ if (unwindplan_regloc.IsAFAPlusOffset()) {
+ if (m_afa == LLDB_INVALID_ADDRESS)
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+
+ int offset = unwindplan_regloc.GetOffset();
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+ regloc.location.inferred_value = m_afa + offset;
+ m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg("supplying caller's register %s (%d), value is AFA plus "
+ "offset %d [value is 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
+ regloc.location.inferred_value);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
+
+ if (unwindplan_regloc.IsAtAFAPlusOffset()) {
+ if (m_afa == LLDB_INVALID_ADDRESS)
+ return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+
+ int offset = unwindplan_regloc.GetOffset();
+ regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+ regloc.location.target_memory_location = m_afa + offset;
+ m_registers[regnum.GetAsKind(eRegisterKindLLDB)] = regloc;
+ UnwindLogMsg("supplying caller's register %s (%d) from the stack, saved at "
+ "AFA plus offset %d [saved at 0x%" PRIx64 "]",
+ regnum.GetName(), regnum.GetAsKind(eRegisterKindLLDB), offset,
+ regloc.location.target_memory_location);
+ return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+ }
+
if (unwindplan_regloc.IsInOtherRegister()) {
uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
RegisterNumber row_regnum(m_thread, unwindplan_registerkind,
@@ -1555,7 +1593,6 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
addr_t old_caller_pc_value = LLDB_INVALID_ADDRESS;
addr_t new_caller_pc_value = LLDB_INVALID_ADDRESS;
- addr_t old_this_frame_cfa_value = m_cfa;
UnwindLLDB::RegisterLocation regloc;
if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
regloc) ==
@@ -1585,6 +1622,7 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
// the value of the m_cfa ivar. Save is down below a bit in 'old_cfa'.
UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
addr_t old_cfa = m_cfa;
+ addr_t old_afa = m_afa;
m_registers.clear();
@@ -1595,19 +1633,21 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
if (active_row &&
active_row->GetCFAValue().GetValueType() !=
- UnwindPlan::Row::CFAValue::unspecified) {
+ UnwindPlan::Row::FAValue::unspecified) {
addr_t new_cfa;
- if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(),
- active_row, new_cfa) ||
+ if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetCFAValue(), new_cfa) ||
new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
UnwindLogMsg("failed to get cfa with fallback unwindplan");
m_fallback_unwind_plan_sp.reset();
m_full_unwind_plan_sp = original_full_unwind_plan_sp;
- m_cfa = old_cfa;
return false;
}
m_cfa = new_cfa;
+ ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetAFAValue(), m_afa);
+
if (SavedLocationForRegister(pc_regnum.GetAsKind(eRegisterKindLLDB),
regloc) ==
UnwindLLDB::RegisterSearchResult::eRegisterFound) {
@@ -1628,19 +1668,18 @@ bool RegisterContextLLDB::TryFallbackUnwindPlan() {
m_fallback_unwind_plan_sp.reset();
m_full_unwind_plan_sp = original_full_unwind_plan_sp;
m_cfa = old_cfa;
+ m_afa = old_afa;
return false;
}
- if (old_caller_pc_value != LLDB_INVALID_ADDRESS) {
- if (old_caller_pc_value == new_caller_pc_value &&
- new_cfa == old_this_frame_cfa_value) {
- UnwindLogMsg("fallback unwind plan got the same values for this frame "
- "CFA and caller frame pc, not using");
- m_fallback_unwind_plan_sp.reset();
- m_full_unwind_plan_sp = original_full_unwind_plan_sp;
- m_cfa = old_cfa;
- return false;
- }
+ if (old_caller_pc_value == new_caller_pc_value &&
+ m_cfa == old_cfa &&
+ m_afa == old_afa) {
+ UnwindLogMsg("fallback unwind plan got the same values for this frame "
+ "CFA and caller frame pc, not using");
+ m_fallback_unwind_plan_sp.reset();
+ m_full_unwind_plan_sp = original_full_unwind_plan_sp;
+ return false;
}
UnwindLogMsg("trying to unwind from this function with the UnwindPlan '%s' "
@@ -1674,16 +1713,19 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() {
if (active_row &&
active_row->GetCFAValue().GetValueType() !=
- UnwindPlan::Row::CFAValue::unspecified) {
+ UnwindPlan::Row::FAValue::unspecified) {
addr_t new_cfa;
- if (!ReadCFAValueForRow(m_fallback_unwind_plan_sp->GetRegisterKind(),
- active_row, new_cfa) ||
+ if (!ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetCFAValue(), new_cfa) ||
new_cfa == 0 || new_cfa == 1 || new_cfa == LLDB_INVALID_ADDRESS) {
UnwindLogMsg("failed to get cfa with fallback unwindplan");
m_fallback_unwind_plan_sp.reset();
return false;
}
+ ReadFrameAddress(m_fallback_unwind_plan_sp->GetRegisterKind(),
+ active_row->GetAFAValue(), m_afa);
+
m_full_unwind_plan_sp = m_fallback_unwind_plan_sp;
m_fallback_unwind_plan_sp.reset();
@@ -1698,18 +1740,18 @@ bool RegisterContextLLDB::ForceSwitchToFallbackUnwindPlan() {
return false;
}
-bool RegisterContextLLDB::ReadCFAValueForRow(
- lldb::RegisterKind row_register_kind, const UnwindPlan::RowSP &row,
- addr_t &cfa_value) {
+bool RegisterContextLLDB::ReadFrameAddress(
+ lldb::RegisterKind row_register_kind, UnwindPlan::Row::FAValue &fa,
+ addr_t &address) {
RegisterValue reg_value;
- cfa_value = LLDB_INVALID_ADDRESS;
+ address = LLDB_INVALID_ADDRESS;
addr_t cfa_reg_contents;
- switch (row->GetCFAValue().GetValueType()) {
- case UnwindPlan::Row::CFAValue::isRegisterDereferenced: {
+ switch (fa.GetValueType()) {
+ case UnwindPlan::Row::FAValue::isRegisterDereferenced: {
RegisterNumber cfa_reg(m_thread, row_register_kind,
- row->GetCFAValue().GetRegisterNumber());
+ fa.GetRegisterNumber());
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
const RegisterInfo *reg_info =
GetRegisterInfoAtIndex(cfa_reg.GetAsKind(eRegisterKindLLDB));
@@ -1718,12 +1760,12 @@ bool RegisterContextLLDB::ReadCFAValueForRow(
Status error = ReadRegisterValueFromMemory(
reg_info, cfa_reg_contents, reg_info->byte_size, reg_value);
if (error.Success()) {
- cfa_value = reg_value.GetAsUInt64();
+ address = reg_value.GetAsUInt64();
UnwindLogMsg(
"CFA value via dereferencing reg %s (%d): reg has val 0x%" PRIx64
", CFA value is 0x%" PRIx64,
cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
- cfa_reg_contents, cfa_value);
+ cfa_reg_contents, address);
return true;
} else {
UnwindLogMsg("Tried to deref reg %s (%d) [0x%" PRIx64
@@ -1735,9 +1777,9 @@ bool RegisterContextLLDB::ReadCFAValueForRow(
}
break;
}
- case UnwindPlan::Row::CFAValue::isRegisterPlusOffset: {
+ case UnwindPlan::Row::FAValue::isRegisterPlusOffset: {
RegisterNumber cfa_reg(m_thread, row_register_kind,
- row->GetCFAValue().GetRegisterNumber());
+ fa.GetRegisterNumber());
if (ReadGPRValue(cfa_reg, cfa_reg_contents)) {
if (cfa_reg_contents == LLDB_INVALID_ADDRESS || cfa_reg_contents == 0 ||
cfa_reg_contents == 1) {
@@ -1748,35 +1790,35 @@ bool RegisterContextLLDB::ReadCFAValueForRow(
cfa_reg_contents = LLDB_INVALID_ADDRESS;
return false;
}
- cfa_value = cfa_reg_contents + row->GetCFAValue().GetOffset();
+ address = cfa_reg_contents + fa.GetOffset();
UnwindLogMsg(
"CFA is 0x%" PRIx64 ": Register %s (%d) contents are 0x%" PRIx64
", offset is %d",
- cfa_value, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
- cfa_reg_contents, row->GetCFAValue().GetOffset());
+ address, cfa_reg.GetName(), cfa_reg.GetAsKind(eRegisterKindLLDB),
+ cfa_reg_contents, fa.GetOffset());
return true;
}
break;
}
- case UnwindPlan::Row::CFAValue::isDWARFExpression: {
+ case UnwindPlan::Row::FAValue::isDWARFExpression: {
ExecutionContext exe_ctx(m_thread.shared_from_this());
Process *process = exe_ctx.GetProcessPtr();
- DataExtractor dwarfdata(row->GetCFAValue().GetDWARFExpressionBytes(),
- row->GetCFAValue().GetDWARFExpressionLength(),
+ DataExtractor dwarfdata(fa.GetDWARFExpressionBytes(),
+ fa.GetDWARFExpressionLength(),
process->GetByteOrder(),
process->GetAddressByteSize());
ModuleSP opcode_ctx;
DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr, 0,
- row->GetCFAValue().GetDWARFExpressionLength());
+ fa.GetDWARFExpressionLength());
dwarfexpr.SetRegisterKind(row_register_kind);
Value result;
Status error;
if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
&error)) {
- cfa_value = result.GetScalar().ULongLong();
+ address = result.GetScalar().ULongLong();
UnwindLogMsg("CFA value set by DWARF expression is 0x%" PRIx64,
- cfa_value);
+ address);
return true;
}
UnwindLogMsg("Failed to set CFA value via DWARF expression: %s",
@@ -2005,12 +2047,8 @@ bool RegisterContextLLDB::ReadPC(addr_t &pc) {
pc = abi->FixCodeAddress(pc);
}
- if (m_all_registers_available == false && above_trap_handler == false &&
- (pc == 0 || pc == 1)) {
- return false;
- }
-
- return true;
+ return !(m_all_registers_available == false &&
+ above_trap_handler == false && (pc == 0 || pc == 1));
} else {
return false;
}
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h
index 7e9e77dcf06d..50f12c6f8541 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -11,12 +11,8 @@
#ifndef lldb_RegisterContextLLDB_h_
#define lldb_RegisterContextLLDB_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "UnwindLLDB.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/UnwindPlan.h"
@@ -192,9 +188,9 @@ private:
bool ReadGPRValue(const RegisterNumber &reg_num, lldb::addr_t &value);
- // Get the CFA register for a given frame.
- bool ReadCFAValueForRow(lldb::RegisterKind register_kind,
- const UnwindPlan::RowSP &row, lldb::addr_t &value);
+ // Get the Frame Address register for a given frame.
+ bool ReadFrameAddress(lldb::RegisterKind register_kind,
+ UnwindPlan::Row::FAValue &fa, lldb::addr_t &address);
lldb::UnwindPlanSP GetFastUnwindPlanForFrame();
@@ -225,6 +221,7 @@ private:
int m_frame_type; // enum FrameType
lldb::addr_t m_cfa;
+ lldb::addr_t m_afa;
lldb_private::Address m_start_pc;
lldb_private::Address m_current_pc;
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index 77c1bea34851..c0a6084cd723 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -9,16 +9,12 @@
#include "RegisterContextMacOSXFrameBackchain.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
-// Project includes
#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
index 4f5816aa4909..69e23c2782fd 100644
--- a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
@@ -10,10 +10,6 @@
#ifndef lldb_RegisterContextMacOSXFrameBackchain_h_
#define lldb_RegisterContextMacOSXFrameBackchain_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
index 71d35bbd3938..69522ace1a68 100644
--- a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
@@ -11,13 +11,9 @@
#include "RegisterContextMach_arm.h"
-// C Includes
#include <mach/mach_types.h>
#include <mach/thread_act.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_arm.h b/source/Plugins/Process/Utility/RegisterContextMach_arm.h
index a2cf6bfcbe4a..5ea47f214e25 100644
--- a/source/Plugins/Process/Utility/RegisterContextMach_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextMach_arm.h
@@ -10,11 +10,7 @@
#ifndef liblldb_RegisterContextMach_arm_h_
#define liblldb_RegisterContextMach_arm_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextDarwin_arm.h"
class RegisterContextMach_arm : public RegisterContextDarwin_arm {
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
index 5a260d5de1d5..94138605239e 100644
--- a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
@@ -9,12 +9,8 @@
#if defined(__APPLE__)
-// C Includes
#include <mach/thread_act.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextMach_i386.h"
using namespace lldb;
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_i386.h b/source/Plugins/Process/Utility/RegisterContextMach_i386.h
index 8ac693a55584..a7e29e96b267 100644
--- a/source/Plugins/Process/Utility/RegisterContextMach_i386.h
+++ b/source/Plugins/Process/Utility/RegisterContextMach_i386.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextMach_i386_h_
#define liblldb_RegisterContextMach_i386_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextDarwin_i386.h"
class RegisterContextMach_i386 : public RegisterContextDarwin_i386 {
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
index 0180879d51ee..e523b95ee974 100644
--- a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
@@ -9,12 +9,8 @@
#if defined(__APPLE__)
-// C Includes
#include <mach/thread_act.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextMach_x86_64.h"
using namespace lldb;
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h
index cd425046b08e..c73bdda79713 100644
--- a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h
+++ b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h
@@ -11,10 +11,6 @@
#ifndef liblldb_RegisterContextMach_x86_64_h_
#define liblldb_RegisterContextMach_x86_64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContextDarwin_x86_64.h"
class RegisterContextMach_x86_64 : public RegisterContextDarwin_x86_64 {
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
index 76189ea781de..f05c07f6c8e1 100644
--- a/source/Plugins/Process/Utility/RegisterContextMemory.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -9,15 +9,11 @@
#include "RegisterContextMemory.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "DynamicRegisterInfo.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h
index cad1592af5ba..cdf2a5446e1e 100644
--- a/source/Plugins/Process/Utility/RegisterContextMemory.h
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -10,12 +10,8 @@
#ifndef lldb_RegisterContextMemory_h_
#define lldb_RegisterContextMemory_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
index 352e251e3b64..b0e53cfcc91f 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.cpp
@@ -11,14 +11,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_arm.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
index 8c5fe9d2c2de..4b5a8fe95a4f 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_arm_h_
#define liblldb_RegisterContextPOSIX_arm_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterInfoInterface.h"
#include "lldb-arm-register-enums.h"
#include "lldb/Target/RegisterContext.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
index 3ff93cde2347..8b00dfc81eab 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.cpp
@@ -11,14 +11,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_arm64.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
index 27251da2a9af..603c12d830d9 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_arm64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_arm64_h_
#define liblldb_RegisterContextPOSIX_arm64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterInfoInterface.h"
#include "lldb-arm64-register-enums.h"
#include "lldb/Target/RegisterContext.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
index 98d1e6fa8817..9270d09f7293 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.cpp
@@ -11,14 +11,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_mips64.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
index 1695ec9a0bab..09cfd42b9c51 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_mips64.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_mips64_h_
#define liblldb_RegisterContextPOSIX_mips64_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContext_mips.h"
#include "RegisterInfoInterface.h"
#include "lldb/Target/RegisterContext.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
index 9f0552539723..47a8e2c3f9e9 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -12,14 +12,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_powerpc.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
index 50f234680ca0..3260cb1ce8bc 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_powerpc_h_
#define liblldb_RegisterContextPOSIX_powerpc_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContext_powerpc.h"
#include "RegisterInfoInterface.h"
#include "lldb/Target/RegisterContext.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
index 41ae5ec6b51a..ef221c963dc4 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.cpp
@@ -11,14 +11,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_ppc64le.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h
index 1070b4dea405..9159819f17c4 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_ppc64le.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_ppc64le_h_
#define liblldb_RegisterContextPOSIX_ppc64le_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
#include "RegisterInfoInterface.h"
#include "Utility/PPC64LE_DWARF_Registers.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
index 662ac38405ef..24f131099be4 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
@@ -11,14 +11,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_s390x.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h
index d5337630c32d..7a7b6bddd6aa 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_s390x_h_
#define liblldb_RegisterContextPOSIX_s390x_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContext_s390x.h"
#include "RegisterInfoInterface.h"
#include "lldb-s390x-register-enums.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
index d2a06e1b7897..78f561a0f04f 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp
@@ -11,14 +11,14 @@
#include <errno.h>
#include <stdint.h>
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "llvm/Support/Compiler.h"
#include "RegisterContextPOSIX_x86.h"
@@ -376,7 +376,7 @@ 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())
+ if (!ReadFPR())
m_fpr_type = eFXSAVE; // assume generic floating-point registers
}
return m_fpr_type;
diff --git a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
index ca71a6f272f8..b6db45e55bbf 100644
--- a/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.h
@@ -10,10 +10,6 @@
#ifndef liblldb_RegisterContextPOSIX_x86_h_
#define liblldb_RegisterContextPOSIX_x86_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "RegisterContext_x86.h"
#include "RegisterInfoInterface.h"
#include "lldb-x86-register-enums.h"
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
index 3b3b0856a4ca..0d50c73a31a9 100644
--- a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
@@ -10,12 +10,8 @@
#ifndef lldb_RegisterContextThreadMemory_h_
#define lldb_RegisterContextThreadMemory_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterContext_x86.h b/source/Plugins/Process/Utility/RegisterContext_x86.h
index 6146dcaf7e5a..e3ff492d707a 100644
--- a/source/Plugins/Process/Utility/RegisterContext_x86.h
+++ b/source/Plugins/Process/Utility/RegisterContext_x86.h
@@ -341,7 +341,7 @@ LLVM_PACKED_END
// x86 extensions to FXSAVE (i.e. for AVX and MPX processors)
LLVM_PACKED_START
-struct LLVM_ALIGNAS(64) XSAVE {
+struct LLVM_ALIGNAS(16) 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
diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm.h b/source/Plugins/Process/Utility/RegisterInfos_arm.h
index 74d3226c8a52..ec951ea8a391 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_arm.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_arm.h
@@ -9,12 +9,8 @@
#ifdef DECLARE_REGISTER_INFOS_ARM_STRUCT
-// C Includes
#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterInfos_arm64.h b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
index b996533791ff..039d98ecdd2d 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_arm64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_arm64.h
@@ -9,12 +9,8 @@
#ifdef DECLARE_REGISTER_INFOS_ARM64_STRUCT
-// C Includes
#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Utility/RegisterInfos_i386.h b/source/Plugins/Process/Utility/RegisterInfos_i386.h
index ffdc4d0d116b..f8947876d15f 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_i386.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_i386.h
@@ -11,7 +11,6 @@
#include <cstddef>
#include <cstdint>
-// Project includes
#ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips.h b/source/Plugins/Process/Utility/RegisterInfos_mips.h
index b116b99b3f81..36483c068d26 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_mips.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_mips.h
@@ -7,15 +7,11 @@
//
//===---------------------------------------------------------------------===//
-// C Includes
#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Core/dwarf.h"
#include "llvm/Support/Compiler.h"
-// Project includes
#ifdef DECLARE_REGISTER_INFOS_MIPS_STRUCT
diff --git a/source/Plugins/Process/Utility/RegisterInfos_mips64.h b/source/Plugins/Process/Utility/RegisterInfos_mips64.h
index 3c3912fa6978..0194074f34f2 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_mips64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_mips64.h
@@ -7,15 +7,11 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Core/dwarf.h"
#include "llvm/Support/Compiler.h"
-// Project includes
#ifdef DECLARE_REGISTER_INFOS_MIPS64_STRUCT
diff --git a/source/Plugins/Process/Utility/RegisterInfos_ppc64.h b/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
index 69f00e4ba885..dbd87ad71a45 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_ppc64.h
@@ -9,7 +9,6 @@
#ifdef DECLARE_REGISTER_INFOS_PPC64_STRUCT
-// C Includes
#include <stddef.h>
// Computes the offset of the given GPR_PPC64 in the user data area.
diff --git a/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h b/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
index bffa7a1d8b63..e6fa17b60758 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_ppc64le.h
@@ -9,7 +9,6 @@
#ifdef DECLARE_REGISTER_INFOS_PPC64LE_STRUCT
-// C Includes
#include <stddef.h>
// Computes the offset of the given GPR in the user data area.
diff --git a/source/Plugins/Process/Utility/RegisterInfos_s390x.h b/source/Plugins/Process/Utility/RegisterInfos_s390x.h
index 0bbf422405ee..b750be4116a5 100644
--- a/source/Plugins/Process/Utility/RegisterInfos_s390x.h
+++ b/source/Plugins/Process/Utility/RegisterInfos_s390x.h
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stddef.h>
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/Support/Compiler.h"
-// Project includes
#ifdef DECLARE_REGISTER_INFOS_S390X_STRUCT
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp
index 3dbfe611e713..de0821eb4253 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.cpp
+++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -9,10 +9,12 @@
#include "StopInfoMachException.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
+
+#if defined(__APPLE__)
+// Needed for the EXC_RESOURCE interpretation macros
+#include <kern/exc_resource.h>
+#endif
+
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/DynamicLoader.h"
@@ -41,6 +43,12 @@ const char *StopInfoMachException::GetDescription() {
const char *code_desc = NULL;
const char *subcode_label = "subcode";
const char *subcode_desc = NULL;
+
+#if defined(__APPLE__)
+ char code_desc_buf[32];
+ char subcode_desc_buf[32];
+#endif
+
switch (m_value) {
case 1: // EXC_BAD_ACCESS
exc_desc = "EXC_BAD_ACCESS";
@@ -275,6 +283,47 @@ const char *StopInfoMachException::GetDescription() {
break;
case 11:
exc_desc = "EXC_RESOURCE";
+#if defined(__APPLE__)
+ {
+ int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code);
+
+ code_label = "limit";
+ code_desc = code_desc_buf;
+ subcode_label = "observed";
+ subcode_desc = subcode_desc_buf;
+
+ switch (resource_type) {
+ case RESOURCE_TYPE_CPU:
+ exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU";
+ snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%",
+ (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code));
+ snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%",
+ (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(m_exc_subcode));
+ break;
+ case RESOURCE_TYPE_WAKEUPS:
+ exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS";
+ snprintf(code_desc_buf, sizeof(code_desc_buf), "%d w/s",
+ (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code));
+ snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s",
+ (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(m_exc_subcode));
+ break;
+ case RESOURCE_TYPE_MEMORY:
+ exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY";
+ snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
+ (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code));
+ subcode_desc = nullptr;
+ subcode_label = "unused";
+ break;
+ case RESOURCE_TYPE_IO:
+ exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO";
+ snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB",
+ (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code));
+ snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB",
+ (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));;
+ break;
+ }
+ }
+#endif
break;
case 12:
exc_desc = "EXC_GUARD";
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.h b/source/Plugins/Process/Utility/StopInfoMachException.h
index 94516454105e..027ed80e8a98 100644
--- a/source/Plugins/Process/Utility/StopInfoMachException.h
+++ b/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -10,12 +10,8 @@
#ifndef liblldb_StopInfoMachException_h_
#define liblldb_StopInfoMachException_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StopInfo.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Utility/ThreadMemory.h b/source/Plugins/Process/Utility/ThreadMemory.h
index 89229710da4d..c966ca03a017 100644
--- a/source/Plugins/Process/Utility/ThreadMemory.h
+++ b/source/Plugins/Process/Utility/ThreadMemory.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ThreadMemory_h_
#define liblldb_ThreadMemory_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
class ThreadMemory : public lldb_private::Thread {
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 55559f07f1e5..b34c87230bd1 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -130,6 +130,8 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB(
m_thread, prev_frame->reg_ctx_lldb_sp, cursor_sp->sctx, cur_idx, *this));
+ uint64_t max_stack_depth = m_thread.GetMaxBacktraceDepth();
+
// We want to detect an unwind that cycles erroneously and stop backtracing.
// Don't want this maximum unwind limit to be too low -- if you have a
// backtrace with an "infinitely recursing" bug, it will crash when the stack
@@ -138,7 +140,7 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
// unwind at 10,000 or something. Realistically anything over around 200,000
// is going to blow out the stack space. If we're still unwinding at that
// point, we're probably never going to finish.
- if (cur_idx > 300000) {
+ if (cur_idx >= max_stack_depth) {
if (log)
log->Printf("%*sFrame %d unwound too many frames, assuming unwind has "
"gone astray, stopping.",
@@ -210,15 +212,15 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
// On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not
// have its (constructed) CFA aligned correctly -- don't do the abi
// alignment check for these.
- if (reg_ctx_sp->IsTrapHandlerFrame() == false) {
+ if (!reg_ctx_sp->IsTrapHandlerFrame()) {
// See if we can find a fallback unwind plan for THIS frame. It may be
// that the UnwindPlan we're using for THIS frame was bad and gave us a
// bad CFA. If that's not it, then see if we can change the UnwindPlan
// for the frame below us ("NEXT") -- see if using that other UnwindPlan
// gets us a better unwind state.
- if (reg_ctx_sp->TryFallbackUnwindPlan() == false ||
- reg_ctx_sp->GetCFA(cursor_sp->cfa) == false ||
- abi->CallFrameAddressIsValid(cursor_sp->cfa) == false) {
+ if (!reg_ctx_sp->TryFallbackUnwindPlan() ||
+ !reg_ctx_sp->GetCFA(cursor_sp->cfa) ||
+ !abi->CallFrameAddressIsValid(cursor_sp->cfa)) {
if (prev_frame->reg_ctx_lldb_sp->TryFallbackUnwindPlan()) {
// TryFallbackUnwindPlan for prev_frame succeeded and updated
// reg_ctx_lldb_sp field of prev_frame. However, cfa field of
@@ -383,10 +385,8 @@ bool UnwindLLDB::AddOneMoreFrame(ABI *abi) {
// Cursor::m_frames[m_frames.size() - 2], reg_ctx_lldb_sp field was already
// updated during TryFallbackUnwindPlan call above. However, cfa field
// still needs to be updated. Hence updating it here and then returning.
- if (!(m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(
- m_frames[m_frames.size() - 2]->cfa)))
- return false;
- return true;
+ return m_frames[m_frames.size() - 2]->reg_ctx_lldb_sp->GetCFA(
+ m_frames[m_frames.size() - 2]->cfa);
}
// The new frame hasn't helped in unwinding. Fall back to the original one as
@@ -468,10 +468,7 @@ bool UnwindLLDB::SearchForSavedLocationForRegister(
UnwindLLDB::RegisterSearchResult result;
result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister(
lldb_regnum, regloc);
- if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
- return true;
- else
- return false;
+ return result == UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
while (frame_num >= 0) {
UnwindLLDB::RegisterSearchResult result;
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
index 3d1f85a3dec3..aec7b66d9354 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -10,12 +10,8 @@
#ifndef lldb_UnwindLLDB_h_
#define lldb_UnwindLLDB_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/UnwindPlan.h"
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
index 2115b4e179c0..ae0b9fb0a526 100644
--- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
@@ -114,7 +114,7 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_i386(
if (!m_cursors.empty()) {
lldb::addr_t first_frame_pc = m_cursors.front().pc;
if (first_frame_pc != LLDB_INVALID_ADDRESS) {
- const uint32_t resolve_scope =
+ const SymbolContextItem resolve_scope =
eSymbolContextModule | eSymbolContextCompUnit |
eSymbolContextFunction | eSymbolContextSymbol;
@@ -205,7 +205,7 @@ size_t UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64(
if (!m_cursors.empty()) {
lldb::addr_t first_frame_pc = m_cursors.front().pc;
if (first_frame_pc != LLDB_INVALID_ADDRESS) {
- const uint32_t resolve_scope =
+ const SymbolContextItem resolve_scope =
eSymbolContextModule | eSymbolContextCompUnit |
eSymbolContextFunction | eSymbolContextSymbol;
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
index 328117a306ef..9ee0b08ca09a 100644
--- a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
@@ -10,12 +10,8 @@
#ifndef lldb_UnwindMacOSXFrameBackchain_h_
#define lldb_UnwindMacOSXFrameBackchain_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Unwind.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
index ad43551a4c6d..81ec25871c57 100644
--- a/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
+++ b/source/Plugins/Process/Windows/Common/DebuggerThread.cpp
@@ -12,7 +12,6 @@
#include "IDebugDelegate.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Host/ThreadLauncher.h"
#include "lldb/Host/windows/HostProcessWindows.h"
#include "lldb/Host/windows/HostThreadWindows.h"
@@ -21,6 +20,7 @@
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/Status.h"
#include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
@@ -50,7 +50,7 @@ struct DebugAttachContext {
lldb::pid_t m_pid;
ProcessAttachInfo m_attach_info;
};
-}
+} // namespace
DebuggerThread::DebuggerThread(DebugDelegateSP debug_delegate)
: m_debug_delegate(debug_delegate), m_pid_to_detach(0),
@@ -191,7 +191,8 @@ Status DebuggerThread::StopDebugging(bool terminate) {
handle, pid, terminate_suceeded);
} else {
LLDB_LOG(log,
- "NOT calling TerminateProcess because the inferior is not valid ({0}, 0) (inferior={1})",
+ "NOT calling TerminateProcess because the inferior is not valid "
+ "({0}, 0) (inferior={1})",
handle, pid);
}
}
@@ -267,6 +268,8 @@ void DebuggerThread::DebugLoop() {
if (wait_result) {
DWORD continue_status = DBG_CONTINUE;
switch (dbe.dwDebugEventCode) {
+ default:
+ llvm_unreachable("Unhandle debug event code!");
case EXCEPTION_DEBUG_EVENT: {
ExceptionResult status =
HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
@@ -330,7 +333,7 @@ void DebuggerThread::DebugLoop() {
FreeProcessHandles();
LLDB_LOG(log, "WaitForDebugEvent loop completed, exiting.");
- SetEvent(m_debugging_ended_event);
+ ::SetEvent(m_debugging_ended_event);
}
ExceptionResult
@@ -381,7 +384,7 @@ DebuggerThread::HandleCreateThreadEvent(const CREATE_THREAD_DEBUG_INFO &info,
DWORD thread_id) {
Log *log =
ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_EVENT | WINDOWS_LOG_THREAD);
- LLDB_LOG(log, "Thread {0:x} spawned in process {1}", thread_id,
+ LLDB_LOG(log, "Thread {0} spawned in process {1}", thread_id,
m_process.GetProcessId());
HostThread thread(info.hThread);
thread.GetNativeThread().SetOwnsHandle(false);
@@ -439,7 +442,6 @@ DebuggerThread::HandleExitProcessEvent(const EXIT_PROCESS_DEBUG_INFO &info,
m_debug_delegate->OnExitProcess(info.dwExitCode);
- FreeProcessHandles();
return DBG_CONTINUE;
}
@@ -468,7 +470,7 @@ DebuggerThread::HandleLoadDllEvent(const LOAD_DLL_DEBUG_INFO &info,
if (path_str.startswith("\\\\?\\"))
path += 4;
- FileSpec file_spec(path, false);
+ FileSpec file_spec(path);
ModuleSpec module_spec(file_spec);
lldb::addr_t load_addr = reinterpret_cast<lldb::addr_t>(info.lpBaseOfDll);
diff --git a/source/Plugins/Process/Windows/Common/DebuggerThread.h b/source/Plugins/Process/Windows/Common/DebuggerThread.h
index fcf36f7dec9b..047d3ccb7296 100644
--- a/source/Plugins/Process/Windows/Common/DebuggerThread.h
+++ b/source/Plugins/Process/Windows/Common/DebuggerThread.h
@@ -16,8 +16,8 @@
#include "ForwardDecl.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/HostThread.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/Predicate.h"
namespace lldb_private {
diff --git a/source/Plugins/Process/Windows/Common/ForwardDecl.h b/source/Plugins/Process/Windows/Common/ForwardDecl.h
index cfe1b79cee11..ce2af3ca4111 100644
--- a/source/Plugins/Process/Windows/Common/ForwardDecl.h
+++ b/source/Plugins/Process/Windows/Common/ForwardDecl.h
@@ -39,4 +39,4 @@ typedef std::shared_ptr<ExceptionRecord> ExceptionRecordSP;
typedef std::unique_ptr<ExceptionRecord> ExceptionRecordUP;
}
-#endif \ No newline at end of file
+#endif
diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
index b14081f76617..3fe5ab7804cb 100644
--- a/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
+++ b/source/Plugins/Process/Windows/Common/ProcessWindows.cpp
@@ -13,12 +13,11 @@
#include "lldb/Host/windows/windows.h"
#include <psapi.h>
-// Other libraries and framework includes
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostNativeProcessBase.h"
#include "lldb/Host/HostProcess.h"
#include "lldb/Host/windows/HostThreadWindows.h"
@@ -28,6 +27,7 @@
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/State.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Format.h"
@@ -72,6 +72,20 @@ std::string GetProcessExecutableName(DWORD pid) {
return file_name;
}
+DWORD ConvertLldbToWinApiProtect(uint32_t protect) {
+ // We also can process a read / write permissions here, but if the debugger
+ // will make later a write into the allocated memory, it will fail. To get
+ // around it is possible inside DoWriteMemory to remember memory permissions,
+ // allow write, write and restore permissions, but for now we process only
+ // the executable permission.
+ //
+ // TODO: Process permissions other than executable
+ if (protect & ePermissionsExecutable)
+ return PAGE_EXECUTE_READWRITE;
+
+ return PAGE_READWRITE;
+}
+
} // anonymous namespace
namespace lldb_private {
@@ -237,11 +251,13 @@ Status ProcessWindows::DoLaunch(Module *exe_module,
FileSpec working_dir = launch_info.GetWorkingDirectory();
namespace fs = llvm::sys::fs;
- if (working_dir && (!working_dir.ResolvePath() ||
- !fs::is_directory(working_dir.GetPath()))) {
- result.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return result;
+ if (working_dir) {
+ FileSystem::Instance().Resolve(working_dir);
+ if (!FileSystem::Instance().IsDirectory(working_dir)) {
+ result.SetErrorStringWithFormat("No such file or directory: %s",
+ working_dir.GetCString());
+ return result;
+ }
}
if (!launch_info.GetFlags().Test(eLaunchFlagDebug)) {
@@ -379,7 +395,7 @@ Status ProcessWindows::DoResume() {
SetPrivateState(eStateRunning);
}
} else {
- LLDB_LOG(log, "error: process %I64u is in state %u. Returning...",
+ LLDB_LOG(log, "error: process {0} is in state {1}. Returning...",
m_session_data->m_debugger->GetProcess().GetProcessId(),
GetPrivateState());
}
@@ -577,7 +593,7 @@ bool ProcessWindows::CanDebug(lldb::TargetSP target_sp,
// For now we are just making sure the file exists for a given module
ModuleSP exe_module_sp(target_sp->GetExecutableModule());
if (exe_module_sp.get())
- return exe_module_sp->GetFileSpec().Exists();
+ return FileSystem::Instance().Exists(exe_module_sp->GetFileSpec());
// However, if there is no executable module, we return true since we might
// be preparing to attach.
return true;
@@ -695,6 +711,58 @@ size_t ProcessWindows::DoWriteMemory(lldb::addr_t vm_addr, const void *buf,
return bytes_written;
}
+lldb::addr_t ProcessWindows::DoAllocateMemory(size_t size, uint32_t permissions,
+ Status &error) {
+ Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
+ llvm::sys::ScopedLock lock(m_mutex);
+ LLDB_LOG(log, "attempting to allocate {0} bytes with permissions {1}", size,
+ permissions);
+
+ if (!m_session_data) {
+ LLDB_LOG(log, "cannot allocate, there is no active debugger connection.");
+ error.SetErrorString(
+ "cannot allocate, there is no active debugger connection");
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ HostProcess process = m_session_data->m_debugger->GetProcess();
+ lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
+ auto protect = ConvertLldbToWinApiProtect(permissions);
+ auto result = VirtualAllocEx(handle, nullptr, size, MEM_COMMIT, protect);
+ if (!result) {
+ error.SetError(GetLastError(), eErrorTypeWin32);
+ LLDB_LOG(log, "allocating failed with error: {0}", error);
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ return reinterpret_cast<addr_t>(result);
+}
+
+Status ProcessWindows::DoDeallocateMemory(lldb::addr_t ptr) {
+ Status result;
+
+ Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
+ llvm::sys::ScopedLock lock(m_mutex);
+ LLDB_LOG(log, "attempting to deallocate bytes at address {0}", ptr);
+
+ if (!m_session_data) {
+ LLDB_LOG(log, "cannot deallocate, there is no active debugger connection.");
+ result.SetErrorString(
+ "cannot deallocate, there is no active debugger connection");
+ return result;
+ }
+
+ HostProcess process = m_session_data->m_debugger->GetProcess();
+ lldb::process_t handle = process.GetNativeProcess().GetSystemHandle();
+ if (!VirtualFreeEx(handle, reinterpret_cast<LPVOID>(ptr), 0, MEM_RELEASE)) {
+ result.SetError(GetLastError(), eErrorTypeWin32);
+ LLDB_LOG(log, "deallocating failed with error: {0}", result);
+ return result;
+ }
+
+ return result;
+}
+
Status ProcessWindows::GetMemoryRegionInfo(lldb::addr_t vm_addr,
MemoryRegionInfo &info) {
Log *log = ProcessWindowsLog::GetLogIfAny(WINDOWS_LOG_MEMORY);
@@ -812,6 +880,14 @@ void ProcessWindows::OnExitProcess(uint32_t exit_code) {
SetProcessExitStatus(GetID(), true, 0, exit_code);
SetPrivateState(eStateExited);
+
+ // If the process exits before any initial stop then notify the debugger
+ // of the error otherwise WaitForDebuggerConnection() will be blocked.
+ // An example of this issue is when a process fails to load a dependent DLL.
+ if (m_session_data && !m_session_data->m_initial_stop_received) {
+ Status error(exit_code, eErrorTypeWin32);
+ OnDebuggerError(error, 0);
+ }
}
void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
@@ -829,7 +905,8 @@ void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
return;
}
- FileSpec executable_file(file_name, true);
+ FileSpec executable_file(file_name);
+ FileSystem::Instance().Resolve(executable_file);
ModuleSpec module_spec(executable_file);
Status error;
module = GetTarget().GetSharedModule(module_spec, &error);
@@ -837,7 +914,7 @@ void ProcessWindows::OnDebuggerConnected(lldb::addr_t image_base) {
return;
}
- GetTarget().SetExecutableModule(module, false);
+ GetTarget().SetExecutableModule(module, eLoadDependentsNo);
}
bool load_addr_changed;
@@ -880,8 +957,9 @@ ProcessWindows::OnDebugException(bool first_chance,
}
if (!first_chance) {
- // Any second chance exception is an application crash by definition.
- SetPrivateState(eStateCrashed);
+ // Not any second chance exception is an application crash by definition.
+ // It may be an expression evaluation crash.
+ SetPrivateState(eStateStopped);
}
ExceptionResult result = ExceptionResult::SendToApplication;
diff --git a/source/Plugins/Process/Windows/Common/ProcessWindows.h b/source/Plugins/Process/Windows/Common/ProcessWindows.h
index ed3938beb347..00e384f58408 100644
--- a/source/Plugins/Process/Windows/Common/ProcessWindows.h
+++ b/source/Plugins/Process/Windows/Common/ProcessWindows.h
@@ -10,7 +10,6 @@
#ifndef liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
#define liblldb_Plugins_Process_Windows_Common_ProcessWindows_H_
-// Other libraries and framework includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-forward.h"
@@ -84,6 +83,9 @@ public:
Status &error) override;
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
Status &error) override;
+ lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions,
+ Status &error) override;
+ Status DoDeallocateMemory(lldb::addr_t ptr) override;
Status GetMemoryRegionInfo(lldb::addr_t vm_addr,
MemoryRegionInfo &info) override;
diff --git a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp b/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
index b3f507128f82..90d43b2cf828 100644
--- a/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
+++ b/source/Plugins/Process/Windows/Common/RegisterContextWindows.cpp
@@ -40,12 +40,13 @@ void RegisterContextWindows::InvalidateAllRegisters() {
bool RegisterContextWindows::ReadAllRegisterValues(
lldb::DataBufferSP &data_sp) {
+
if (!CacheAllRegisterValues())
return false;
- if (data_sp->GetByteSize() < sizeof(m_context)) {
- data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
- }
+
+ data_sp.reset(new DataBufferHeap(sizeof(CONTEXT), 0));
memcpy(data_sp->GetBytes(), &m_context, sizeof(m_context));
+
return true;
}
diff --git a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
index 3903280918cc..b121dc7bf15e 100644
--- a/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
+++ b/source/Plugins/Process/Windows/Common/TargetThreadWindows.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/HostNativeThreadBase.h"
#include "lldb/Host/windows/HostThreadWindows.h"
@@ -15,6 +14,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/State.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "ProcessWindows.h"
diff --git a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp
index 4aa6c785f83c..584136a6e5bb 100644
--- a/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp
+++ b/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"
@@ -74,12 +74,12 @@ RegisterInfo g_register_infos[] = {
nullptr,
nullptr},
{DEFINE_GPR(rcx, nullptr),
- {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_INVALID_REGNUM,
+ {dwarf_rcx_x86_64, dwarf_rcx_x86_64, LLDB_REGNUM_GENERIC_ARG1,
LLDB_INVALID_REGNUM, lldb_rcx_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(rdx, nullptr),
- {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_INVALID_REGNUM,
+ {dwarf_rdx_x86_64, dwarf_rdx_x86_64, LLDB_REGNUM_GENERIC_ARG2,
LLDB_INVALID_REGNUM, lldb_rdx_x86_64},
nullptr,
nullptr},
@@ -104,22 +104,22 @@ RegisterInfo g_register_infos[] = {
nullptr,
nullptr},
{DEFINE_GPR(r8, nullptr),
- {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_INVALID_REGNUM,
+ {dwarf_r8_x86_64, dwarf_r8_x86_64, LLDB_REGNUM_GENERIC_ARG3,
LLDB_INVALID_REGNUM, lldb_r8_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r9, nullptr),
- {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_INVALID_REGNUM,
+ {dwarf_r9_x86_64, dwarf_r9_x86_64, LLDB_REGNUM_GENERIC_ARG4,
LLDB_INVALID_REGNUM, lldb_r9_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r10, nullptr),
- {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_INVALID_REGNUM,
+ {dwarf_r10_x86_64, dwarf_r10_x86_64, LLDB_REGNUM_GENERIC_ARG5,
LLDB_INVALID_REGNUM, lldb_r10_x86_64},
nullptr,
nullptr},
{DEFINE_GPR(r11, nullptr),
- {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_INVALID_REGNUM,
+ {dwarf_r11_x86_64, dwarf_r11_x86_64, LLDB_REGNUM_GENERIC_ARG6,
LLDB_INVALID_REGNUM, lldb_r11_x86_64},
nullptr,
nullptr},
diff --git a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp
index fd486f3d0829..e012f9105f31 100644
--- a/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp
+++ b/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/windows/HostThreadWindows.h"
#include "lldb/Host/windows/windows.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private-types.h"
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 7bb7b72eaac1..7d66461c15bc 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -7,25 +7,21 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdlib.h>
-// C++ Includes
#include <mutex>
-// Other libraries and framework includes
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Threading.h"
@@ -61,8 +57,8 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
// the header extension.
const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
- auto data_sp = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(),
- header_size, 0);
+ auto data_sp = FileSystem::Instance().CreateDataBuffer(
+ crash_file->GetPath(), header_size, 0);
if (data_sp && data_sp->GetByteSize() == header_size &&
elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())) {
elf::ELFHeader elf_header;
@@ -81,7 +77,7 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) {
// For now we are just making sure the file exists for a given module
- if (!m_core_module_sp && m_core_file.Exists()) {
+ if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
NULL, NULL, NULL));
@@ -122,10 +118,10 @@ ConstString ProcessElfCore::GetPluginName() { return GetPluginNameStatic(); }
uint32_t ProcessElfCore::GetPluginVersion() { return 1; }
lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(
- const elf::ELFProgramHeader *header) {
- const lldb::addr_t addr = header->p_vaddr;
- FileRange file_range(header->p_offset, header->p_filesz);
- VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range);
+ const elf::ELFProgramHeader &header) {
+ const lldb::addr_t addr = header.p_vaddr;
+ FileRange file_range(header.p_offset, header.p_filesz);
+ VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);
VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
@@ -140,12 +136,12 @@ lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(
// Keep a separate map of permissions that that isn't coalesced so all ranges
// are maintained.
const uint32_t permissions =
- ((header->p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |
- ((header->p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |
- ((header->p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);
+ ((header.p_flags & llvm::ELF::PF_R) ? lldb::ePermissionsReadable : 0u) |
+ ((header.p_flags & llvm::ELF::PF_W) ? lldb::ePermissionsWritable : 0u) |
+ ((header.p_flags & llvm::ELF::PF_X) ? lldb::ePermissionsExecutable : 0u);
m_core_range_infos.Append(
- VMRangeToPermissions::Entry(addr, header->p_memsz, permissions));
+ VMRangeToPermissions::Entry(addr, header.p_memsz, permissions));
return addr;
}
@@ -166,8 +162,8 @@ Status ProcessElfCore::DoLoadCore() {
return error;
}
- const uint32_t num_segments = core->GetProgramHeaderCount();
- if (num_segments == 0) {
+ llvm::ArrayRef<elf::ELFProgramHeader> segments = core->ProgramHeaders();
+ if (segments.size() == 0) {
error.SetErrorString("core file has no segments");
return error;
}
@@ -181,20 +177,17 @@ Status ProcessElfCore::DoLoadCore() {
/// Walk through segments and Thread and Address Map information.
/// PT_NOTE - Contains Thread and Register information
/// PT_LOAD - Contains a contiguous range of Process Address Space
- for (uint32_t i = 1; i <= num_segments; i++) {
- const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i);
- assert(header != NULL);
-
- DataExtractor data = core->GetSegmentDataByIndex(i);
+ for (const elf::ELFProgramHeader &H : segments) {
+ DataExtractor data = core->GetSegmentData(H);
// Parse thread contexts and auxv structure
- if (header->p_type == llvm::ELF::PT_NOTE) {
- if (llvm::Error error = ParseThreadContextsFromNoteSegment(header, data))
+ if (H.p_type == llvm::ELF::PT_NOTE) {
+ if (llvm::Error error = ParseThreadContextsFromNoteSegment(H, data))
return Status(std::move(error));
}
// PT_LOAD segments contains address map
- if (header->p_type == llvm::ELF::PT_LOAD) {
- lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header);
+ if (H.p_type == llvm::ELF::PT_LOAD) {
+ lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(H);
if (vm_addr > last_addr)
ranges_are_sorted = false;
vm_addr = last_addr;
@@ -249,12 +242,11 @@ Status ProcessElfCore::DoLoadCore() {
ModuleSpec exe_module_spec;
exe_module_spec.GetArchitecture() = arch;
exe_module_spec.GetFileSpec().SetFile(
- m_nt_file_entries[0].path.GetCString(), false,
- FileSpec::Style::native);
+ m_nt_file_entries[0].path.GetCString(), FileSpec::Style::native);
if (exe_module_spec.GetFileSpec()) {
exe_module_sp = GetTarget().GetSharedModule(exe_module_spec);
if (exe_module_sp)
- GetTarget().SetExecutableModule(exe_module_sp, false);
+ GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
}
}
}
@@ -715,8 +707,8 @@ llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
/// A note segment consists of one or more NOTE entries, but their types and
/// meaning differ depending on the OS.
llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
- const elf::ELFProgramHeader *segment_header, DataExtractor segment_data) {
- assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
+ const elf::ELFProgramHeader &segment_header, DataExtractor segment_data) {
+ assert(segment_header.p_type == llvm::ELF::PT_NOTE);
auto notes_or_error = parseSegment(segment_data);
if(!notes_or_error)
@@ -744,8 +736,7 @@ uint32_t ProcessElfCore::GetNumThreadContexts() {
}
ArchSpec ProcessElfCore::GetArchitecture() {
- ArchSpec arch;
- m_core_module_sp->GetObjectFile()->GetArchitecture(arch);
+ ArchSpec arch = m_core_module_sp->GetObjectFile()->GetArchitecture();
ArchSpec target_arch = GetTarget().GetArchitecture();
arch.MergeFrom(target_arch);
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h
index 325c0152e028..2c7268662fef 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.h
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -17,13 +17,9 @@
#ifndef liblldb_ProcessElfCore_h_
#define liblldb_ProcessElfCore_h_
-// C Includes
-// C++ Includes
#include <list>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
@@ -140,7 +136,7 @@ private:
// For ProcessElfCore only
//------------------------------------------------------------------
typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
- typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1>
+ typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange>
VMRangeToFileOffset;
typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t>
VMRangeToPermissions;
@@ -170,7 +166,7 @@ private:
// Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
llvm::Error ParseThreadContextsFromNoteSegment(
- const elf::ELFProgramHeader *segment_header,
+ const elf::ELFProgramHeader &segment_header,
lldb_private::DataExtractor segment_data);
// Returns number of thread contexts stored in the core file
@@ -178,7 +174,7 @@ private:
// Parse a contiguous address range of the process from LOAD segment
lldb::addr_t
- AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
+ AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);
llvm::Expected<std::vector<lldb_private::CoreNote>>
parseSegment(const lldb_private::DataExtractor &segment);
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
index 0d683153d9ed..80c6c0207a1e 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm.cpp
@@ -9,8 +9,8 @@
#include "RegisterContextPOSIXCore_arm.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index 919f8901d39a..017646b44b5c 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -9,8 +9,8 @@
#include "RegisterContextPOSIXCore_arm64.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
index 532a1f5c0831..beeb9b666ccd 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_mips64.cpp
@@ -9,8 +9,8 @@
#include "RegisterContextPOSIXCore_mips64.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
index 8670e341a277..d4f86b354784 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -9,9 +9,9 @@
#include "RegisterContextPOSIXCore_powerpc.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp
index 2237e72353ac..8116a1c7ea57 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_ppc64le.cpp
@@ -9,9 +9,9 @@
#include "RegisterContextPOSIXCore_ppc64le.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
#include "Plugins/Process/elf-core/RegisterUtilities.h"
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
index f0edbf1ea854..875bb1647281 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
@@ -9,9 +9,9 @@
#include "RegisterContextPOSIXCore_s390x.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index a1f26d52444b..27295492f43d 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -8,9 +8,9 @@
//===----------------------------------------------------------------------===//
#include "RegisterContextPOSIXCore_x86_64.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
using namespace lldb_private;
diff --git a/source/Plugins/Process/gdb-remote/CMakeLists.txt b/source/Plugins/Process/gdb-remote/CMakeLists.txt
index 7ae25f83c5f8..4eb5291d54d5 100644
--- a/source/Plugins/Process/gdb-remote/CMakeLists.txt
+++ b/source/Plugins/Process/gdb-remote/CMakeLists.txt
@@ -15,6 +15,8 @@ add_lldb_library(lldbPluginProcessGDBRemote PLUGIN
GDBRemoteClientBase.cpp
GDBRemoteCommunication.cpp
GDBRemoteCommunicationClient.cpp
+ GDBRemoteCommunicationHistory.cpp
+ GDBRemoteCommunicationReplayServer.cpp
GDBRemoteCommunicationServer.cpp
GDBRemoteCommunicationServerCommon.cpp
GDBRemoteCommunicationServerLLGS.cpp
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index 4e20b56fb111..a3a4aa053261 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -379,7 +379,7 @@ void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
m_comm.m_interrupt_time = steady_clock::now();
}
- m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; });
+ m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
m_did_interrupt = true;
}
m_acquired = true;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index c335b6002861..72c1314a7c94 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -9,21 +9,22 @@
#include "GDBRemoteCommunication.h"
-// C Includes
+#include <future>
#include <limits.h>
#include <string.h>
#include <sys/stat.h>
-// C++ Includes
-// Other libraries and framework includes
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Host/common/TCPSocket.h"
+#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/FileSpec.h"
@@ -33,7 +34,6 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ScopedPrinter.h"
-// Project includes
#include "ProcessGDBRemoteLog.h"
#if defined(__APPLE__)
@@ -42,7 +42,8 @@
#define DEBUGSERVER_BASENAME "lldb-server"
#endif
-#if defined(HAVE_LIBCOMPRESSION)
+#if defined(__APPLE__)
+#define HAVE_LIBCOMPRESSION
#include <compression.h>
#endif
@@ -54,78 +55,6 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-GDBRemoteCommunication::History::History(uint32_t size)
- : m_packets(), m_curr_idx(0), m_total_packet_count(0),
- m_dumped_to_log(false) {
- m_packets.resize(size);
-}
-
-GDBRemoteCommunication::History::~History() {}
-
-void GDBRemoteCommunication::History::AddPacket(char packet_char,
- PacketType type,
- uint32_t bytes_transmitted) {
- const size_t size = m_packets.size();
- if (size > 0) {
- const uint32_t idx = GetNextIndex();
- m_packets[idx].packet.assign(1, packet_char);
- m_packets[idx].type = type;
- m_packets[idx].bytes_transmitted = bytes_transmitted;
- m_packets[idx].packet_idx = m_total_packet_count;
- m_packets[idx].tid = llvm::get_threadid();
- }
-}
-
-void GDBRemoteCommunication::History::AddPacket(const std::string &src,
- uint32_t src_len,
- PacketType type,
- uint32_t bytes_transmitted) {
- const size_t size = m_packets.size();
- if (size > 0) {
- const uint32_t idx = GetNextIndex();
- m_packets[idx].packet.assign(src, 0, src_len);
- m_packets[idx].type = type;
- m_packets[idx].bytes_transmitted = bytes_transmitted;
- m_packets[idx].packet_idx = m_total_packet_count;
- m_packets[idx].tid = llvm::get_threadid();
- }
-}
-
-void GDBRemoteCommunication::History::Dump(Stream &strm) const {
- const uint32_t size = GetNumPacketsInHistory();
- const uint32_t first_idx = GetFirstSavedPacketIndex();
- const uint32_t stop_idx = m_curr_idx + size;
- for (uint32_t i = first_idx; i < stop_idx; ++i) {
- const uint32_t idx = NormalizeIndex(i);
- const Entry &entry = m_packets[idx];
- if (entry.type == ePacketTypeInvalid || entry.packet.empty())
- break;
- strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
- entry.packet_idx, entry.tid, entry.bytes_transmitted,
- (entry.type == ePacketTypeSend) ? "send" : "read",
- entry.packet.c_str());
- }
-}
-
-void GDBRemoteCommunication::History::Dump(Log *log) const {
- if (log && !m_dumped_to_log) {
- m_dumped_to_log = true;
- const uint32_t size = GetNumPacketsInHistory();
- const uint32_t first_idx = GetFirstSavedPacketIndex();
- const uint32_t stop_idx = m_curr_idx + size;
- for (uint32_t i = first_idx; i < stop_idx; ++i) {
- const uint32_t idx = NormalizeIndex(i);
- const Entry &entry = m_packets[idx];
- if (entry.type == ePacketTypeInvalid || entry.packet.empty())
- break;
- log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
- entry.packet_idx, entry.tid, entry.bytes_transmitted,
- (entry.type == ePacketTypeSend) ? "send" : "read",
- entry.packet.c_str());
- }
- }
-}
-
//----------------------------------------------------------------------
// GDBRemoteCommunication constructor
//----------------------------------------------------------------------
@@ -139,7 +68,10 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
#endif
m_echo_number(0), m_supports_qEcho(eLazyBoolCalculate), m_history(512),
m_send_acks(true), m_compression_type(CompressionType::None),
- m_listen_url() {
+ m_listen_url(), m_decompression_scratch_type(CompressionType::None),
+ m_decompression_scratch(nullptr) {
+ // Unused unless HAVE_LIBCOMPRESSION is defined.
+ (void)m_decompression_scratch_type;
}
//----------------------------------------------------------------------
@@ -150,6 +82,9 @@ GDBRemoteCommunication::~GDBRemoteCommunication() {
Disconnect();
}
+ if (m_decompression_scratch)
+ free (m_decompression_scratch);
+
// Stop the communications read thread which is used to parse all incoming
// packets. This function will block until the read thread returns.
if (m_read_thread_enabled)
@@ -172,7 +107,8 @@ size_t GDBRemoteCommunication::SendAck() {
const size_t bytes_written = Write(&ch, 1, status, NULL);
if (log)
log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
- m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written);
+ m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend,
+ bytes_written);
return bytes_written;
}
@@ -183,26 +119,31 @@ size_t GDBRemoteCommunication::SendNack() {
const size_t bytes_written = Write(&ch, 1, status, NULL);
if (log)
log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
- m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written);
+ m_history.AddPacket(ch, GDBRemoteCommunicationHistory::ePacketTypeSend,
+ bytes_written);
return bytes_written;
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
- if (IsConnected()) {
StreamString packet(0, 4, eByteOrderBig);
-
packet.PutChar('$');
packet.Write(payload.data(), payload.size());
packet.PutChar('#');
packet.PutHex8(CalculcateChecksum(payload));
+ std::string packet_str = packet.GetString();
+
+ return SendRawPacketNoLock(packet_str);
+}
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunication::SendRawPacketNoLock(llvm::StringRef packet,
+ bool skip_ack) {
+ if (IsConnected()) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
ConnectionStatus status = eConnectionStatusSuccess;
- // TODO: Don't shimmy through a std::string, just use StringRef.
- std::string packet_str = packet.GetString();
- const char *packet_data = packet_str.c_str();
- const size_t packet_length = packet.GetSize();
+ const char *packet_data = packet.data();
+ const size_t packet_length = packet.size();
size_t bytes_written = Write(packet_data, packet_length, status, NULL);
if (log) {
size_t binary_start_offset = 0;
@@ -241,11 +182,12 @@ GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
(int)packet_length, packet_data);
}
- m_history.AddPacket(packet.GetString(), packet_length,
- History::ePacketTypeSend, bytes_written);
+ m_history.AddPacket(packet.str(), packet_length,
+ GDBRemoteCommunicationHistory::ePacketTypeSend,
+ bytes_written);
if (bytes_written == packet_length) {
- if (GetSendAcks())
+ if (!skip_ack && GetSendAcks())
return GetAck();
else
return PacketResult::Success;
@@ -597,7 +539,7 @@ bool GDBRemoteCommunication::DecompressPacket() {
size_t decompressed_bytes = 0;
if (decompressed_bufsize != ULONG_MAX) {
- decompressed_buffer = (uint8_t *)malloc(decompressed_bufsize + 1);
+ decompressed_buffer = (uint8_t *)malloc(decompressed_bufsize);
if (decompressed_buffer == nullptr) {
m_bytes.erase(0, size_of_first_packet);
return false;
@@ -605,11 +547,10 @@ bool GDBRemoteCommunication::DecompressPacket() {
}
#if defined(HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so check that compression_decode_buffer() is
- // available
if (m_compression_type == CompressionType::ZlibDeflate ||
m_compression_type == CompressionType::LZFSE ||
- m_compression_type == CompressionType::LZ4) {
+ m_compression_type == CompressionType::LZ4 ||
+ m_compression_type == CompressionType::LZMA) {
compression_algorithm compression_type;
if (m_compression_type == CompressionType::LZFSE)
compression_type = COMPRESSION_LZFSE;
@@ -620,16 +561,33 @@ bool GDBRemoteCommunication::DecompressPacket() {
else if (m_compression_type == CompressionType::LZMA)
compression_type = COMPRESSION_LZMA;
- // If we have the expected size of the decompressed payload, we can
- // allocate the right-sized buffer and do it. If we don't have that
- // information, we'll need to try decoding into a big buffer and if the
- // buffer wasn't big enough, increase it and try again.
+ if (m_decompression_scratch_type != m_compression_type) {
+ if (m_decompression_scratch) {
+ free (m_decompression_scratch);
+ m_decompression_scratch = nullptr;
+ }
+ size_t scratchbuf_size = 0;
+ if (m_compression_type == CompressionType::LZFSE)
+ scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZFSE);
+ else if (m_compression_type == CompressionType::LZ4)
+ scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZ4_RAW);
+ else if (m_compression_type == CompressionType::ZlibDeflate)
+ scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_ZLIB);
+ else if (m_compression_type == CompressionType::LZMA)
+ scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZMA);
+ else if (m_compression_type == CompressionType::LZFSE)
+ scratchbuf_size = compression_decode_scratch_buffer_size (COMPRESSION_LZFSE);
+ if (scratchbuf_size > 0) {
+ m_decompression_scratch = (void*) malloc (scratchbuf_size);
+ m_decompression_scratch_type = m_compression_type;
+ }
+ }
if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {
decompressed_bytes = compression_decode_buffer(
- decompressed_buffer, decompressed_bufsize + 10,
- (uint8_t *)unescaped_content.data(), unescaped_content.size(), NULL,
- compression_type);
+ decompressed_buffer, decompressed_bufsize,
+ (uint8_t *)unescaped_content.data(), unescaped_content.size(),
+ m_decompression_scratch, compression_type);
}
}
#endif
@@ -721,7 +679,7 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
// Size of packet before it is decompressed, for logging purposes
size_t original_packet_size = m_bytes.size();
if (CompressionIsEnabled()) {
- if (DecompressPacket() == false) {
+ if (!DecompressPacket()) {
packet.Clear();
return GDBRemoteCommunication::PacketType::Standard;
}
@@ -860,7 +818,8 @@ GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
}
}
- m_history.AddPacket(m_bytes, total_length, History::ePacketTypeRecv,
+ m_history.AddPacket(m_bytes, total_length,
+ GDBRemoteCommunicationHistory::ePacketTypeRecv,
total_length);
// Clear packet_str in case there is some existing data in it.
@@ -997,7 +956,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
// debugserver to use and use it if we do.
const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
if (env_debugserver_path) {
- debugserver_file_spec.SetFile(env_debugserver_path, false,
+ debugserver_file_spec.SetFile(env_debugserver_path,
FileSpec::Style::native);
if (log)
log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set "
@@ -1005,13 +964,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
__FUNCTION__, env_debugserver_path);
} else
debugserver_file_spec = g_debugserver_file_spec;
- bool debugserver_exists = debugserver_file_spec.Exists();
+ bool debugserver_exists =
+ FileSystem::Instance().Exists(debugserver_file_spec);
if (!debugserver_exists) {
// The debugserver binary is in the LLDB.framework/Resources directory.
debugserver_file_spec = HostInfo::GetSupportExeDir();
if (debugserver_file_spec) {
debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
- debugserver_exists = debugserver_file_spec.Exists();
+ debugserver_exists = FileSystem::Instance().Exists(debugserver_file_spec);
if (debugserver_exists) {
if (log)
log->Printf(
@@ -1074,7 +1034,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
debugserver_args.AppendArgument(llvm::StringRef("--setsid"));
}
- llvm::SmallString<PATH_MAX> named_pipe_path;
+ llvm::SmallString<128> named_pipe_path;
// socket_pipe is used by debug server to communicate back either
// TCP port or domain socket name which it listens on.
// The second purpose of the pipe to serve as a synchronization point -
@@ -1114,9 +1074,9 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
__FUNCTION__, error.AsCString());
return error;
}
- int write_fd = socket_pipe.GetWriteFileDescriptor();
+ pipe_t write = socket_pipe.GetWritePipe();
debugserver_args.AppendArgument(llvm::StringRef("--pipe"));
- debugserver_args.AppendArgument(llvm::to_string(write_fd));
+ debugserver_args.AppendArgument(llvm::to_string(write));
launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
#endif
} else {
@@ -1304,6 +1264,42 @@ Status GDBRemoteCommunication::StartDebugserverProcess(
void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
+void GDBRemoteCommunication::SetHistoryStream(llvm::raw_ostream *strm) {
+ m_history.SetStream(strm);
+};
+
+llvm::Error
+GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client,
+ GDBRemoteCommunication &server) {
+ const bool child_processes_inherit = false;
+ const int backlog = 5;
+ TCPSocket listen_socket(true, child_processes_inherit);
+ if (llvm::Error error =
+ listen_socket.Listen("127.0.0.1:0", backlog).ToError())
+ return error;
+
+ Socket *accept_socket;
+ std::future<Status> accept_status = std::async(
+ std::launch::async, [&] { return listen_socket.Accept(accept_socket); });
+
+ llvm::SmallString<32> remote_addr;
+ llvm::raw_svector_ostream(remote_addr)
+ << "connect://localhost:" << listen_socket.GetLocalPortNumber();
+
+ std::unique_ptr<ConnectionFileDescriptor> conn_up(
+ new ConnectionFileDescriptor());
+ if (conn_up->Connect(remote_addr, nullptr) != lldb::eConnectionStatusSuccess)
+ return llvm::make_error<llvm::StringError>("Unable to connect",
+ llvm::inconvertibleErrorCode());
+
+ client.SetConnection(conn_up.release());
+ if (llvm::Error error = accept_status.get().ToError())
+ return error;
+
+ server.SetConnection(new ConnectionFileDescriptor(accept_socket));
+ return llvm::Error::success();
+}
+
GDBRemoteCommunication::ScopedTimeout::ScopedTimeout(
GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout)
: m_gdb_comm(gdb_comm), m_timeout_modified(false) {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 67796e4c61ef..369eb25b1dfa 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -10,24 +10,21 @@
#ifndef liblldb_GDBRemoteCommunication_h_
#define liblldb_GDBRemoteCommunication_h_
-// C Includes
-// C++ Includes
+#include "GDBRemoteCommunicationHistory.h"
+
#include <condition_variable>
#include <mutex>
#include <queue>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Communication.h"
-#include "lldb/Core/Listener.h"
#include "lldb/Host/HostThread.h"
-#include "lldb/Host/Predicate.h"
#include "lldb/Utility/Args.h"
-#include "lldb/lldb-public.h"
-
+#include "lldb/Utility/Listener.h"
+#include "lldb/Utility/Predicate.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
+#include "lldb/lldb-public.h"
namespace lldb_private {
namespace process_gdb_remote {
@@ -140,86 +137,16 @@ public:
// fork/exec to avoid having to connect/accept
void DumpHistory(Stream &strm);
+ void SetHistoryStream(llvm::raw_ostream *strm);
-protected:
- class History {
- public:
- enum PacketType {
- ePacketTypeInvalid = 0,
- ePacketTypeSend,
- ePacketTypeRecv
- };
-
- struct Entry {
- Entry()
- : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
- packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
-
- void Clear() {
- packet.clear();
- type = ePacketTypeInvalid;
- bytes_transmitted = 0;
- packet_idx = 0;
- tid = LLDB_INVALID_THREAD_ID;
- }
- std::string packet;
- PacketType type;
- uint32_t bytes_transmitted;
- uint32_t packet_idx;
- lldb::tid_t tid;
- };
-
- History(uint32_t size);
-
- ~History();
-
- // For single char packets for ack, nack and /x03
- void AddPacket(char packet_char, PacketType type,
- uint32_t bytes_transmitted);
-
- void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
- uint32_t bytes_transmitted);
-
- void Dump(Stream &strm) const;
-
- void Dump(Log *log) const;
-
- bool DidDumpToLog() const { return m_dumped_to_log; }
-
- protected:
- uint32_t GetFirstSavedPacketIndex() const {
- if (m_total_packet_count < m_packets.size())
- return 0;
- else
- return m_curr_idx + 1;
- }
-
- uint32_t GetNumPacketsInHistory() const {
- if (m_total_packet_count < m_packets.size())
- return m_total_packet_count;
- else
- return (uint32_t)m_packets.size();
- }
-
- uint32_t GetNextIndex() {
- ++m_total_packet_count;
- const uint32_t idx = m_curr_idx;
- m_curr_idx = NormalizeIndex(idx + 1);
- return idx;
- }
-
- uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); }
-
- std::vector<Entry> m_packets;
- uint32_t m_curr_idx;
- uint32_t m_total_packet_count;
- mutable bool m_dumped_to_log;
- };
+ static llvm::Error ConnectLocally(GDBRemoteCommunication &client,
+ GDBRemoteCommunication &server);
+protected:
std::chrono::seconds m_packet_timeout;
uint32_t m_echo_number;
LazyBool m_supports_qEcho;
- History m_history;
+ GDBRemoteCommunicationHistory m_history;
bool m_send_acks;
bool m_is_platform; // Set to true if this class represents a platform,
// false if this class represents a debug session for
@@ -228,6 +155,8 @@ protected:
CompressionType m_compression_type;
PacketResult SendPacketNoLock(llvm::StringRef payload);
+ PacketResult SendRawPacketNoLock(llvm::StringRef payload,
+ bool skip_ack = false);
PacketResult ReadPacket(StringExtractorGDBRemote &response,
Timeout<std::micro> timeout, bool sync_on_timeout);
@@ -289,6 +218,9 @@ private:
HostThread m_listen_thread;
std::string m_listen_url;
+ CompressionType m_decompression_scratch_type;
+ void *m_decompression_scratch;
+
DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);
};
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index c8b59d5d236b..1e12ea6b2d56 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -9,17 +9,13 @@
#include "GDBRemoteCommunicationClient.h"
-// C Includes
#include <math.h>
#include <sys/stat.h>
-// C++ Includes
#include <numeric>
#include <sstream>
-// Other libraries and framework includes
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
@@ -31,9 +27,9 @@
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
-// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "lldb/Host/Config.h"
@@ -41,7 +37,8 @@
#include "llvm/ADT/StringSwitch.h"
-#if defined(HAVE_LIBCOMPRESSION)
+#if defined(__APPLE__)
+#define HAVE_LIBCOMPRESSION
#include <compression.h>
#endif
@@ -256,10 +253,7 @@ bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
m_attach_or_wait_reply = eLazyBoolYes;
}
}
- if (m_attach_or_wait_reply == eLazyBoolYes)
- return true;
- else
- return false;
+ return m_attach_or_wait_reply == eLazyBoolYes;
}
bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
@@ -273,14 +267,11 @@ bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
m_prepare_for_reg_writing_reply = eLazyBoolYes;
}
}
- if (m_prepare_for_reg_writing_reply == eLazyBoolYes)
- return true;
- else
- return false;
+ return m_prepare_for_reg_writing_reply == eLazyBoolYes;
}
void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
- if (did_exec == false) {
+ if (!did_exec) {
// Hard reset everything, this is when we first connect to a GDB server
m_supports_not_sending_acks = eLazyBoolCalculate;
m_supports_thread_suffix = eLazyBoolCalculate;
@@ -749,7 +740,7 @@ lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
bool sequence_mutex_unavailable;
size_t size;
size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable);
- if (size && sequence_mutex_unavailable == false) {
+ if (size && !sequence_mutex_unavailable) {
m_curr_pid = thread_ids.front();
m_curr_pid_is_valid = eLazyBoolYes;
return m_curr_pid;
@@ -843,8 +834,8 @@ int GDBRemoteCommunicationClient::SendEnvironmentPacket(
if (name_equal_value && name_equal_value[0]) {
StreamString packet;
bool send_hex_encoding = false;
- for (const char *p = name_equal_value;
- *p != '\0' && send_hex_encoding == false; ++p) {
+ for (const char *p = name_equal_value; *p != '\0' && !send_hex_encoding;
+ ++p) {
if (isprint(*p)) {
switch (*p) {
case '$':
@@ -1134,6 +1125,9 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS));
if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) {
+ // host info computation can require DNS traffic and shelling out to external processes.
+ // Increase the timeout to account for that.
+ ScopedTimeout timeout(*this, seconds(10));
m_qHostInfo_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse("qHostInfo", response, false) ==
@@ -1686,12 +1680,17 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
m_supports_watchpoint_support_info = eLazyBoolYes;
llvm::StringRef name;
llvm::StringRef value;
+ bool found_num_field = false;
while (response.GetNameColonValue(name, value)) {
if (name.equals("num")) {
value.getAsInteger(0, m_num_supported_hardware_watchpoints);
num = m_num_supported_hardware_watchpoints;
+ found_num_field = true;
}
}
+ if (!found_num_field) {
+ m_supports_watchpoint_support_info = eLazyBoolNo;
+ }
} else {
m_supports_watchpoint_support_info = eLazyBoolNo;
}
@@ -1724,12 +1723,10 @@ GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
// On targets like MIPS and ppc64le, watchpoint exceptions are always
// generated before the instruction is executed. The connected target may
// not support qHostInfo or qWatchpointSupportInfo packets.
- if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
- atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el ||
- atype == llvm::Triple::ppc64le)
- after = false;
- else
- after = true;
+ after =
+ !(atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
+ atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el ||
+ atype == llvm::Triple::ppc64le);
} else {
// For MIPS and ppc64le, set m_watchpoints_trigger_after_instruction to
// eLazyBoolNo if it is not calculated before.
@@ -1815,7 +1812,7 @@ bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
return false;
std::string cwd;
response.GetHexByteString(cwd);
- working_dir.SetFile(cwd, false, GetHostArchitecture().GetTriple());
+ working_dir.SetFile(cwd, GetHostArchitecture().GetTriple());
return !cwd.empty();
}
return false;
@@ -1925,8 +1922,7 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
// characters in a process name
std::string name;
extractor.GetHexByteString(name);
- process_info.GetExecutableFile().SetFile(name, false,
- FileSpec::Style::native);
+ process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
} else if (name.equals("cputype")) {
value.getAsInteger(0, cpu);
} else if (name.equals("cpusubtype")) {
@@ -3559,7 +3555,7 @@ bool GDBRemoteCommunicationClient::GetModuleInfo(
StringExtractor extractor(value);
std::string path;
extractor.GetHexByteString(path);
- module_spec.GetFileSpec() = FileSpec(path, false, arch_spec.GetTriple());
+ module_spec.GetFileSpec() = FileSpec(path, arch_spec.GetTriple());
}
}
@@ -3595,8 +3591,7 @@ ParseModuleSpec(StructuredData::Dictionary *dict) {
if (!dict->GetValueForKeyAsString("file_path", string))
return llvm::None;
- result.GetFileSpec() =
- FileSpec(string, false, result.GetArchitecture().GetTriple());
+ result.GetFileSpec() = FileSpec(string, result.GetArchitecture().GetTriple());
return result;
}
@@ -3774,7 +3769,7 @@ void GDBRemoteCommunicationClient::ServeSymbolLookups(
// Is this the initial qSymbol:: packet?
bool first_qsymbol_query = true;
- if (m_supports_qSymbol && m_qSymbol_requests_done == false) {
+ if (m_supports_qSymbol && !m_qSymbol_requests_done) {
Lock lock(*this, false);
if (lock) {
StreamString packet;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index cf1d249768d7..37d53ab425f5 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -12,8 +12,6 @@
#include "GDBRemoteClientBase.h"
-// C Includes
-// C++ Includes
#include <chrono>
#include <map>
#include <mutex>
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
new file mode 100644
index 000000000000..69b13f2a3acb
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.cpp
@@ -0,0 +1,143 @@
+//===-- GDBRemoteCommunicationHistory.cpp -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GDBRemoteCommunicationHistory.h"
+
+// Other libraries and framework includes
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Log.h"
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+
+void GDBRemoteCommunicationHistory::Entry::Serialize(raw_ostream &strm) const {
+ yaml::Output yout(strm);
+ yout << const_cast<GDBRemoteCommunicationHistory::Entry &>(*this);
+ strm.flush();
+}
+
+GDBRemoteCommunicationHistory::GDBRemoteCommunicationHistory(uint32_t size)
+ : m_packets(), m_curr_idx(0), m_total_packet_count(0),
+ m_dumped_to_log(false) {
+ if (size)
+ m_packets.resize(size);
+}
+
+GDBRemoteCommunicationHistory::~GDBRemoteCommunicationHistory() {}
+
+void GDBRemoteCommunicationHistory::AddPacket(char packet_char, PacketType type,
+ uint32_t bytes_transmitted) {
+ const size_t size = m_packets.size();
+ if (size == 0)
+ return;
+
+ const uint32_t idx = GetNextIndex();
+ m_packets[idx].packet.data.assign(1, packet_char);
+ m_packets[idx].type = type;
+ m_packets[idx].bytes_transmitted = bytes_transmitted;
+ m_packets[idx].packet_idx = m_total_packet_count;
+ m_packets[idx].tid = llvm::get_threadid();
+ if (m_stream && type == ePacketTypeRecv)
+ m_packets[idx].Serialize(*m_stream);
+}
+
+void GDBRemoteCommunicationHistory::AddPacket(const std::string &src,
+ uint32_t src_len, PacketType type,
+ uint32_t bytes_transmitted) {
+ const size_t size = m_packets.size();
+ if (size == 0)
+ return;
+
+ const uint32_t idx = GetNextIndex();
+ m_packets[idx].packet.data.assign(src, 0, src_len);
+ m_packets[idx].type = type;
+ m_packets[idx].bytes_transmitted = bytes_transmitted;
+ m_packets[idx].packet_idx = m_total_packet_count;
+ m_packets[idx].tid = llvm::get_threadid();
+ if (m_stream && type == ePacketTypeRecv)
+ m_packets[idx].Serialize(*m_stream);
+}
+
+void GDBRemoteCommunicationHistory::Dump(Stream &strm) const {
+ const uint32_t size = GetNumPacketsInHistory();
+ const uint32_t first_idx = GetFirstSavedPacketIndex();
+ const uint32_t stop_idx = m_curr_idx + size;
+ for (uint32_t i = first_idx; i < stop_idx; ++i) {
+ const uint32_t idx = NormalizeIndex(i);
+ const Entry &entry = m_packets[idx];
+ if (entry.type == ePacketTypeInvalid || entry.packet.data.empty())
+ break;
+ strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
+ entry.packet_idx, entry.tid, entry.bytes_transmitted,
+ (entry.type == ePacketTypeSend) ? "send" : "read",
+ entry.packet.data.c_str());
+ }
+}
+
+void GDBRemoteCommunicationHistory::Dump(Log *log) const {
+ if (!log || m_dumped_to_log)
+ return;
+
+ m_dumped_to_log = true;
+ const uint32_t size = GetNumPacketsInHistory();
+ const uint32_t first_idx = GetFirstSavedPacketIndex();
+ const uint32_t stop_idx = m_curr_idx + size;
+ for (uint32_t i = first_idx; i < stop_idx; ++i) {
+ const uint32_t idx = NormalizeIndex(i);
+ const Entry &entry = m_packets[idx];
+ if (entry.type == ePacketTypeInvalid || entry.packet.data.empty())
+ break;
+ log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
+ entry.packet_idx, entry.tid, entry.bytes_transmitted,
+ (entry.type == ePacketTypeSend) ? "send" : "read",
+ entry.packet.data.c_str());
+ }
+}
+
+void yaml::ScalarEnumerationTraits<GDBRemoteCommunicationHistory::PacketType>::
+ enumeration(IO &io, GDBRemoteCommunicationHistory::PacketType &value) {
+ io.enumCase(value, "Invalid",
+ GDBRemoteCommunicationHistory::ePacketTypeInvalid);
+ io.enumCase(value, "Send", GDBRemoteCommunicationHistory::ePacketTypeSend);
+ io.enumCase(value, "Recv", GDBRemoteCommunicationHistory::ePacketTypeRecv);
+}
+
+void yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::
+ output(const GDBRemoteCommunicationHistory::Entry::BinaryData &Val, void *,
+ raw_ostream &Out) {
+ Out << toHex(Val.data);
+}
+
+StringRef
+yaml::ScalarTraits<GDBRemoteCommunicationHistory::Entry::BinaryData>::input(
+ StringRef Scalar, void *,
+ GDBRemoteCommunicationHistory::Entry::BinaryData &Val) {
+ Val.data = fromHex(Scalar);
+ return {};
+}
+
+void yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::mapping(
+ IO &io, GDBRemoteCommunicationHistory::Entry &Entry) {
+ io.mapRequired("packet", Entry.packet);
+ io.mapRequired("type", Entry.type);
+ io.mapRequired("bytes", Entry.bytes_transmitted);
+ io.mapRequired("index", Entry.packet_idx);
+ io.mapRequired("tid", Entry.tid);
+}
+
+StringRef yaml::MappingTraits<GDBRemoteCommunicationHistory::Entry>::validate(
+ IO &io, GDBRemoteCommunicationHistory::Entry &Entry) {
+ if (Entry.bytes_transmitted != Entry.packet.data.size())
+ return "BinaryData size doesn't match bytes transmitted";
+
+ return {};
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
new file mode 100644
index 000000000000..d0ca6a0235c9
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationHistory.h
@@ -0,0 +1,156 @@
+//===-- GDBRemoteCommunicationHistory.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_GDBRemoteCommunicationHistory_h_
+#define liblldb_GDBRemoteCommunicationHistory_h_
+
+#include <string>
+#include <vector>
+
+#include "lldb/lldb-public.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace lldb_private {
+namespace process_gdb_remote {
+
+/// The history keeps a circular buffer of GDB remote packets. The history is
+/// used for logging and replaying GDB remote packets.
+class GDBRemoteCommunicationHistory {
+public:
+ friend llvm::yaml::MappingTraits<GDBRemoteCommunicationHistory>;
+
+ enum PacketType { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv };
+
+ /// Entry in the ring buffer containing the packet data, its type, size and
+ /// index. Entries can be serialized to file.
+ struct Entry {
+ Entry()
+ : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
+ packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
+
+ void Clear() {
+ packet.data.clear();
+ type = ePacketTypeInvalid;
+ bytes_transmitted = 0;
+ packet_idx = 0;
+ tid = LLDB_INVALID_THREAD_ID;
+ }
+
+ struct BinaryData {
+ std::string data;
+ };
+
+ void Serialize(llvm::raw_ostream &strm) const;
+
+ BinaryData packet;
+ PacketType type;
+ uint32_t bytes_transmitted;
+ uint32_t packet_idx;
+ lldb::tid_t tid;
+ };
+
+ GDBRemoteCommunicationHistory(uint32_t size = 0);
+
+ ~GDBRemoteCommunicationHistory();
+
+ // For single char packets for ack, nack and /x03
+ void AddPacket(char packet_char, PacketType type, uint32_t bytes_transmitted);
+
+ void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
+ uint32_t bytes_transmitted);
+
+ void Dump(Stream &strm) const;
+ void Dump(Log *log) const;
+ bool DidDumpToLog() const { return m_dumped_to_log; }
+
+ void SetStream(llvm::raw_ostream *strm) { m_stream = strm; }
+
+private:
+ uint32_t GetFirstSavedPacketIndex() const {
+ if (m_total_packet_count < m_packets.size())
+ return 0;
+ else
+ return m_curr_idx + 1;
+ }
+
+ uint32_t GetNumPacketsInHistory() const {
+ if (m_total_packet_count < m_packets.size())
+ return m_total_packet_count;
+ else
+ return (uint32_t)m_packets.size();
+ }
+
+ uint32_t GetNextIndex() {
+ ++m_total_packet_count;
+ const uint32_t idx = m_curr_idx;
+ m_curr_idx = NormalizeIndex(idx + 1);
+ return idx;
+ }
+
+ uint32_t NormalizeIndex(uint32_t i) const {
+ return m_packets.empty() ? 0 : i % m_packets.size();
+ }
+
+ std::vector<Entry> m_packets;
+ uint32_t m_curr_idx;
+ uint32_t m_total_packet_count;
+ mutable bool m_dumped_to_log;
+ llvm::raw_ostream *m_stream = nullptr;
+};
+
+} // namespace process_gdb_remote
+} // namespace lldb_private
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(
+ lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry)
+
+namespace llvm {
+namespace yaml {
+
+template <>
+struct ScalarEnumerationTraits<lldb_private::process_gdb_remote::
+ GDBRemoteCommunicationHistory::PacketType> {
+ static void enumeration(IO &io,
+ lldb_private::process_gdb_remote::
+ GDBRemoteCommunicationHistory::PacketType &value);
+};
+
+template <>
+struct ScalarTraits<lldb_private::process_gdb_remote::
+ GDBRemoteCommunicationHistory::Entry::BinaryData> {
+ static void output(const lldb_private::process_gdb_remote::
+ GDBRemoteCommunicationHistory::Entry::BinaryData &,
+ void *, raw_ostream &);
+
+ static StringRef
+ input(StringRef, void *,
+ lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry::
+ BinaryData &);
+
+ static QuotingType mustQuote(StringRef S) { return QuotingType::None; }
+};
+
+template <>
+struct MappingTraits<
+ lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry> {
+ static void
+ mapping(IO &io,
+ lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry
+ &Entry);
+
+ static StringRef validate(
+ IO &io,
+ lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry &);
+};
+
+} // namespace yaml
+} // namespace llvm
+
+#endif // liblldb_GDBRemoteCommunicationHistory_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
new file mode 100644
index 000000000000..6a78eb20992e
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp
@@ -0,0 +1,204 @@
+//===-- GDBRemoteCommunicationReplayServer.cpp ------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <errno.h>
+
+#include "lldb/Host/Config.h"
+
+#include "GDBRemoteCommunicationReplayServer.h"
+#include "ProcessGDBRemoteLog.h"
+
+// C Includes
+// C++ Includes
+#include <cstring>
+
+// Project includes
+#include "lldb/Host/ThreadLauncher.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/StringExtractorGDBRemote.h"
+
+using namespace llvm;
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+
+GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer()
+ : GDBRemoteCommunication("gdb-remote.server",
+ "gdb-remote.server.rx_packet"),
+ m_async_broadcaster(nullptr, "lldb.gdb-remote.server.async-broadcaster"),
+ m_async_listener_sp(
+ Listener::MakeListener("lldb.gdb-remote.server.async-listener")),
+ m_async_thread_state_mutex(), m_skip_acks(false) {
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
+ "async thread continue");
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
+ "async thread should exit");
+
+ const uint32_t async_event_mask =
+ eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
+ m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster,
+ async_event_mask);
+}
+
+GDBRemoteCommunicationReplayServer::~GDBRemoteCommunicationReplayServer() {
+ StopAsyncThread();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse(
+ Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {
+ StringExtractorGDBRemote packet;
+ PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false);
+
+ if (packet_result != PacketResult::Success) {
+ if (!IsConnected()) {
+ error.SetErrorString("lost connection");
+ quit = true;
+ } else {
+ error.SetErrorString("timeout");
+ }
+ return packet_result;
+ }
+
+ m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
+
+ if (m_skip_acks) {
+ const StringExtractorGDBRemote::ServerPacketType packet_type =
+ packet.GetServerPacketType();
+ switch (packet_type) {
+ case StringExtractorGDBRemote::eServerPacketType_nack:
+ case StringExtractorGDBRemote::eServerPacketType_ack:
+ return PacketResult::Success;
+ default:
+ break;
+ }
+ } else if (packet.GetStringRef() == "QStartNoAckMode") {
+ m_skip_acks = true;
+ m_send_acks = false;
+ }
+
+ while (!m_packet_history.empty()) {
+ // Pop last packet from the history.
+ GDBRemoteCommunicationHistory::Entry entry = m_packet_history.back();
+ m_packet_history.pop_back();
+
+ // We only care about what we received from the server. Skip everything
+ // the client sent.
+ if (entry.type != GDBRemoteCommunicationHistory::ePacketTypeRecv)
+ continue;
+
+ return SendRawPacketNoLock(entry.packet.data, true);
+ }
+
+ quit = true;
+
+ return packet_result;
+}
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(
+ std::vector<
+ lldb_private::process_gdb_remote::GDBRemoteCommunicationHistory::Entry>)
+
+llvm::Error
+GDBRemoteCommunicationReplayServer::LoadReplayHistory(const FileSpec &path) {
+ auto error_or_file = MemoryBuffer::getFile(path.GetPath());
+ if (auto err = error_or_file.getError())
+ return errorCodeToError(err);
+
+ yaml::Input yin((*error_or_file)->getBuffer());
+ yin >> m_packet_history;
+
+ if (auto err = yin.error())
+ return errorCodeToError(err);
+
+ // We want to manipulate the vector like a stack so we need to reverse the
+ // order of the packets to have the oldest on at the back.
+ std::reverse(m_packet_history.begin(), m_packet_history.end());
+
+ return Error::success();
+}
+
+bool GDBRemoteCommunicationReplayServer::StartAsyncThread() {
+ std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
+ if (!m_async_thread.IsJoinable()) {
+ // Create a thread that watches our internal state and controls which
+ // events make it to clients (into the DCProcess event queue).
+ m_async_thread = ThreadLauncher::LaunchThread(
+ "<lldb.gdb-remote.server.async>",
+ GDBRemoteCommunicationReplayServer::AsyncThread, this, nullptr);
+ }
+
+ // Wait for handshake.
+ m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
+
+ return m_async_thread.IsJoinable();
+}
+
+void GDBRemoteCommunicationReplayServer::StopAsyncThread() {
+ std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
+
+ if (!m_async_thread.IsJoinable())
+ return;
+
+ // Request thread to stop.
+ m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);
+
+ // Disconnect client.
+ Disconnect();
+
+ // Stop the thread.
+ m_async_thread.Join(nullptr);
+ m_async_thread.Reset();
+}
+
+void GDBRemoteCommunicationReplayServer::ReceivePacket(
+ GDBRemoteCommunicationReplayServer &server, bool &done) {
+ Status error;
+ bool interrupt;
+ auto packet_result = server.GetPacketAndSendResponse(std::chrono::seconds(1),
+ error, interrupt, done);
+ if (packet_result != GDBRemoteCommunication::PacketResult::Success &&
+ packet_result !=
+ GDBRemoteCommunication::PacketResult::ErrorReplyTimeout) {
+ done = true;
+ } else {
+ server.m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue);
+ }
+}
+
+thread_result_t GDBRemoteCommunicationReplayServer::AsyncThread(void *arg) {
+ GDBRemoteCommunicationReplayServer *server =
+ (GDBRemoteCommunicationReplayServer *)arg;
+
+ EventSP event_sp;
+ bool done = false;
+
+ while (true) {
+ if (server->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
+ const uint32_t event_type = event_sp->GetType();
+ if (event_sp->BroadcasterIs(&server->m_async_broadcaster)) {
+ switch (event_type) {
+ case eBroadcastBitAsyncContinue:
+ ReceivePacket(*server, done);
+ if (done)
+ return {};
+ break;
+ case eBroadcastBitAsyncThreadShouldExit:
+ default:
+ return {};
+ }
+ }
+ }
+ }
+
+ return {};
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
new file mode 100644
index 000000000000..5b840c8459b7
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.h
@@ -0,0 +1,83 @@
+//===-- GDBRemoteCommunicationReplayServer.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_GDBRemoteCommunicationReplayServer_h_
+#define liblldb_GDBRemoteCommunicationReplayServer_h_
+
+// Other libraries and framework includes
+#include "GDBRemoteCommunication.h"
+#include "GDBRemoteCommunicationHistory.h"
+
+// Project includes
+#include "lldb/Host/HostThread.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/lldb-private-forward.h"
+#include "llvm/Support/Error.h"
+
+// C Includes
+// C++ Includes
+#include <functional>
+#include <map>
+#include <thread>
+
+class StringExtractorGDBRemote;
+
+namespace lldb_private {
+namespace process_gdb_remote {
+
+class ProcessGDBRemote;
+
+/// Dummy GDB server that replays packets from the GDB Remote Communication
+/// history. This is used to replay GDB packets.
+class GDBRemoteCommunicationReplayServer : public GDBRemoteCommunication {
+public:
+ GDBRemoteCommunicationReplayServer();
+
+ ~GDBRemoteCommunicationReplayServer() override;
+
+ PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout,
+ Status &error, bool &interrupt,
+ bool &quit);
+
+ bool HandshakeWithClient() { return GetAck() == PacketResult::Success; }
+
+ llvm::Error LoadReplayHistory(const FileSpec &path);
+
+ bool StartAsyncThread();
+ void StopAsyncThread();
+
+protected:
+ enum {
+ eBroadcastBitAsyncContinue = (1 << 0),
+ eBroadcastBitAsyncThreadShouldExit = (1 << 1),
+ };
+
+ static void ReceivePacket(GDBRemoteCommunicationReplayServer &server,
+ bool &done);
+ static lldb::thread_result_t AsyncThread(void *arg);
+
+ /// Replay history with the oldest packet at the end.
+ std::vector<GDBRemoteCommunicationHistory::Entry> m_packet_history;
+
+ /// Server thread.
+ Broadcaster m_async_broadcaster;
+ lldb::ListenerSP m_async_listener_sp;
+ HostThread m_async_thread;
+ std::recursive_mutex m_async_thread_state_mutex;
+
+ bool m_skip_acks;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationReplayServer);
+};
+
+} // namespace process_gdb_remote
+} // namespace lldb_private
+
+#endif // liblldb_GDBRemoteCommunicationReplayServer_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 4fc1fc7a1964..026f78117a0c 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -13,11 +13,8 @@
#include "GDBRemoteCommunicationServer.h"
-// C Includes
-// C++ Includes
#include <cstring>
-// Project includes
#include "ProcessGDBRemoteLog.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 880caacd6414..082fb0d85424 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -10,13 +10,9 @@
#ifndef liblldb_GDBRemoteCommunicationServer_h_
#define liblldb_GDBRemoteCommunicationServer_h_
-// C Includes
-// C++ Includes
#include <functional>
#include <map>
-// Other libraries and framework includes
-// Project includes
#include "GDBRemoteCommunication.h"
#include "lldb/lldb-private-forward.h"
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index c5b478378faa..f11ef4f1bbf8 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -11,23 +11,21 @@
#include <errno.h>
-// C Includes
#ifdef __APPLE__
#include <TargetConditionals.h>
#endif
-// C++ Includes
#include <chrono>
#include <cstring>
-// Other libraries and framework includes
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/File.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/FileAction.h"
@@ -36,12 +34,10 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/StreamGDBRemote.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/Triple.h"
-// Project includes
#include "ProcessGDBRemoteLog.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
@@ -353,7 +349,7 @@ GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
std::string file;
extractor.GetHexByteString(file);
match_info.GetProcessInfo().GetExecutableFile().SetFile(
- file, false, FileSpec::Style::native);
+ file, FileSpec::Style::native);
} else if (key.equals("name_match")) {
NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
.Case("equals", NameMatch::Equals)
@@ -520,7 +516,8 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Open(
if (packet.GetChar() == ',') {
mode_t mode = packet.GetHexMaxU32(false, 0600);
Status error;
- const FileSpec path_spec{path, true};
+ FileSpec path_spec(path);
+ FileSystem::Instance().Resolve(path_spec);
int fd = ::open(path_spec.GetCString(), flags, mode);
const int save_errno = fd == -1 ? errno : 0;
StreamString response;
@@ -659,12 +656,14 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_Mode(
std::string path;
packet.GetHexByteString(path);
if (!path.empty()) {
- Status error;
- const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error);
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
+ std::error_code ec;
+ const uint32_t mode = FileSystem::Instance().GetPermissions(file_spec, ec);
StreamString response;
response.Printf("F%u", mode);
- if (mode == 0 || error.Fail())
- response.Printf(",%i", (int)error.GetError());
+ if (mode == 0 || ec)
+ response.Printf(",%i", (int)Status(ec).GetError());
return SendPacketNoLock(response.GetString());
}
return SendErrorResponse(23);
@@ -698,7 +697,11 @@ GDBRemoteCommunicationServerCommon::Handle_vFile_symlink(
packet.GetHexByteStringTerminatedBy(dst, ',');
packet.GetChar(); // Skip ',' char
packet.GetHexByteString(src);
- Status error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false});
+
+ FileSpec src_spec(src);
+ FileSystem::Instance().Resolve(src_spec);
+ Status error = FileSystem::Instance().Symlink(src_spec, FileSpec(dst));
+
StreamString response;
response.Printf("F%u,%u", error.GetError(), error.GetError());
return SendPacketNoLock(response.GetString());
@@ -731,9 +734,11 @@ GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
packet.GetHexByteString(working_dir);
int status, signo;
std::string output;
- Status err = Host::RunShellCommand(
- path.c_str(), FileSpec{working_dir, true}, &status, &signo, &output,
- std::chrono::seconds(10));
+ FileSpec working_spec(working_dir);
+ FileSystem::Instance().Resolve(working_spec);
+ Status err =
+ Host::RunShellCommand(path.c_str(), working_spec, &status, &signo,
+ &output, std::chrono::seconds(10));
StreamGDBRemote response;
if (err.Fail()) {
response.PutCString("F,");
@@ -884,7 +889,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN(
packet.GetHexByteString(path);
const bool read = true;
const bool write = false;
- if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) {
+ if (file_action.Open(STDIN_FILENO, FileSpec(path), read, write)) {
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse();
}
@@ -900,7 +905,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT(
packet.GetHexByteString(path);
const bool read = false;
const bool write = true;
- if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) {
+ if (file_action.Open(STDOUT_FILENO, FileSpec(path), read, write)) {
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse();
}
@@ -916,7 +921,7 @@ GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR(
packet.GetHexByteString(path);
const bool read = false;
const bool write = true;
- if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) {
+ if (file_action.Open(STDERR_FILENO, FileSpec(path), read, write)) {
m_process_launch_info.AppendFileAction(file_action);
return SendOKResponse();
}
@@ -1024,7 +1029,7 @@ GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
if (success) {
if (arg_idx == 0)
m_process_launch_info.GetExecutableFile().SetFile(
- arg, false, FileSpec::Style::native);
+ arg, FileSpec::Style::native);
m_process_launch_info.GetArguments().AppendArgument(arg);
if (log)
log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"",
@@ -1263,7 +1268,9 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile(
#ifdef __ANDROID__
return HostInfoAndroid::ResolveLibraryPath(module_path, arch);
#else
- return FileSpec(module_path, true);
+ FileSpec file_spec(module_path);
+ FileSystem::Instance().Resolve(file_spec);
+ return file_spec;
#endif
}
@@ -1272,7 +1279,9 @@ GDBRemoteCommunicationServerCommon::GetModuleInfo(llvm::StringRef module_path,
llvm::StringRef triple) {
ArchSpec arch(triple);
- const FileSpec req_module_path_spec(module_path, true);
+ FileSpec req_module_path_spec(module_path);
+ FileSystem::Instance().Resolve(req_module_path_spec);
+
const FileSpec module_path_spec =
FindModuleFile(req_module_path_spec.GetPath(), arch);
const ModuleSpec module_spec(module_path_spec, arch);
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index e9ab8f1a11de..f3825bb36791 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -10,12 +10,8 @@
#ifndef liblldb_GDBRemoteCommunicationServerCommon_h_
#define liblldb_GDBRemoteCommunicationServerCommon_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/lldb-private-forward.h"
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index 50392fa38956..cdb63e72f6bd 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -14,15 +14,10 @@
#include "GDBRemoteCommunicationServerLLGS.h"
#include "lldb/Utility/StreamGDBRemote.h"
-// C Includes
-// C++ Includes
#include <chrono>
#include <cstring>
#include <thread>
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Debug.h"
#include "lldb/Host/File.h"
@@ -41,12 +36,13 @@
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/UriParser.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ScopedPrinter.h"
-// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
@@ -222,8 +218,10 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() {
m_process_launch_info.SetLaunchInSeparateProcessGroup(true);
m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);
- const bool default_to_use_pty = true;
- m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty);
+ if (should_forward_stdio) {
+ if (llvm::Error Err = m_process_launch_info.SetUpPtyRedirection())
+ return Status(std::move(Err));
+ }
{
std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
@@ -1333,7 +1331,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(
packet.SetFilePos(::strlen("QSetWorkingDir:"));
std::string path;
packet.GetHexByteString(path);
- m_process_launch_info.SetWorkingDirectory(FileSpec{path, true});
+ m_process_launch_info.SetWorkingDirectory(FileSpec(path));
return SendOKResponse();
}
@@ -3220,7 +3218,7 @@ GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
if (m_debugged_process_up
->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
.Success()) {
- if (file_spec.Exists())
+ if (FileSystem::Instance().Exists(file_spec))
return file_spec;
}
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index 5a74d1acaa23..a085a3cc17dd 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -10,18 +10,14 @@
#ifndef liblldb_GDBRemoteCommunicationServerLLGS_h_
#define liblldb_GDBRemoteCommunicationServerLLGS_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <unordered_map>
-// Other libraries and framework includes
#include "lldb/Core/Communication.h"
#include "lldb/Host/MainLoop.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/lldb-private-forward.h"
-// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
class StringExtractorGDBRemote;
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index 26e28a900320..3521ddafbb16 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -11,15 +11,12 @@
#include <errno.h>
-// C Includes
-// C++ Includes
#include <chrono>
#include <csignal>
#include <cstring>
#include <mutex>
#include <sstream>
-// Other libraries and framework includes
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Threading.h"
@@ -38,7 +35,6 @@
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UriParser.h"
-// Project includes
#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
@@ -168,9 +164,6 @@ Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
StringExtractorGDBRemote &packet) {
-#ifdef _WIN32
- return SendErrorResponse(9);
-#else
// Spawn a local debugserver as a platform so we can then attach or launch a
// process...
@@ -221,10 +214,9 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
PacketResult packet_result = SendPacketNoLock(response.GetString());
if (packet_result != PacketResult::Success) {
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- ::kill(debugserver_pid, SIGINT);
+ Host::Kill(debugserver_pid, SIGINT);
}
return packet_result;
-#endif
}
GDBRemoteCommunication::PacketResult
@@ -532,7 +524,7 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
const char *domainsocket_dir_env =
::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
if (domainsocket_dir_env != nullptr)
- g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
+ g_domainsocket_dir = FileSpec(domainsocket_dir_env);
else
g_domainsocket_dir = HostInfo::GetProcessTempDir();
});
@@ -542,15 +534,15 @@ const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
FileSpec
GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
- llvm::SmallString<PATH_MAX> socket_path;
- llvm::SmallString<PATH_MAX> socket_name(
+ llvm::SmallString<128> socket_path;
+ llvm::SmallString<128> socket_name(
(llvm::StringRef(prefix) + ".%%%%%%").str());
FileSpec socket_path_spec(GetDomainSocketDir());
socket_path_spec.AppendPathComponent(socket_name.c_str());
llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
- return FileSpec(socket_path.c_str(), false);
+ return FileSpec(socket_path.c_str());
}
void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
index aed5106272d1..df51e0367d1d 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
@@ -10,14 +10,10 @@
#ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_
#define liblldb_GDBRemoteCommunicationServerPlatform_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <set>
-// Other libraries and framework includes
-// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
#include "lldb/Host/Socket.h"
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 07dab751f4b9..e58f47f4befe 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -9,17 +9,13 @@
#include "GDBRemoteRegisterContext.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
-// Project includes
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
@@ -462,7 +458,7 @@ bool GDBRemoteRegisterContext::ReadAllRegisterValues(
((ProcessGDBRemote *)process)->GetGDBRemote());
const bool use_g_packet =
- gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false;
+ !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock) {
@@ -525,7 +521,7 @@ bool GDBRemoteRegisterContext::WriteAllRegisterValues(
((ProcessGDBRemote *)process)->GetGDBRemote());
const bool use_g_packet =
- gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false;
+ !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock) {
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 8ef91af55e0f..6e8f3306669f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -10,12 +10,8 @@
#ifndef lldb_GDBRemoteRegisterContext_h_
#define lldb_GDBRemoteRegisterContext_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/ConstString.h"
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index b3d33b19bd66..797f63d537a1 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -9,12 +9,11 @@
#include "lldb/Host/Config.h"
-// C Includes
#include <errno.h>
#include <stdlib.h>
#ifndef LLDB_DISABLE_POSIX
#include <netinet/in.h>
-#include <sys/mman.h> // for mmap
+#include <sys/mman.h>
#include <sys/socket.h>
#include <unistd.h>
#endif
@@ -22,7 +21,6 @@
#include <sys/types.h>
#include <time.h>
-// C++ Includes
#include <algorithm>
#include <csignal>
#include <map>
@@ -34,7 +32,6 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
@@ -68,10 +65,11 @@
#include "lldb/Utility/Args.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Reproducer.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
-// Project includes
#include "GDBRemoteRegisterContext.h"
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
@@ -88,6 +86,7 @@
#include "llvm/Support/raw_ostream.h"
#define DEBUGSERVER_BASENAME "debugserver"
+using namespace llvm;
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
@@ -101,21 +100,21 @@ namespace lldb {
// and get the packet history dumped to a file.
void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
StreamFile strm;
- Status error(strm.GetFile().Open(path, File::eOpenOptionWrite |
- File::eOpenOptionCanCreate));
+ Status error = FileSystem::Instance().Open(strm.GetFile(), FileSpec(path),
+ File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate);
if (error.Success())
((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);
}
-}
+} // namespace lldb
namespace {
-static PropertyDefinition g_properties[] = {
- {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL,
+static constexpr PropertyDefinition g_properties[] = {
+ {"packet-timeout", OptionValue::eTypeUInt64, true, 1, 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}};
+ {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, {},
+ "The file that provides the description for remote target registers."}};
enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile };
@@ -158,7 +157,42 @@ static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
return g_settings_sp;
}
-} // anonymous namespace end
+class ProcessGDBRemoteProvider
+ : public repro::Provider<ProcessGDBRemoteProvider> {
+public:
+ ProcessGDBRemoteProvider(const FileSpec &directory) : Provider(directory) {
+ m_info.name = "gdb-remote";
+ m_info.files.push_back("gdb-remote.yaml");
+ }
+
+ raw_ostream *GetHistoryStream() {
+ FileSpec history_file =
+ GetRoot().CopyByAppendingPathComponent("gdb-remote.yaml");
+
+ std::error_code EC;
+ m_stream_up = llvm::make_unique<raw_fd_ostream>(history_file.GetPath(), EC,
+ sys::fs::OpenFlags::F_None);
+ return m_stream_up.get();
+ }
+
+ void SetCallback(std::function<void()> callback) {
+ m_callback = std::move(callback);
+ }
+
+ void Keep() override { m_callback(); }
+
+ void Discard() override { m_callback(); }
+
+ static char ID;
+
+private:
+ std::function<void()> m_callback;
+ std::unique_ptr<raw_fd_ostream> m_stream_up;
+};
+
+char ProcessGDBRemoteProvider::ID = 0;
+
+} // namespace
// TODO Randomly assigning a port is unsafe. We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing it
@@ -234,7 +268,7 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
case ObjectFile::eTypeUnknown:
break;
}
- return exe_module->GetFileSpec().Exists();
+ return FileSystem::Instance().Exists(exe_module->GetFileSpec());
}
// However, if there is no executable module, we return true since we might
// be preparing to attach.
@@ -259,8 +293,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_addr_to_mmap_size(), m_thread_create_bp_sp(),
m_waiting_for_attach(false), m_destroy_tried_resuming(false),
m_command_sp(), m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false),
- m_erased_flash_ranges() {
+ m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false),
+ m_allow_flash_writes(false), m_erased_flash_ranges() {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
"async thread should exit");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
@@ -268,6 +302,15 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit,
"async thread did exit");
+ if (repro::Generator *g = repro::Reproducer::Instance().GetGenerator()) {
+ ProcessGDBRemoteProvider &provider =
+ g->GetOrCreate<ProcessGDBRemoteProvider>();
+ // Set the history stream to the stream owned by the provider.
+ m_gdb_comm.SetHistoryStream(provider.GetHistoryStream());
+ // Make sure to clear the stream again when we're finished.
+ provider.SetCallback([&]() { m_gdb_comm.SetHistoryStream(nullptr); });
+ }
+
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
const uint32_t async_event_mask =
@@ -440,10 +483,10 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
FileSpec target_definition_fspec =
GetGlobalPluginProperties()->GetTargetDefinitionFile();
- if (!target_definition_fspec.Exists()) {
+ if (!FileSystem::Instance().Exists(target_definition_fspec)) {
// If the filename doesn't exist, it may be a ~ not having been expanded -
// try to resolve it.
- target_definition_fspec.ResolvePath();
+ FileSystem::Instance().Resolve(target_definition_fspec);
}
if (target_definition_fspec) {
// See if we can get register definitions from a python file
@@ -640,7 +683,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
m_register_info.Finalize(GetTarget().GetArchitecture());
}
-Status ProcessGDBRemote::WillLaunch(Module *module) {
+Status ProcessGDBRemote::WillLaunch(lldb_private::Module *module) {
return WillLaunchOrAttach();
}
@@ -689,7 +732,9 @@ Status ProcessGDBRemote::DoConnectRemote(Stream *strm,
if (m_gdb_comm.GetProcessArchitecture().IsValid()) {
target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
} else {
- target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ if (m_gdb_comm.GetHostArchitecture().IsValid()) {
+ target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ }
}
}
@@ -754,7 +799,7 @@ Status ProcessGDBRemote::WillLaunchOrAttach() {
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
-Status ProcessGDBRemote::DoLaunch(Module *exe_module,
+Status ProcessGDBRemote::DoLaunch(lldb_private::Module *exe_module,
ProcessLaunchInfo &launch_info) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
Status error;
@@ -824,13 +869,13 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
if (disable_stdio) {
// set to /dev/null unless redirected to a file above
if (!stdin_file_spec)
- stdin_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
if (!stdout_file_spec)
- stdout_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
if (!stderr_file_spec)
- stderr_file_spec.SetFile(FileSystem::DEV_NULL, false,
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL,
FileSpec::Style::native);
} else if (platform_sp && platform_sp->IsHost()) {
// If the debugserver is local and we aren't disabling STDIO, lets use
@@ -839,7 +884,7 @@ Status ProcessGDBRemote::DoLaunch(Module *exe_module,
// does a lot of output.
if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) {
- FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};
+ FileSpec slave_name{pty.GetSlaveName(NULL, 0)};
if (!stdin_file_spec)
stdin_file_spec = slave_name;
@@ -1058,9 +1103,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
if (log)
log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, "
"using %s %s",
- __FUNCTION__, process_arch.GetArchitectureName()
- ? process_arch.GetArchitectureName()
- : "<null>",
+ __FUNCTION__,
+ process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
process_arch.GetTriple().getTriple().c_str()
? process_arch.GetTriple().getTriple().c_str()
: "<null>");
@@ -1069,9 +1115,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
if (log)
log->Printf("ProcessGDBRemote::%s gdb-remote did not have process "
"architecture, using gdb-remote host architecture %s %s",
- __FUNCTION__, process_arch.GetArchitectureName()
- ? process_arch.GetArchitectureName()
- : "<null>",
+ __FUNCTION__,
+ process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
process_arch.GetTriple().getTriple().c_str()
? process_arch.GetTriple().getTriple().c_str()
: "<null>");
@@ -1083,9 +1130,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
if (log)
log->Printf(
"ProcessGDBRemote::%s analyzing target arch, currently %s %s",
- __FUNCTION__, target_arch.GetArchitectureName()
- ? target_arch.GetArchitectureName()
- : "<null>",
+ __FUNCTION__,
+ target_arch.GetArchitectureName()
+ ? target_arch.GetArchitectureName()
+ : "<null>",
target_arch.GetTriple().getTriple().c_str()
? target_arch.GetTriple().getTriple().c_str()
: "<null>");
@@ -1105,9 +1153,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
if (log)
log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, "
"setting target arch to %s %s",
- __FUNCTION__, process_arch.GetArchitectureName()
- ? process_arch.GetArchitectureName()
- : "<null>",
+ __FUNCTION__,
+ process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
process_arch.GetTriple().getTriple().c_str()
? process_arch.GetTriple().getTriple().c_str()
: "<null>");
@@ -1135,9 +1184,10 @@ void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
if (log)
log->Printf("ProcessGDBRemote::%s final target arch after "
"adjustments for remote architecture: %s %s",
- __FUNCTION__, target_arch.GetArchitectureName()
- ? target_arch.GetArchitectureName()
- : "<null>",
+ __FUNCTION__,
+ target_arch.GetArchitectureName()
+ ? target_arch.GetArchitectureName()
+ : "<null>",
target_arch.GetTriple().getTriple().c_str()
? target_arch.GetTriple().getTriple().c_str()
: "<null>");
@@ -1478,7 +1528,7 @@ Status ProcessGDBRemote::DoResume() {
new EventDataBytes(continue_packet.GetString().data(),
continue_packet.GetSize()));
- if (listener_sp->GetEvent(event_sp, std::chrono::seconds(5)) == false) {
+ if (!listener_sp->GetEvent(event_sp, std::chrono::seconds(5))) {
error.SetErrorString("Resume timed out.");
if (log)
log->Printf("ProcessGDBRemote::DoResume: Resume timed out.");
@@ -1832,7 +1882,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
bool handled = false;
bool did_exec = false;
if (!reason.empty()) {
- if (reason.compare("trace") == 0) {
+ if (reason == "trace") {
addr_t pc = thread_sp->GetRegisterContext()->GetPC();
lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
->GetBreakpointSiteList()
@@ -1850,7 +1900,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonToTrace(*thread_sp));
handled = true;
- } else if (reason.compare("breakpoint") == 0) {
+ } else if (reason == "breakpoint") {
addr_t pc = thread_sp->GetRegisterContext()->GetPC();
lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
->GetBreakpointSiteList()
@@ -1871,9 +1921,9 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
thread_sp->SetStopInfo(invalid_stop_info_sp);
}
}
- } else if (reason.compare("trap") == 0) {
+ } else if (reason == "trap") {
// Let the trap just use the standard signal stop reason below...
- } else if (reason.compare("watchpoint") == 0) {
+ } else if (reason == "watchpoint") {
StringExtractor desc_extractor(description.c_str());
addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
@@ -1905,11 +1955,11 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID(
*thread_sp, watch_id, wp_hit_addr));
handled = true;
- } else if (reason.compare("exception") == 0) {
+ } else if (reason == "exception") {
thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
*thread_sp, description.c_str()));
handled = true;
- } else if (reason.compare("exec") == 0) {
+ } else if (reason == "exec") {
did_exec = true;
thread_sp->SetStopInfo(
StopInfo::CreateStopReasonWithExec(*thread_sp));
@@ -1934,7 +1984,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
}
}
- if (!handled && signo && did_exec == false) {
+ if (!handled && signo && !did_exec) {
if (signo == SIGTRAP) {
// Currently we are going to assume SIGTRAP means we are either
// hitting a breakpoint or hardware single stepping.
@@ -2648,7 +2698,7 @@ void ProcessGDBRemote::SetLastStopPacket(
// We are are not using non-stop mode, there can only be one last stop
// reply packet, so clear the list.
- if (GetTarget().GetNonStopModeEnabled() == false)
+ if (!GetTarget().GetNonStopModeEnabled())
m_stop_packet_stack.clear();
// Add this stop packet to the stop packet stack This stack will get popped
@@ -3378,6 +3428,43 @@ Status ProcessGDBRemote::DoSignal(int signo) {
return error;
}
+Status ProcessGDBRemote::ConnectToReplayServer(repro::Loader *loader) {
+ if (!loader)
+ return Status("No loader provided.");
+
+ auto provider_info = loader->GetProviderInfo("gdb-remote");
+ if (!provider_info)
+ return Status("No provider for gdb-remote.");
+
+ if (provider_info->files.empty())
+ return Status("Provider for gdb-remote contains no files.");
+
+ // Construct replay history path.
+ FileSpec history_file = loader->GetRoot().CopyByAppendingPathComponent(
+ provider_info->files.front());
+
+ // Enable replay mode.
+ m_replay_mode = true;
+
+ // Load replay history.
+ if (auto error = m_gdb_replay_server.LoadReplayHistory(history_file))
+ return Status("Unable to load replay history");
+
+ // Make a local connection.
+ if (auto error = GDBRemoteCommunication::ConnectLocally(m_gdb_comm,
+ m_gdb_replay_server))
+ return Status("Unable to connect to replay server");
+
+ // Start server thread.
+ m_gdb_replay_server.StartAsyncThread();
+
+ // Start client thread.
+ StartAsyncThread();
+
+ // Do the usual setup.
+ return ConnectToDebugserver("");
+}
+
Status
ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {
// Make sure we aren't already connected?
@@ -3388,6 +3475,9 @@ ProcessGDBRemote::EstablishConnectionIfNeeded(const ProcessInfo &process_info) {
if (platform_sp && !platform_sp->IsHost())
return Status("Lost debug server connection");
+ if (repro::Loader *loader = repro::Reproducer::Instance().GetLoader())
+ return ConnectToReplayServer(loader);
+
auto error = LaunchAndConnectToDebugserver(process_info);
if (error.Fail()) {
const char *error_string = error.AsCString();
@@ -3497,7 +3587,7 @@ bool ProcessGDBRemote::MonitorDebugserverProcess(
bool exited, // True if the process did exit
int signo, // Zero for no signal
int exit_status // Exit value of process if signal is zero
- ) {
+) {
// "debugserver_pid" argument passed in is the process ID for debugserver
// that we are tracking...
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
@@ -4269,8 +4359,9 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
return false;
feature_node.ForEachChildElementWithName(
- "reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset,
- &abi_sp](const XMLNode &reg_node) -> bool {
+ "reg",
+ [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset,
+ &abi_sp](const XMLNode &reg_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@@ -4432,7 +4523,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
return true;
}
-} // namespace {}
+} // namespace
// query the target of gdb-remote for extended target information return:
// 'true' on success
@@ -4509,12 +4600,19 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
// <architecture>arm</architecture> (seen from Segger JLink on unspecified arm board)
// use that if we don't have anything better.
if (!arch_to_use.IsValid() && !target_info.arch.empty()) {
- if (target_info.arch == "i386:x86-64")
- {
+ if (target_info.arch == "i386:x86-64") {
// We don't have any information about vendor or OS.
arch_to_use.SetTriple("x86_64--");
GetTarget().MergeArchitecture(arch_to_use);
}
+
+ // SEGGER J-Link jtag boards send this very-generic arch name,
+ // we'll need to use this if we have absolutely nothing better
+ // to work with or the register definitions won't be accepted.
+ if (target_info.arch == "arm") {
+ arch_to_use.SetTriple("arm--");
+ GetTarget().MergeArchitecture(arch_to_use);
+ }
}
// Initialize these outside of ParseRegisters, since they should not be
@@ -4760,7 +4858,8 @@ size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {
if (!modInfo.get_link_map(link_map))
link_map = LLDB_INVALID_ADDRESS;
- FileSpec file(mod_name, true);
+ FileSpec file(mod_name);
+ FileSystem::Instance().Resolve(file);
lldb::ModuleSP module_sp =
LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset);
@@ -4802,7 +4901,7 @@ size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {
return true;
lldb::ModuleSP module_copy_sp = module_sp;
- target.SetExecutableModule(module_copy_sp, false);
+ target.SetExecutableModule(module_copy_sp, eLoadDependentsNo);
return false;
});
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 45bb2d4c28e7..14a5237e4345 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -10,15 +10,12 @@
#ifndef liblldb_ProcessGDBRemote_h_
#define liblldb_ProcessGDBRemote_h_
-// C Includes
-// C++ Includes
#include <atomic>
#include <map>
#include <mutex>
#include <string>
#include <vector>
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/ThreadSafeValue.h"
@@ -26,6 +23,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamGDBRemote.h"
@@ -36,11 +34,15 @@
#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationClient.h"
+#include "GDBRemoteCommunicationReplayServer.h"
#include "GDBRemoteRegisterContext.h"
#include "llvm/ADT/DenseMap.h"
namespace lldb_private {
+namespace repro {
+class Loader;
+}
namespace process_gdb_remote {
class ThreadGDBRemote;
@@ -264,6 +266,7 @@ protected:
};
GDBRemoteCommunicationClient m_gdb_comm;
+ GDBRemoteCommunicationReplayServer m_gdb_replay_server;
std::atomic<lldb::pid_t> m_debugserver_pid;
std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet
// stack replaces
@@ -304,6 +307,7 @@ protected:
int64_t m_breakpoint_pc_offset;
lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
+ bool m_replay_mode;
bool m_allow_flash_writes;
using FlashRangeVector = lldb_private::RangeVector<lldb::addr_t, size_t>;
using FlashRange = FlashRangeVector::Entry;
@@ -331,6 +335,8 @@ protected:
bool UpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) override;
+ Status ConnectToReplayServer(repro::Loader *loader);
+
Status EstablishConnectionIfNeeded(const ProcessInfo &process_info);
Status LaunchAndConnectToDebugserver(const ProcessInfo &process_info);
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
index 3c5801176690..d4981df88d8d 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
@@ -10,11 +10,7 @@
#ifndef liblldb_ProcessGDBRemoteLog_h_
#define liblldb_ProcessGDBRemoteLog_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Log.h"
#define GDBR_LOG_PROCESS (1u << 1)
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index a525c16b9f13..db7dc3eae0ba 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -10,7 +10,6 @@
#include "ThreadGDBRemote.h"
#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -20,6 +19,7 @@
#include "lldb/Target/UnixSignals.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "ProcessGDBRemote.h"
@@ -197,13 +197,10 @@ void ThreadGDBRemote::SetQueueLibdispatchQueueAddress(
}
bool ThreadGDBRemote::ThreadHasQueueInformation() const {
- if (m_thread_dispatch_qaddr != 0 &&
- m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS &&
- m_dispatch_queue_t != LLDB_INVALID_ADDRESS &&
- m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0) {
- return true;
- }
- return false;
+ return m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS &&
+ m_dispatch_queue_t != LLDB_INVALID_ADDRESS &&
+ m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0;
}
LazyBool ThreadGDBRemote::GetAssociatedWithLibdispatchQueue() {
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 1a5b60aea288..4485a9cdc4c3 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ThreadGDBRemote_h_
#define liblldb_ThreadGDBRemote_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.cpp b/source/Plugins/Process/mach-core/ProcessMachCore.cpp
index bfa35ed506a9..08b9f08a47f6 100644
--- a/source/Plugins/Process/mach-core/ProcessMachCore.cpp
+++ b/source/Plugins/Process/mach-core/ProcessMachCore.cpp
@@ -8,38 +8,33 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#include <stdlib.h>
-// C++ Includes
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Threading.h"
#include <mutex>
-// Other libraries and framework includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBuffer.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
-// Project includes
#include "ProcessMachCore.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
#include "ThreadMachCore.h"
// Needed for the plug-in names for the dynamic loaders.
-#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Host/SafeMachO.h"
#include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
#include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
@@ -67,8 +62,8 @@ lldb::ProcessSP ProcessMachCore::CreateInstance(lldb::TargetSP target_sp,
lldb::ProcessSP process_sp;
if (crash_file) {
const size_t header_size = sizeof(llvm::MachO::mach_header);
- auto data_sp =
- DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0);
+ auto data_sp = FileSystem::Instance().CreateDataBuffer(
+ crash_file->GetPath(), header_size, 0);
if (data_sp && data_sp->GetByteSize() == header_size) {
DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
@@ -90,7 +85,7 @@ bool ProcessMachCore::CanDebug(lldb::TargetSP target_sp,
return true;
// For now we are just making sure the file exists for a given module
- if (!m_core_module_sp && m_core_file.Exists()) {
+ if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
// Don't add the Target's architecture to the ModuleSpec - we may be
// working with a core file that doesn't have the correct cpusubtype in the
// header but we should still try to use it -
@@ -307,36 +302,38 @@ Status ProcessMachCore::DoLoadCore() {
// LC_IDENT is very obsolete and should not be used in new code, but if the
// load command is present, let's use the contents.
std::string corefile_identifier = core_objfile->GetIdentifierString();
- if (found_main_binary_definitively == false
- && corefile_identifier.find("Darwin Kernel") != std::string::npos) {
- UUID uuid;
- addr_t addr = LLDB_INVALID_ADDRESS;
- if (corefile_identifier.find("UUID=") != std::string::npos) {
- size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
- std::string uuid_str = corefile_identifier.substr(p, 36);
- uuid.SetFromStringRef(uuid_str);
- }
- if (corefile_identifier.find("stext=") != std::string::npos) {
- size_t p = corefile_identifier.find("stext=") + strlen("stext=");
- if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
- errno = 0;
- addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16);
- if (errno != 0 || addr == 0)
- addr = LLDB_INVALID_ADDRESS;
- }
- }
- if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) {
- m_mach_kernel_addr = addr;
- found_main_binary_definitively = true;
- if (log)
- log->Printf("ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64
- " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'", addr, corefile_identifier.c_str());
+ if (!found_main_binary_definitively &&
+ corefile_identifier.find("Darwin Kernel") != std::string::npos) {
+ UUID uuid;
+ addr_t addr = LLDB_INVALID_ADDRESS;
+ if (corefile_identifier.find("UUID=") != std::string::npos) {
+ size_t p = corefile_identifier.find("UUID=") + strlen("UUID=");
+ std::string uuid_str = corefile_identifier.substr(p, 36);
+ uuid.SetFromStringRef(uuid_str);
+ }
+ if (corefile_identifier.find("stext=") != std::string::npos) {
+ size_t p = corefile_identifier.find("stext=") + strlen("stext=");
+ if (corefile_identifier[p] == '0' && corefile_identifier[p + 1] == 'x') {
+ errno = 0;
+ addr = ::strtoul(corefile_identifier.c_str() + p, NULL, 16);
+ if (errno != 0 || addr == 0)
+ addr = LLDB_INVALID_ADDRESS;
}
+ }
+ if (uuid.IsValid() && addr != LLDB_INVALID_ADDRESS) {
+ m_mach_kernel_addr = addr;
+ found_main_binary_definitively = true;
+ if (log)
+ log->Printf(
+ "ProcessMachCore::DoLoadCore: Using the kernel address 0x%" PRIx64
+ " from LC_IDENT/LC_NOTE 'kern ver str' string: '%s'",
+ addr, corefile_identifier.c_str());
+ }
}
- if (found_main_binary_definitively == false
- && (m_dyld_addr == LLDB_INVALID_ADDRESS
- || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
+ if (!found_main_binary_definitively &&
+ (m_dyld_addr == LLDB_INVALID_ADDRESS ||
+ m_mach_kernel_addr == LLDB_INVALID_ADDRESS)) {
// We need to locate the main executable in the memory ranges we have in
// the core file. We need to search for both a user-process dyld binary
// and a kernel binary in memory; we must look at all the pages in the
@@ -357,16 +354,15 @@ Status ProcessMachCore::DoLoadCore() {
}
}
- if (found_main_binary_definitively == false
- && m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
+ if (!found_main_binary_definitively &&
+ m_mach_kernel_addr != LLDB_INVALID_ADDRESS) {
// In the case of multiple kernel images found in the core file via
// exhaustive search, we may not pick the correct one. See if the
// DynamicLoaderDarwinKernel's search heuristics might identify the correct
// one. Most of the time, I expect the address from SearchForDarwinKernel()
// will be the same as the address we found via exhaustive search.
- if (GetTarget().GetArchitecture().IsValid() == false &&
- m_core_module_sp.get()) {
+ if (!GetTarget().GetArchitecture().IsValid() && m_core_module_sp.get()) {
GetTarget().SetArchitecture(m_core_module_sp->GetArchitecture());
}
diff --git a/source/Plugins/Process/mach-core/ProcessMachCore.h b/source/Plugins/Process/mach-core/ProcessMachCore.h
index 101df6b79115..0c6fc693a50c 100644
--- a/source/Plugins/Process/mach-core/ProcessMachCore.h
+++ b/source/Plugins/Process/mach-core/ProcessMachCore.h
@@ -10,13 +10,9 @@
#ifndef liblldb_ProcessMachCore_h_
#define liblldb_ProcessMachCore_h_
-// C Includes
-// C++ Includes
#include <list>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Status.h"
diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.cpp b/source/Plugins/Process/mach-core/ThreadMachCore.cpp
index c262dd47f978..16edd28f1a13 100644
--- a/source/Plugins/Process/mach-core/ThreadMachCore.cpp
+++ b/source/Plugins/Process/mach-core/ThreadMachCore.cpp
@@ -9,10 +9,7 @@
#include "ThreadMachCore.h"
-#include "lldb/Utility/SafeMachO.h"
-
#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Core/State.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -21,6 +18,7 @@
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "ProcessMachCore.h"
diff --git a/source/Plugins/Process/mach-core/ThreadMachCore.h b/source/Plugins/Process/mach-core/ThreadMachCore.h
index a4db484e850f..696ba7294e4a 100644
--- a/source/Plugins/Process/mach-core/ThreadMachCore.h
+++ b/source/Plugins/Process/mach-core/ThreadMachCore.h
@@ -10,12 +10,8 @@
#ifndef liblldb_ThreadMachCore_h_
#define liblldb_ThreadMachCore_h_
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
class ProcessMachCore;
diff --git a/source/Plugins/Process/minidump/CMakeLists.txt b/source/Plugins/Process/minidump/CMakeLists.txt
index b898ee1aa144..4126a7ea991c 100644
--- a/source/Plugins/Process/minidump/CMakeLists.txt
+++ b/source/Plugins/Process/minidump/CMakeLists.txt
@@ -1,6 +1,8 @@
add_lldb_library(lldbPluginProcessMinidump PLUGIN
MinidumpTypes.cpp
MinidumpParser.cpp
+ RegisterContextMinidump_ARM.cpp
+ RegisterContextMinidump_ARM64.cpp
RegisterContextMinidump_x86_32.cpp
RegisterContextMinidump_x86_64.cpp
ProcessMinidump.cpp
diff --git a/source/Plugins/Process/minidump/MinidumpParser.cpp b/source/Plugins/Process/minidump/MinidumpParser.cpp
index 9a979335e99e..d4053ca70b94 100644
--- a/source/Plugins/Process/minidump/MinidumpParser.cpp
+++ b/source/Plugins/Process/minidump/MinidumpParser.cpp
@@ -7,20 +7,19 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "MinidumpParser.h"
#include "NtStructures.h"
#include "RegisterContextMinidump_x86_32.h"
-// Other libraries and framework includes
-#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "Plugins/Process/Utility/LinuxProcMaps.h"
// C includes
// C++ includes
#include <algorithm>
#include <map>
#include <vector>
+#include <utility>
using namespace lldb_private;
using namespace minidump;
@@ -80,8 +79,18 @@ UUID MinidumpParser::GetModuleUUID(const MinidumpModule *module) {
// PDB70 record
const CvRecordPdb70 *pdb70_uuid = nullptr;
Status error = consumeObject(cv_record, pdb70_uuid);
- if (!error.Fail())
- return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
+ if (!error.Fail()) {
+ auto arch = GetArchitecture();
+ // For Apple targets we only need a 16 byte UUID so that we can match
+ // the UUID in the Module to actual UUIDs from the built binaries. The
+ // "Age" field is zero in breakpad minidump files for Apple targets, so
+ // we restrict the UUID to the "Uuid" field so we have a UUID we can use
+ // to match.
+ if (arch.GetTriple().getVendor() == llvm::Triple::Apple)
+ return UUID::fromData(pdb70_uuid->Uuid, sizeof(pdb70_uuid->Uuid));
+ else
+ return UUID::fromData(pdb70_uuid, sizeof(*pdb70_uuid));
+ }
} else if (cv_signature == CvSignature::ElfBuildId)
return UUID::fromData(cv_record);
@@ -98,11 +107,15 @@ llvm::ArrayRef<MinidumpThread> MinidumpParser::GetThreads() {
}
llvm::ArrayRef<uint8_t>
-MinidumpParser::GetThreadContext(const MinidumpThread &td) {
- if (td.thread_context.rva + td.thread_context.data_size > GetData().size())
+MinidumpParser::GetThreadContext(const MinidumpLocationDescriptor &location) {
+ if (location.rva + location.data_size > GetData().size())
return {};
+ return GetData().slice(location.rva, location.data_size);
+}
- return GetData().slice(td.thread_context.rva, td.thread_context.data_size);
+llvm::ArrayRef<uint8_t>
+MinidumpParser::GetThreadContext(const MinidumpThread &td) {
+ return GetThreadContext(td.thread_context);
}
llvm::ArrayRef<uint8_t>
@@ -146,11 +159,14 @@ const MinidumpSystemInfo *MinidumpParser::GetSystemInfo() {
}
ArchSpec MinidumpParser::GetArchitecture() {
- ArchSpec arch_spec;
+ if (m_arch.IsValid())
+ return m_arch;
+
+ // Set the architecture in m_arch
const MinidumpSystemInfo *system_info = GetSystemInfo();
if (!system_info)
- return arch_spec;
+ return m_arch;
// TODO what to do about big endiand flavors of arm ?
// TODO set the arm subarch stuff if the minidump has info about it
@@ -196,19 +212,28 @@ ArchSpec MinidumpParser::GetArchitecture() {
break;
case MinidumpOSPlatform::MacOSX:
triple.setOS(llvm::Triple::OSType::MacOSX);
+ triple.setVendor(llvm::Triple::Apple);
+ break;
+ case MinidumpOSPlatform::IOS:
+ triple.setOS(llvm::Triple::OSType::IOS);
+ triple.setVendor(llvm::Triple::Apple);
break;
case MinidumpOSPlatform::Android:
triple.setOS(llvm::Triple::OSType::Linux);
triple.setEnvironment(llvm::Triple::EnvironmentType::Android);
break;
- default:
+ default: {
triple.setOS(llvm::Triple::OSType::UnknownOS);
+ std::string csd_version;
+ if (auto s = GetMinidumpString(system_info->csd_version_rva))
+ csd_version = *s;
+ if (csd_version.find("Linux") != std::string::npos)
+ triple.setOS(llvm::Triple::OSType::Linux);
break;
+ }
}
-
- arch_spec.SetTriple(triple);
-
- return arch_spec;
+ m_arch.SetTriple(triple);
+ return m_arch;
}
const MinidumpMiscInfo *MinidumpParser::GetMiscInfo() {
@@ -254,36 +279,45 @@ llvm::ArrayRef<MinidumpModule> MinidumpParser::GetModuleList() {
std::vector<const MinidumpModule *> MinidumpParser::GetFilteredModuleList() {
llvm::ArrayRef<MinidumpModule> modules = GetModuleList();
- // map module_name -> pair(load_address, pointer to module struct in memory)
- llvm::StringMap<std::pair<uint64_t, const MinidumpModule *>> lowest_addr;
+ // map module_name -> filtered_modules index
+ typedef llvm::StringMap<size_t> MapType;
+ MapType module_name_to_filtered_index;
std::vector<const MinidumpModule *> filtered_modules;
-
+
llvm::Optional<std::string> name;
std::string module_name;
for (const auto &module : modules) {
name = GetMinidumpString(module.module_name_rva);
-
+
if (!name)
continue;
-
+
module_name = name.getValue();
-
- auto iter = lowest_addr.end();
- bool exists;
- std::tie(iter, exists) = lowest_addr.try_emplace(
- module_name, std::make_pair(module.base_of_image, &module));
-
- if (exists && module.base_of_image < iter->second.first)
- iter->second = std::make_pair(module.base_of_image, &module);
- }
-
- filtered_modules.reserve(lowest_addr.size());
- for (const auto &module : lowest_addr) {
- filtered_modules.push_back(module.second.second);
+
+ MapType::iterator iter;
+ bool inserted;
+ // See if we have inserted this module aready into filtered_modules. If we
+ // haven't insert an entry into module_name_to_filtered_index with the
+ // index where we will insert it if it isn't in the vector already.
+ std::tie(iter, inserted) = module_name_to_filtered_index.try_emplace(
+ module_name, filtered_modules.size());
+
+ if (inserted) {
+ // This module has not been seen yet, insert it into filtered_modules at
+ // the index that was inserted into module_name_to_filtered_index using
+ // "filtered_modules.size()" above.
+ filtered_modules.push_back(&module);
+ } else {
+ // This module has been seen. Modules are sometimes mentioned multiple
+ // times when they are mapped discontiguously, so find the module with
+ // the lowest "base_of_image" and use that as the filtered module.
+ auto dup_module = filtered_modules[iter->second];
+ if (module.base_of_image < dup_module->base_of_image)
+ filtered_modules[iter->second] = &module;
+ }
}
-
return filtered_modules;
}
@@ -381,72 +415,153 @@ llvm::ArrayRef<uint8_t> MinidumpParser::GetMemory(lldb::addr_t addr,
return range->range_ref.slice(offset, overlap);
}
-llvm::Optional<MemoryRegionInfo>
-MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
- MemoryRegionInfo info;
- llvm::ArrayRef<uint8_t> data = GetStream(MinidumpStreamType::MemoryInfoList);
+static bool
+CreateRegionsCacheFromLinuxMaps(MinidumpParser &parser,
+ std::vector<MemoryRegionInfo> &regions) {
+ auto data = parser.GetStream(MinidumpStreamType::LinuxMaps);
if (data.empty())
- return llvm::None;
+ return false;
+ ParseLinuxMapRegions(llvm::toStringRef(data),
+ [&](const lldb_private::MemoryRegionInfo &region,
+ const lldb_private::Status &status) -> bool {
+ if (status.Success())
+ regions.push_back(region);
+ return true;
+ });
+ return !regions.empty();
+}
- std::vector<const MinidumpMemoryInfo *> mem_info_list =
- MinidumpMemoryInfo::ParseMemoryInfoList(data);
+static bool
+CreateRegionsCacheFromMemoryInfoList(MinidumpParser &parser,
+ std::vector<MemoryRegionInfo> &regions) {
+ auto data = parser.GetStream(MinidumpStreamType::MemoryInfoList);
+ if (data.empty())
+ return false;
+ auto mem_info_list = MinidumpMemoryInfo::ParseMemoryInfoList(data);
if (mem_info_list.empty())
- return llvm::None;
+ return false;
+ constexpr auto yes = MemoryRegionInfo::eYes;
+ constexpr auto no = MemoryRegionInfo::eNo;
+ regions.reserve(mem_info_list.size());
+ for (const auto &entry : mem_info_list) {
+ MemoryRegionInfo region;
+ region.GetRange().SetRangeBase(entry->base_address);
+ region.GetRange().SetByteSize(entry->region_size);
+ region.SetReadable(entry->isReadable() ? yes : no);
+ region.SetWritable(entry->isWritable() ? yes : no);
+ region.SetExecutable(entry->isExecutable() ? yes : no);
+ region.SetMapped(entry->isMapped() ? yes : no);
+ regions.push_back(region);
+ }
+ return !regions.empty();
+}
- const auto yes = MemoryRegionInfo::eYes;
- const auto no = MemoryRegionInfo::eNo;
+static bool
+CreateRegionsCacheFromMemoryList(MinidumpParser &parser,
+ std::vector<MemoryRegionInfo> &regions) {
+ auto data = parser.GetStream(MinidumpStreamType::MemoryList);
+ if (data.empty())
+ return false;
+ auto memory_list = MinidumpMemoryDescriptor::ParseMemoryList(data);
+ if (memory_list.empty())
+ return false;
+ regions.reserve(memory_list.size());
+ for (const auto &memory_desc : memory_list) {
+ if (memory_desc.memory.data_size == 0)
+ continue;
+ MemoryRegionInfo region;
+ region.GetRange().SetRangeBase(memory_desc.start_of_memory_range);
+ region.GetRange().SetByteSize(memory_desc.memory.data_size);
+ region.SetReadable(MemoryRegionInfo::eYes);
+ region.SetMapped(MemoryRegionInfo::eYes);
+ regions.push_back(region);
+ }
+ regions.shrink_to_fit();
+ return !regions.empty();
+}
- const MinidumpMemoryInfo *next_entry = nullptr;
- for (const auto &entry : mem_info_list) {
- const auto head = entry->base_address;
- const auto tail = head + entry->region_size;
-
- if (head <= load_addr && load_addr < tail) {
- info.GetRange().SetRangeBase(
- (entry->state != uint32_t(MinidumpMemoryInfoState::MemFree))
- ? head
- : load_addr);
- info.GetRange().SetRangeEnd(tail);
-
- const uint32_t PageNoAccess =
- static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageNoAccess);
- info.SetReadable((entry->protect & PageNoAccess) == 0 ? yes : no);
-
- const uint32_t PageWritable =
- static_cast<uint32_t>(MinidumpMemoryProtectionContants::PageWritable);
- info.SetWritable((entry->protect & PageWritable) != 0 ? yes : no);
-
- const uint32_t PageExecutable = static_cast<uint32_t>(
- MinidumpMemoryProtectionContants::PageExecutable);
- info.SetExecutable((entry->protect & PageExecutable) != 0 ? yes : no);
-
- const uint32_t MemFree =
- static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree);
- info.SetMapped((entry->state != MemFree) ? yes : no);
-
- return info;
- } else if (head > load_addr &&
- (next_entry == nullptr || head < next_entry->base_address)) {
- // In case there is no region containing load_addr keep track of the
- // nearest region after load_addr so we can return the distance to it.
- next_entry = entry;
- }
+static bool
+CreateRegionsCacheFromMemory64List(MinidumpParser &parser,
+ std::vector<MemoryRegionInfo> &regions) {
+ llvm::ArrayRef<uint8_t> data =
+ parser.GetStream(MinidumpStreamType::Memory64List);
+ if (data.empty())
+ return false;
+ llvm::ArrayRef<MinidumpMemoryDescriptor64> memory64_list;
+ uint64_t base_rva;
+ std::tie(memory64_list, base_rva) =
+ MinidumpMemoryDescriptor64::ParseMemory64List(data);
+
+ if (memory64_list.empty())
+ return false;
+
+ regions.reserve(memory64_list.size());
+ for (const auto &memory_desc : memory64_list) {
+ if (memory_desc.data_size == 0)
+ continue;
+ MemoryRegionInfo region;
+ region.GetRange().SetRangeBase(memory_desc.start_of_memory_range);
+ region.GetRange().SetByteSize(memory_desc.data_size);
+ region.SetReadable(MemoryRegionInfo::eYes);
+ region.SetMapped(MemoryRegionInfo::eYes);
+ regions.push_back(region);
}
+ regions.shrink_to_fit();
+ return !regions.empty();
+}
+
+MemoryRegionInfo
+MinidumpParser::FindMemoryRegion(lldb::addr_t load_addr) const {
+ auto begin = m_regions.begin();
+ auto end = m_regions.end();
+ auto pos = std::lower_bound(begin, end, load_addr);
+ if (pos != end && pos->GetRange().Contains(load_addr))
+ return *pos;
+
+ MemoryRegionInfo region;
+ if (pos == begin)
+ region.GetRange().SetRangeBase(0);
+ else {
+ auto prev = pos - 1;
+ if (prev->GetRange().Contains(load_addr))
+ return *prev;
+ region.GetRange().SetRangeBase(prev->GetRange().GetRangeEnd());
+ }
+ if (pos == end)
+ region.GetRange().SetRangeEnd(UINT64_MAX);
+ else
+ region.GetRange().SetRangeEnd(pos->GetRange().GetRangeBase());
+ region.SetReadable(MemoryRegionInfo::eNo);
+ region.SetWritable(MemoryRegionInfo::eNo);
+ region.SetExecutable(MemoryRegionInfo::eNo);
+ region.SetMapped(MemoryRegionInfo::eNo);
+ return region;
+}
- // No containing region found. Create an unmapped region that extends to the
- // next region or LLDB_INVALID_ADDRESS
- info.GetRange().SetRangeBase(load_addr);
- info.GetRange().SetRangeEnd((next_entry != nullptr) ? next_entry->base_address
- : LLDB_INVALID_ADDRESS);
- info.SetReadable(no);
- info.SetWritable(no);
- info.SetExecutable(no);
- info.SetMapped(no);
-
- // Note that the memory info list doesn't seem to contain ranges in kernel
- // space, so if you're walking a stack that has kernel frames, the stack may
- // appear truncated.
- return info;
+MemoryRegionInfo
+MinidumpParser::GetMemoryRegionInfo(lldb::addr_t load_addr) {
+ if (!m_parsed_regions)
+ GetMemoryRegions();
+ return FindMemoryRegion(load_addr);
+}
+
+const MemoryRegionInfos &MinidumpParser::GetMemoryRegions() {
+ if (!m_parsed_regions) {
+ m_parsed_regions = true;
+ // We haven't cached our memory regions yet we will create the region cache
+ // once. We create the region cache using the best source. We start with
+ // the linux maps since they are the most complete and have names for the
+ // regions. Next we try the MemoryInfoList since it has
+ // read/write/execute/map data, and then fall back to the MemoryList and
+ // Memory64List to just get a list of the memory that is mapped in this
+ // core file
+ if (!CreateRegionsCacheFromLinuxMaps(*this, m_regions))
+ if (!CreateRegionsCacheFromMemoryInfoList(*this, m_regions))
+ if (!CreateRegionsCacheFromMemoryList(*this, m_regions))
+ CreateRegionsCacheFromMemory64List(*this, m_regions);
+ llvm::sort(m_regions.begin(), m_regions.end());
+ }
+ return m_regions;
}
Status MinidumpParser::Initialize() {
@@ -531,10 +646,10 @@ Status MinidumpParser::Initialize() {
}
// Sort the file map ranges by start offset
- std::sort(minidump_map.begin(), minidump_map.end(),
- [](const FileRange &a, const FileRange &b) {
- return a.offset < b.offset;
- });
+ llvm::sort(minidump_map.begin(), minidump_map.end(),
+ [](const FileRange &a, const FileRange &b) {
+ return a.offset < b.offset;
+ });
// Check for overlapping streams/data structures
for (size_t i = 1; i < minidump_map.size(); ++i) {
@@ -554,3 +669,48 @@ Status MinidumpParser::Initialize() {
return error;
}
+
+#define ENUM_TO_CSTR(ST) case (uint32_t)MinidumpStreamType::ST: return #ST
+
+llvm::StringRef
+MinidumpParser::GetStreamTypeAsString(uint32_t stream_type) {
+ switch (stream_type) {
+ ENUM_TO_CSTR(Unused);
+ ENUM_TO_CSTR(Reserved0);
+ ENUM_TO_CSTR(Reserved1);
+ ENUM_TO_CSTR(ThreadList);
+ ENUM_TO_CSTR(ModuleList);
+ ENUM_TO_CSTR(MemoryList);
+ ENUM_TO_CSTR(Exception);
+ ENUM_TO_CSTR(SystemInfo);
+ ENUM_TO_CSTR(ThreadExList);
+ ENUM_TO_CSTR(Memory64List);
+ ENUM_TO_CSTR(CommentA);
+ ENUM_TO_CSTR(CommentW);
+ ENUM_TO_CSTR(HandleData);
+ ENUM_TO_CSTR(FunctionTable);
+ ENUM_TO_CSTR(UnloadedModuleList);
+ ENUM_TO_CSTR(MiscInfo);
+ ENUM_TO_CSTR(MemoryInfoList);
+ ENUM_TO_CSTR(ThreadInfoList);
+ ENUM_TO_CSTR(HandleOperationList);
+ ENUM_TO_CSTR(Token);
+ ENUM_TO_CSTR(JavascriptData);
+ ENUM_TO_CSTR(SystemMemoryInfo);
+ ENUM_TO_CSTR(ProcessVMCounters);
+ ENUM_TO_CSTR(BreakpadInfo);
+ ENUM_TO_CSTR(AssertionInfo);
+ ENUM_TO_CSTR(LinuxCPUInfo);
+ ENUM_TO_CSTR(LinuxProcStatus);
+ ENUM_TO_CSTR(LinuxLSBRelease);
+ ENUM_TO_CSTR(LinuxCMDLine);
+ ENUM_TO_CSTR(LinuxEnviron);
+ ENUM_TO_CSTR(LinuxAuxv);
+ ENUM_TO_CSTR(LinuxMaps);
+ ENUM_TO_CSTR(LinuxDSODebug);
+ ENUM_TO_CSTR(LinuxProcStat);
+ ENUM_TO_CSTR(LinuxProcUptime);
+ ENUM_TO_CSTR(LinuxProcFD);
+ }
+ return "unknown stream type";
+}
diff --git a/source/Plugins/Process/minidump/MinidumpParser.h b/source/Plugins/Process/minidump/MinidumpParser.h
index 49b1eef14de5..07ea6aa908ff 100644
--- a/source/Plugins/Process/minidump/MinidumpParser.h
+++ b/source/Plugins/Process/minidump/MinidumpParser.h
@@ -1,5 +1,4 @@
-//===-- MinidumpParser.h -----------------------------------------*- C++
-//-*-===//
+//===-- MinidumpParser.h -----------------------------------------*- C++-*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -11,9 +10,9 @@
#ifndef liblldb_MinidumpParser_h_
#define liblldb_MinidumpParser_h_
-// Project includes
#include "MinidumpTypes.h"
+#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/Status.h"
@@ -59,6 +58,9 @@ public:
llvm::ArrayRef<MinidumpThread> GetThreads();
+ llvm::ArrayRef<uint8_t>
+ GetThreadContext(const MinidumpLocationDescriptor &location);
+
llvm::ArrayRef<uint8_t> GetThreadContext(const MinidumpThread &td);
llvm::ArrayRef<uint8_t> GetThreadContextWow64(const MinidumpThread &td);
@@ -87,17 +89,31 @@ public:
llvm::ArrayRef<uint8_t> GetMemory(lldb::addr_t addr, size_t size);
- llvm::Optional<MemoryRegionInfo> GetMemoryRegionInfo(lldb::addr_t);
+ MemoryRegionInfo GetMemoryRegionInfo(lldb::addr_t load_addr);
+
+ const MemoryRegionInfos &GetMemoryRegions();
// Perform consistency checks and initialize internal data structures
Status Initialize();
+ static llvm::StringRef GetStreamTypeAsString(uint32_t stream_type);
+
+ const llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> &
+ GetDirectoryMap() const {
+ return m_directory_map;
+ }
+
private:
MinidumpParser(const lldb::DataBufferSP &data_buf_sp);
+ MemoryRegionInfo FindMemoryRegion(lldb::addr_t load_addr) const;
+
private:
lldb::DataBufferSP m_data_sp;
llvm::DenseMap<uint32_t, MinidumpLocationDescriptor> m_directory_map;
+ ArchSpec m_arch;
+ MemoryRegionInfos m_regions;
+ bool m_parsed_regions = false;
};
} // end namespace minidump
diff --git a/source/Plugins/Process/minidump/MinidumpTypes.cpp b/source/Plugins/Process/minidump/MinidumpTypes.cpp
index 049704ba80ca..7b1900e34ef1 100644
--- a/source/Plugins/Process/minidump/MinidumpTypes.cpp
+++ b/source/Plugins/Process/minidump/MinidumpTypes.cpp
@@ -7,10 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "MinidumpTypes.h"
-// Other libraries and framework includes
// C includes
// C++ includes
@@ -244,6 +242,8 @@ MinidumpMemoryInfo::ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data) {
return {};
std::vector<const MinidumpMemoryInfo *> result;
+ result.reserve(header->num_of_entries);
+
for (uint64_t i = 0; i < header->num_of_entries; ++i) {
result.push_back(reinterpret_cast<const MinidumpMemoryInfo *>(
data.data() + i * header->size_of_entry));
diff --git a/source/Plugins/Process/minidump/MinidumpTypes.h b/source/Plugins/Process/minidump/MinidumpTypes.h
index e83089865b9e..a5ea215d2548 100644
--- a/source/Plugins/Process/minidump/MinidumpTypes.h
+++ b/source/Plugins/Process/minidump/MinidumpTypes.h
@@ -10,9 +10,7 @@
#ifndef liblldb_MinidumpTypes_h_
#define liblldb_MinidumpTypes_h_
-// Project includes
-// Other libraries and framework includes
#include "lldb/Utility/Status.h"
#include "llvm/ADT/ArrayRef.h"
@@ -98,7 +96,10 @@ enum class MinidumpStreamType : uint32_t {
LinuxEnviron = 0x47670007, /* /proc/$x/environ */
LinuxAuxv = 0x47670008, /* /proc/$x/auxv */
LinuxMaps = 0x47670009, /* /proc/$x/maps */
- LinuxDSODebug = 0x4767000A
+ LinuxDSODebug = 0x4767000A,
+ LinuxProcStat = 0x4767000B, /* /proc/$x/stat */
+ LinuxProcUptime = 0x4767000C, /* uptime */
+ LinuxProcFD = 0x4767000D, /* /proc/$x/fb */
};
// for MinidumpSystemInfo.processor_arch
@@ -258,25 +259,6 @@ struct MinidumpMemoryInfoListHeader {
static_assert(sizeof(MinidumpMemoryInfoListHeader) == 16,
"sizeof MinidumpMemoryInfoListHeader is not correct!");
-// Reference:
-// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx
-struct MinidumpMemoryInfo {
- llvm::support::ulittle64_t base_address;
- llvm::support::ulittle64_t allocation_base;
- llvm::support::ulittle32_t allocation_protect;
- llvm::support::ulittle32_t alignment1;
- llvm::support::ulittle64_t region_size;
- llvm::support::ulittle32_t state;
- llvm::support::ulittle32_t protect;
- llvm::support::ulittle32_t type;
- llvm::support::ulittle32_t alignment2;
-
- static std::vector<const MinidumpMemoryInfo *>
- ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data);
-};
-static_assert(sizeof(MinidumpMemoryInfo) == 48,
- "sizeof MinidumpMemoryInfo is not correct!");
-
enum class MinidumpMemoryInfoState : uint32_t {
MemCommit = 0x1000,
MemFree = 0x10000,
@@ -313,6 +295,45 @@ enum class MinidumpMemoryProtectionContants : uint32_t {
};
// Reference:
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680386(v=vs.85).aspx
+struct MinidumpMemoryInfo {
+ llvm::support::ulittle64_t base_address;
+ llvm::support::ulittle64_t allocation_base;
+ llvm::support::ulittle32_t allocation_protect;
+ llvm::support::ulittle32_t alignment1;
+ llvm::support::ulittle64_t region_size;
+ llvm::support::ulittle32_t state;
+ llvm::support::ulittle32_t protect;
+ llvm::support::ulittle32_t type;
+ llvm::support::ulittle32_t alignment2;
+
+ static std::vector<const MinidumpMemoryInfo *>
+ ParseMemoryInfoList(llvm::ArrayRef<uint8_t> &data);
+
+ bool isReadable() const {
+ const auto mask = MinidumpMemoryProtectionContants::PageNoAccess;
+ return (static_cast<uint32_t>(mask) & protect) == 0;
+ }
+
+ bool isWritable() const {
+ const auto mask = MinidumpMemoryProtectionContants::PageWritable;
+ return (static_cast<uint32_t>(mask) & protect) != 0;
+ }
+
+ bool isExecutable() const {
+ const auto mask = MinidumpMemoryProtectionContants::PageExecutable;
+ return (static_cast<uint32_t>(mask) & protect) != 0;
+ }
+
+ bool isMapped() const {
+ return state != static_cast<uint32_t>(MinidumpMemoryInfoState::MemFree);
+ }
+};
+
+static_assert(sizeof(MinidumpMemoryInfo) == 48,
+ "sizeof MinidumpMemoryInfo is not correct!");
+
+// Reference:
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680517(v=vs.85).aspx
struct MinidumpThread {
llvm::support::ulittle32_t thread_id;
diff --git a/source/Plugins/Process/minidump/ProcessMinidump.cpp b/source/Plugins/Process/minidump/ProcessMinidump.cpp
index b43f22382eac..c5cca7ea62c6 100644
--- a/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -7,28 +7,34 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "ProcessMinidump.h"
#include "ThreadMinidump.h"
-// Other libraries and framework includes
+#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Section.h"
-#include "lldb/Core/State.h"
-#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/OptionArgParser.h"
+#include "lldb/Interpreter/OptionGroupBoolean.h"
+#include "lldb/Target/JITLoaderList.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Threading.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
+
// C includes
// C++ includes
@@ -75,7 +81,7 @@ public:
section_sp, module->base_of_image);
}
- ObjectFile *GetObjectFile() override { return nullptr; }
+ObjectFile *GetObjectFile() override { return nullptr; }
SectionList *GetSectionList() override {
return Module::GetUnifiedSectionList();
@@ -100,8 +106,8 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp,
lldb::ProcessSP process_sp;
// Read enough data for the Minidump header
constexpr size_t header_size = sizeof(MinidumpHeader);
- auto DataPtr =
- DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), header_size, 0);
+ auto DataPtr = FileSystem::Instance().CreateDataBuffer(crash_file->GetPath(),
+ header_size, 0);
if (!DataPtr)
return nullptr;
@@ -113,7 +119,8 @@ lldb::ProcessSP ProcessMinidump::CreateInstance(lldb::TargetSP target_sp,
if (header == nullptr)
return nullptr;
- auto AllData = DataBufferLLVM::CreateSliceFromPath(crash_file->GetPath(), -1, 0);
+ auto AllData =
+ FileSystem::Instance().CreateDataBuffer(crash_file->GetPath(), -1, 0);
if (!AllData)
return nullptr;
@@ -174,19 +181,21 @@ Status ProcessMinidump::DoLoadCore() {
switch (arch.GetMachine()) {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
- // supported
+ case llvm::Triple::arm:
+ case llvm::Triple::aarch64:
+ // Any supported architectures must be listed here and also supported in
+ // ThreadMinidump::CreateRegisterContextForFrame().
break;
-
default:
error.SetErrorStringWithFormat("unsupported minidump architecture: %s",
arch.GetArchitectureName());
return error;
}
+ GetTarget().SetArchitecture(arch, true /*set_platform*/);
m_thread_list = m_minidump_parser.GetThreads();
m_active_exception = m_minidump_parser.GetExceptionStream();
ReadModuleList();
- GetTarget().SetArchitecture(arch);
llvm::Optional<lldb::pid_t> pid = m_minidump_parser.GetPid();
if (!pid) {
@@ -198,12 +207,6 @@ Status ProcessMinidump::DoLoadCore() {
return error;
}
-DynamicLoader *ProcessMinidump::GetDynamicLoader() {
- if (m_dyld_ap.get() == nullptr)
- m_dyld_ap.reset(DynamicLoader::FindPlugin(this, nullptr));
- return m_dyld_ap.get();
-}
-
ConstString ProcessMinidump::GetPluginName() { return GetPluginNameStatic(); }
uint32_t ProcessMinidump::GetPluginVersion() { return 1; }
@@ -229,6 +232,11 @@ void ProcessMinidump::RefreshStateAfterStop() {
if (arch.GetTriple().getOS() == llvm::Triple::Linux) {
stop_info = StopInfo::CreateStopReasonWithSignal(
*stop_thread, m_active_exception->exception_record.exception_code);
+ } else if (arch.GetTriple().getVendor() == llvm::Triple::Apple) {
+ stop_info = StopInfoMachException::CreateStopReasonWithMachException(
+ *stop_thread, m_active_exception->exception_record.exception_code, 2,
+ m_active_exception->exception_record.exception_flags,
+ m_active_exception->exception_record.exception_address, 0);
} else {
std::string desc;
llvm::raw_string_ostream desc_stream(desc);
@@ -284,33 +292,36 @@ ArchSpec ProcessMinidump::GetArchitecture() {
Status ProcessMinidump::GetMemoryRegionInfo(lldb::addr_t load_addr,
MemoryRegionInfo &range_info) {
- Status error;
- auto info = m_minidump_parser.GetMemoryRegionInfo(load_addr);
- if (!info) {
- error.SetErrorString("No valid MemoryRegionInfo found!");
- return error;
- }
- range_info = info.getValue();
- return error;
+ range_info = m_minidump_parser.GetMemoryRegionInfo(load_addr);
+ return Status();
+}
+
+Status ProcessMinidump::GetMemoryRegions(
+ lldb_private::MemoryRegionInfos &region_list) {
+ region_list = m_minidump_parser.GetMemoryRegions();
+ return Status();
}
void ProcessMinidump::Clear() { Process::m_thread_list.Clear(); }
bool ProcessMinidump::UpdateThreadList(ThreadList &old_thread_list,
ThreadList &new_thread_list) {
- uint32_t num_threads = 0;
- if (m_thread_list.size() > 0)
- num_threads = m_thread_list.size();
+ for (const MinidumpThread& thread : m_thread_list) {
+ MinidumpLocationDescriptor context_location = thread.thread_context;
+
+ // If the minidump contains an exception context, use it
+ if (m_active_exception != nullptr &&
+ m_active_exception->thread_id == thread.thread_id) {
+ context_location = m_active_exception->thread_context;
+ }
- for (lldb::tid_t tid = 0; tid < num_threads; ++tid) {
llvm::ArrayRef<uint8_t> context;
if (!m_is_wow64)
- context = m_minidump_parser.GetThreadContext(m_thread_list[tid]);
+ context = m_minidump_parser.GetThreadContext(context_location);
else
- context = m_minidump_parser.GetThreadContextWow64(m_thread_list[tid]);
+ context = m_minidump_parser.GetThreadContextWow64(thread);
- lldb::ThreadSP thread_sp(
- new ThreadMinidump(*this, m_thread_list[tid], context));
+ lldb::ThreadSP thread_sp(new ThreadMinidump(*this, thread, context));
new_thread_list.AddThread(thread_sp);
}
return new_thread_list.GetSize(false) > 0;
@@ -344,8 +355,8 @@ void ProcessMinidump::ReadModuleList() {
}
const auto uuid = m_minidump_parser.GetModuleUUID(module);
- const auto file_spec =
- FileSpec(name.getValue(), true, GetArchitecture().GetTriple());
+ auto file_spec = FileSpec(name.getValue(), GetArchitecture().GetTriple());
+ FileSystem::Instance().Resolve(file_spec);
ModuleSpec module_spec(file_spec, uuid);
Status error;
lldb::ModuleSP module_sp = GetTarget().GetSharedModule(module_spec, &error);
@@ -357,6 +368,12 @@ void ProcessMinidump::ReadModuleList() {
// This enables most LLDB functionality involving address-to-module
// translations (ex. identifing the module for a stack frame PC) and
// modules/sections commands (ex. target modules list, ...)
+ if (log) {
+ log->Printf("Unable to locate the matching object file, creating a "
+ "placeholder module for: %s",
+ name.getValue().c_str());
+ }
+
auto placeholder_module =
std::make_shared<PlaceholderModule>(module_spec);
placeholder_module->CreateImageSection(module, GetTarget());
@@ -387,3 +404,248 @@ bool ProcessMinidump::GetProcessInfo(ProcessInstanceInfo &info) {
}
return true;
}
+
+// For minidumps there's no runtime generated code so we don't need JITLoader(s)
+// Avoiding them will also speed up minidump loading since JITLoaders normally
+// try to set up symbolic breakpoints, which in turn may force loading more
+// debug information than needed.
+JITLoaderList &ProcessMinidump::GetJITLoaders() {
+ if (!m_jit_loaders_ap) {
+ m_jit_loaders_ap = llvm::make_unique<JITLoaderList>();
+ }
+ return *m_jit_loaders_ap;
+}
+
+#define INIT_BOOL(VAR, LONG, SHORT, DESC) \
+ VAR(LLDB_OPT_SET_1, false, LONG, SHORT, DESC, false, true)
+#define APPEND_OPT(VAR) \
+ m_option_group.Append(&VAR, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1)
+
+class CommandObjectProcessMinidumpDump : public CommandObjectParsed {
+private:
+ OptionGroupOptions m_option_group;
+ OptionGroupBoolean m_dump_all;
+ OptionGroupBoolean m_dump_directory;
+ OptionGroupBoolean m_dump_linux_cpuinfo;
+ OptionGroupBoolean m_dump_linux_proc_status;
+ OptionGroupBoolean m_dump_linux_lsb_release;
+ OptionGroupBoolean m_dump_linux_cmdline;
+ OptionGroupBoolean m_dump_linux_environ;
+ OptionGroupBoolean m_dump_linux_auxv;
+ OptionGroupBoolean m_dump_linux_maps;
+ OptionGroupBoolean m_dump_linux_proc_stat;
+ OptionGroupBoolean m_dump_linux_proc_uptime;
+ OptionGroupBoolean m_dump_linux_proc_fd;
+ OptionGroupBoolean m_dump_linux_all;
+
+ void SetDefaultOptionsIfNoneAreSet() {
+ if (m_dump_all.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_all.GetOptionValue().GetCurrentValue() ||
+ m_dump_directory.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_cpuinfo.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_proc_status.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_lsb_release.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_cmdline.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_environ.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_auxv.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_maps.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_proc_stat.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_proc_uptime.GetOptionValue().GetCurrentValue() ||
+ m_dump_linux_proc_fd.GetOptionValue().GetCurrentValue())
+ return;
+ // If no options were set, then dump everything
+ m_dump_all.GetOptionValue().SetCurrentValue(true);
+ }
+ bool DumpAll() const {
+ return m_dump_all.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpDirectory() const {
+ return DumpAll() ||
+ m_dump_directory.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinux() const {
+ return DumpAll() || m_dump_linux_all.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxCPUInfo() const {
+ return DumpLinux() ||
+ m_dump_linux_cpuinfo.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxProcStatus() const {
+ return DumpLinux() ||
+ m_dump_linux_proc_status.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxProcStat() const {
+ return DumpLinux() ||
+ m_dump_linux_proc_stat.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxLSBRelease() const {
+ return DumpLinux() ||
+ m_dump_linux_lsb_release.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxCMDLine() const {
+ return DumpLinux() ||
+ m_dump_linux_cmdline.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxEnviron() const {
+ return DumpLinux() ||
+ m_dump_linux_environ.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxAuxv() const {
+ return DumpLinux() ||
+ m_dump_linux_auxv.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxMaps() const {
+ return DumpLinux() ||
+ m_dump_linux_maps.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxProcUptime() const {
+ return DumpLinux() ||
+ m_dump_linux_proc_uptime.GetOptionValue().GetCurrentValue();
+ }
+ bool DumpLinuxProcFD() const {
+ return DumpLinux() ||
+ m_dump_linux_proc_fd.GetOptionValue().GetCurrentValue();
+ }
+public:
+
+ CommandObjectProcessMinidumpDump(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin dump",
+ "Dump information from the minidump file.", NULL),
+ m_option_group(),
+ INIT_BOOL(m_dump_all, "all", 'a',
+ "Dump the everything in the minidump."),
+ INIT_BOOL(m_dump_directory, "directory", 'd',
+ "Dump the minidump directory map."),
+ INIT_BOOL(m_dump_linux_cpuinfo, "cpuinfo", 'C',
+ "Dump linux /proc/cpuinfo."),
+ INIT_BOOL(m_dump_linux_proc_status, "status", 's',
+ "Dump linux /proc/<pid>/status."),
+ INIT_BOOL(m_dump_linux_lsb_release, "lsb-release", 'r',
+ "Dump linux /etc/lsb-release."),
+ INIT_BOOL(m_dump_linux_cmdline, "cmdline", 'c',
+ "Dump linux /proc/<pid>/cmdline."),
+ INIT_BOOL(m_dump_linux_environ, "environ", 'e',
+ "Dump linux /proc/<pid>/environ."),
+ INIT_BOOL(m_dump_linux_auxv, "auxv", 'x',
+ "Dump linux /proc/<pid>/auxv."),
+ INIT_BOOL(m_dump_linux_maps, "maps", 'm',
+ "Dump linux /proc/<pid>/maps."),
+ INIT_BOOL(m_dump_linux_proc_stat, "stat", 'S',
+ "Dump linux /proc/<pid>/stat."),
+ INIT_BOOL(m_dump_linux_proc_uptime, "uptime", 'u',
+ "Dump linux process uptime."),
+ INIT_BOOL(m_dump_linux_proc_fd, "fd", 'f',
+ "Dump linux /proc/<pid>/fd."),
+ INIT_BOOL(m_dump_linux_all, "linux", 'l',
+ "Dump all linux streams.") {
+ APPEND_OPT(m_dump_all);
+ APPEND_OPT(m_dump_directory);
+ APPEND_OPT(m_dump_linux_cpuinfo);
+ APPEND_OPT(m_dump_linux_proc_status);
+ APPEND_OPT(m_dump_linux_lsb_release);
+ APPEND_OPT(m_dump_linux_cmdline);
+ APPEND_OPT(m_dump_linux_environ);
+ APPEND_OPT(m_dump_linux_auxv);
+ APPEND_OPT(m_dump_linux_maps);
+ APPEND_OPT(m_dump_linux_proc_stat);
+ APPEND_OPT(m_dump_linux_proc_uptime);
+ APPEND_OPT(m_dump_linux_proc_fd);
+ APPEND_OPT(m_dump_linux_all);
+ m_option_group.Finalize();
+ }
+
+ ~CommandObjectProcessMinidumpDump() {}
+
+ Options *GetOptions() override { return &m_option_group; }
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc > 0) {
+ result.AppendErrorWithFormat("'%s' take no arguments, only options",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ SetDefaultOptionsIfNoneAreSet();
+
+ ProcessMinidump *process = static_cast<ProcessMinidump *>(
+ m_interpreter.GetExecutionContext().GetProcessPtr());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ Stream &s = result.GetOutputStream();
+ MinidumpParser &minidump = process->m_minidump_parser;
+ if (DumpDirectory()) {
+ s.Printf("RVA SIZE TYPE MinidumpStreamType\n");
+ s.Printf("---------- ---------- ---------- --------------------------\n");
+ for (const auto &pair: minidump.GetDirectoryMap())
+ s.Printf("0x%8.8x 0x%8.8x 0x%8.8x %s\n", (uint32_t)pair.second.rva,
+ (uint32_t)pair.second.data_size, pair.first,
+ MinidumpParser::GetStreamTypeAsString(pair.first).data());
+ s.Printf("\n");
+ }
+ auto DumpTextStream = [&](MinidumpStreamType stream_type,
+ llvm::StringRef label) -> void {
+ auto bytes = minidump.GetStream(stream_type);
+ if (!bytes.empty()) {
+ if (label.empty())
+ label = MinidumpParser::GetStreamTypeAsString((uint32_t)stream_type);
+ s.Printf("%s:\n%s\n\n", label.data(), bytes.data());
+ }
+ };
+ auto DumpBinaryStream = [&](MinidumpStreamType stream_type,
+ llvm::StringRef label) -> void {
+ auto bytes = minidump.GetStream(stream_type);
+ if (!bytes.empty()) {
+ if (label.empty())
+ label = MinidumpParser::GetStreamTypeAsString((uint32_t)stream_type);
+ s.Printf("%s:\n", label.data());
+ DataExtractor data(bytes.data(), bytes.size(), eByteOrderLittle,
+ process->GetAddressByteSize());
+ DumpDataExtractor(data, &s, 0, lldb::eFormatBytesWithASCII, 1,
+ bytes.size(), 16, 0, 0, 0);
+ s.Printf("\n\n");
+ }
+ };
+
+ if (DumpLinuxCPUInfo())
+ DumpTextStream(MinidumpStreamType::LinuxCPUInfo, "/proc/cpuinfo");
+ if (DumpLinuxProcStatus())
+ DumpTextStream(MinidumpStreamType::LinuxProcStatus, "/proc/PID/status");
+ if (DumpLinuxLSBRelease())
+ DumpTextStream(MinidumpStreamType::LinuxLSBRelease, "/etc/lsb-release");
+ if (DumpLinuxCMDLine())
+ DumpTextStream(MinidumpStreamType::LinuxCMDLine, "/proc/PID/cmdline");
+ if (DumpLinuxEnviron())
+ DumpTextStream(MinidumpStreamType::LinuxEnviron, "/proc/PID/environ");
+ if (DumpLinuxAuxv())
+ DumpBinaryStream(MinidumpStreamType::LinuxAuxv, "/proc/PID/auxv");
+ if (DumpLinuxMaps())
+ DumpTextStream(MinidumpStreamType::LinuxMaps, "/proc/PID/maps");
+ if (DumpLinuxProcStat())
+ DumpTextStream(MinidumpStreamType::LinuxProcStat, "/proc/PID/stat");
+ if (DumpLinuxProcUptime())
+ DumpTextStream(MinidumpStreamType::LinuxProcUptime, "uptime");
+ if (DumpLinuxProcFD())
+ DumpTextStream(MinidumpStreamType::LinuxProcFD, "/proc/PID/fd");
+ return true;
+ }
+};
+
+class CommandObjectMultiwordProcessMinidump : public CommandObjectMultiword {
+public:
+ CommandObjectMultiwordProcessMinidump(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "process plugin",
+ "Commands for operating on a ProcessMinidump process.",
+ "process plugin <subcommand> [<subcommand-options>]") {
+ LoadSubCommand("dump",
+ CommandObjectSP(new CommandObjectProcessMinidumpDump(interpreter)));
+ }
+
+ ~CommandObjectMultiwordProcessMinidump() {}
+};
+
+CommandObject *ProcessMinidump::GetPluginCommandObject() {
+ if (!m_command_sp)
+ m_command_sp.reset(new CommandObjectMultiwordProcessMinidump(
+ GetTarget().GetDebugger().GetCommandInterpreter()));
+ return m_command_sp.get();
+}
diff --git a/source/Plugins/Process/minidump/ProcessMinidump.h b/source/Plugins/Process/minidump/ProcessMinidump.h
index d65ada9009a7..30347b79e1c1 100644
--- a/source/Plugins/Process/minidump/ProcessMinidump.h
+++ b/source/Plugins/Process/minidump/ProcessMinidump.h
@@ -10,11 +10,9 @@
#ifndef liblldb_ProcessMinidump_h_
#define liblldb_ProcessMinidump_h_
-// Project includes
#include "MinidumpParser.h"
#include "MinidumpTypes.h"
-// Other libraries and framework includes
#include "lldb/Target/Process.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
@@ -24,8 +22,6 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
-// C Includes
-// C++ Includes
namespace lldb_private {
@@ -53,9 +49,11 @@ public:
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
+ CommandObject *GetPluginCommandObject() override;
+
Status DoLoadCore() override;
- DynamicLoader *GetDynamicLoader() override;
+ DynamicLoader *GetDynamicLoader() override { return nullptr; }
ConstString GetPluginName() override;
@@ -82,6 +80,9 @@ public:
Status GetMemoryRegionInfo(lldb::addr_t load_addr,
MemoryRegionInfo &range_info) override;
+ Status GetMemoryRegions(
+ lldb_private::MemoryRegionInfos &region_list) override;
+
bool GetProcessInfo(ProcessInstanceInfo &info) override;
Status WillResume() override {
@@ -102,10 +103,13 @@ protected:
void ReadModuleList();
+ JITLoaderList &GetJITLoaders() override;
+
private:
FileSpec m_core_file;
llvm::ArrayRef<MinidumpThread> m_thread_list;
const MinidumpExceptionStream *m_active_exception;
+ lldb::CommandObjectSP m_command_sp;
bool m_is_wow64;
};
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
new file mode 100644
index 000000000000..93c3ba70b9e7
--- /dev/null
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.cpp
@@ -0,0 +1,532 @@
+//===-- RegisterContextMinidump_ARM.cpp -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMinidump_ARM.h"
+
+#include "Utility/ARM_DWARF_Registers.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/lldb-enumerations.h"
+
+// C includes
+#include <assert.h>
+
+// C++ includes
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace minidump;
+
+#define INV LLDB_INVALID_REGNUM
+#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM::Context, r))
+
+#define DEF_R(i) \
+ { \
+ "r" #i, nullptr, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \
+ {INV, dwarf_r##i, INV, INV, reg_r##i}, nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_R_ARG(i, n) \
+ { \
+ "r" #i, "arg" #n, 4, OFFSET(r) + i * 4, eEncodingUint, eFormatHex, \
+ {INV, dwarf_r##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_r##i}, \
+ nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_D(i) \
+ { \
+ "d" #i, nullptr, 8, OFFSET(d) + i * 8, eEncodingVector, \
+ eFormatVectorOfUInt8, {INV, dwarf_d##i, INV, INV, reg_d##i}, \
+ nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_S(i) \
+ { \
+ "s" #i, nullptr, 4, OFFSET(s) + i * 4, eEncodingIEEE754, eFormatFloat, \
+ {INV, dwarf_s##i, INV, INV, reg_s##i}, nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_Q(i) \
+ { \
+ "q" #i, nullptr, 16, OFFSET(q) + i * 16, eEncodingVector, \
+ eFormatVectorOfUInt8, {INV, dwarf_q##i, INV, INV, reg_q##i}, \
+ nullptr, nullptr, nullptr, 0 \
+ }
+
+// Zero based LLDB register numbers for this register context
+enum {
+ // General Purpose Registers
+ reg_r0,
+ reg_r1,
+ reg_r2,
+ reg_r3,
+ reg_r4,
+ reg_r5,
+ reg_r6,
+ reg_r7,
+ reg_r8,
+ reg_r9,
+ reg_r10,
+ reg_r11,
+ reg_r12,
+ reg_sp,
+ reg_lr,
+ reg_pc,
+ reg_cpsr,
+ // Floating Point Registers
+ reg_fpscr,
+ reg_d0,
+ reg_d1,
+ reg_d2,
+ reg_d3,
+ reg_d4,
+ reg_d5,
+ reg_d6,
+ reg_d7,
+ reg_d8,
+ reg_d9,
+ reg_d10,
+ reg_d11,
+ reg_d12,
+ reg_d13,
+ reg_d14,
+ reg_d15,
+ reg_d16,
+ reg_d17,
+ reg_d18,
+ reg_d19,
+ reg_d20,
+ reg_d21,
+ reg_d22,
+ reg_d23,
+ reg_d24,
+ reg_d25,
+ reg_d26,
+ reg_d27,
+ reg_d28,
+ reg_d29,
+ reg_d30,
+ reg_d31,
+ reg_s0,
+ reg_s1,
+ reg_s2,
+ reg_s3,
+ reg_s4,
+ reg_s5,
+ reg_s6,
+ reg_s7,
+ reg_s8,
+ reg_s9,
+ reg_s10,
+ reg_s11,
+ reg_s12,
+ reg_s13,
+ reg_s14,
+ reg_s15,
+ reg_s16,
+ reg_s17,
+ reg_s18,
+ reg_s19,
+ reg_s20,
+ reg_s21,
+ reg_s22,
+ reg_s23,
+ reg_s24,
+ reg_s25,
+ reg_s26,
+ reg_s27,
+ reg_s28,
+ reg_s29,
+ reg_s30,
+ reg_s31,
+ reg_q0,
+ reg_q1,
+ reg_q2,
+ reg_q3,
+ reg_q4,
+ reg_q5,
+ reg_q6,
+ reg_q7,
+ reg_q8,
+ reg_q9,
+ reg_q10,
+ reg_q11,
+ reg_q12,
+ reg_q13,
+ reg_q14,
+ reg_q15,
+ k_num_regs
+};
+
+static RegisterInfo g_reg_info_apple_fp = {
+ "fp",
+ "r7",
+ 4,
+ OFFSET(r) + 7 * 4,
+ eEncodingUint,
+ eFormatHex,
+ {INV, dwarf_r7, LLDB_REGNUM_GENERIC_FP, INV, reg_r7},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0};
+
+static RegisterInfo g_reg_info_fp = {
+ "fp",
+ "r11",
+ 4,
+ OFFSET(r) + 11 * 4,
+ eEncodingUint,
+ eFormatHex,
+ {INV, dwarf_r11, LLDB_REGNUM_GENERIC_FP, INV, reg_r11},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0};
+
+// Register info definitions for this register context
+static RegisterInfo g_reg_infos[] = {
+ DEF_R_ARG(0, 1),
+ DEF_R_ARG(1, 2),
+ DEF_R_ARG(2, 3),
+ DEF_R_ARG(3, 4),
+ DEF_R(4),
+ DEF_R(5),
+ DEF_R(6),
+ DEF_R(7),
+ DEF_R(8),
+ DEF_R(9),
+ DEF_R(10),
+ DEF_R(11),
+ DEF_R(12),
+ {"sp",
+ "r13",
+ 4,
+ OFFSET(r) + 13 * 4,
+ eEncodingUint,
+ eFormatHex,
+ {INV, dwarf_sp, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"lr",
+ "r14",
+ 4,
+ OFFSET(r) + 14 * 4,
+ eEncodingUint,
+ eFormatHex,
+ {INV, dwarf_lr, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"pc",
+ "r15",
+ 4,
+ OFFSET(r) + 15 * 4,
+ eEncodingUint,
+ eFormatHex,
+ {INV, dwarf_pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"cpsr",
+ "psr",
+ 4,
+ OFFSET(cpsr),
+ eEncodingUint,
+ eFormatHex,
+ {INV, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"fpscr",
+ nullptr,
+ 8,
+ OFFSET(fpscr),
+ eEncodingUint,
+ eFormatHex,
+ {INV, INV, INV, INV, reg_fpscr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ DEF_D(0),
+ DEF_D(1),
+ DEF_D(2),
+ DEF_D(3),
+ DEF_D(4),
+ DEF_D(5),
+ DEF_D(6),
+ DEF_D(7),
+ DEF_D(8),
+ DEF_D(9),
+ DEF_D(10),
+ DEF_D(11),
+ DEF_D(12),
+ DEF_D(13),
+ DEF_D(14),
+ DEF_D(15),
+ DEF_D(16),
+ DEF_D(17),
+ DEF_D(18),
+ DEF_D(19),
+ DEF_D(20),
+ DEF_D(21),
+ DEF_D(22),
+ DEF_D(23),
+ DEF_D(24),
+ DEF_D(25),
+ DEF_D(26),
+ DEF_D(27),
+ DEF_D(28),
+ DEF_D(29),
+ DEF_D(30),
+ DEF_D(31),
+ DEF_S(0),
+ DEF_S(1),
+ DEF_S(2),
+ DEF_S(3),
+ DEF_S(4),
+ DEF_S(5),
+ DEF_S(6),
+ DEF_S(7),
+ DEF_S(8),
+ DEF_S(9),
+ DEF_S(10),
+ DEF_S(11),
+ DEF_S(12),
+ DEF_S(13),
+ DEF_S(14),
+ DEF_S(15),
+ DEF_S(16),
+ DEF_S(17),
+ DEF_S(18),
+ DEF_S(19),
+ DEF_S(20),
+ DEF_S(21),
+ DEF_S(22),
+ DEF_S(23),
+ DEF_S(24),
+ DEF_S(25),
+ DEF_S(26),
+ DEF_S(27),
+ DEF_S(28),
+ DEF_S(29),
+ DEF_S(30),
+ DEF_S(31),
+ DEF_Q(0),
+ DEF_Q(1),
+ DEF_Q(2),
+ DEF_Q(3),
+ DEF_Q(4),
+ DEF_Q(5),
+ DEF_Q(6),
+ DEF_Q(7),
+ DEF_Q(8),
+ DEF_Q(9),
+ DEF_Q(10),
+ DEF_Q(11),
+ DEF_Q(12),
+ DEF_Q(13),
+ DEF_Q(14),
+ DEF_Q(15)};
+
+constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
+
+// ARM general purpose registers.
+const uint32_t g_gpr_regnums[] = {
+ reg_r0,
+ reg_r1,
+ reg_r2,
+ reg_r3,
+ reg_r4,
+ reg_r5,
+ reg_r6,
+ reg_r7,
+ reg_r8,
+ reg_r9,
+ reg_r10,
+ reg_r11,
+ reg_r12,
+ reg_sp,
+ reg_lr,
+ reg_pc,
+ reg_cpsr,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+const uint32_t g_fpu_regnums[] = {
+ reg_fpscr,
+ reg_d0,
+ reg_d1,
+ reg_d2,
+ reg_d3,
+ reg_d4,
+ reg_d5,
+ reg_d6,
+ reg_d7,
+ reg_d8,
+ reg_d9,
+ reg_d10,
+ reg_d11,
+ reg_d12,
+ reg_d13,
+ reg_d14,
+ reg_d15,
+ reg_d16,
+ reg_d17,
+ reg_d18,
+ reg_d19,
+ reg_d20,
+ reg_d21,
+ reg_d22,
+ reg_d23,
+ reg_d24,
+ reg_d25,
+ reg_d26,
+ reg_d27,
+ reg_d28,
+ reg_d29,
+ reg_d30,
+ reg_d31,
+ reg_s0,
+ reg_s1,
+ reg_s2,
+ reg_s3,
+ reg_s4,
+ reg_s5,
+ reg_s6,
+ reg_s7,
+ reg_s8,
+ reg_s9,
+ reg_s10,
+ reg_s11,
+ reg_s12,
+ reg_s13,
+ reg_s14,
+ reg_s15,
+ reg_s16,
+ reg_s17,
+ reg_s18,
+ reg_s19,
+ reg_s20,
+ reg_s21,
+ reg_s22,
+ reg_s23,
+ reg_s24,
+ reg_s25,
+ reg_s26,
+ reg_s27,
+ reg_s28,
+ reg_s29,
+ reg_s30,
+ reg_s31,
+ reg_q0,
+ reg_q1,
+ reg_q2,
+ reg_q3,
+ reg_q4,
+ reg_q5,
+ reg_q6,
+ reg_q7,
+ reg_q8,
+ reg_q9,
+ reg_q10,
+ reg_q11,
+ reg_q12,
+ reg_q13,
+ reg_q14,
+ reg_q15,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+
+// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
+constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1;
+constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
+
+static RegisterSet g_reg_sets[] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
+ {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
+};
+
+constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
+
+RegisterContextMinidump_ARM::RegisterContextMinidump_ARM(
+ Thread &thread, const DataExtractor &data, bool apple)
+ : RegisterContext(thread, 0), m_apple(apple) {
+ lldb::offset_t offset = 0;
+ m_regs.context_flags = data.GetU32(&offset);
+ for (unsigned i = 0; i < llvm::array_lengthof(m_regs.r); ++i)
+ m_regs.r[i] = data.GetU32(&offset);
+ m_regs.cpsr = data.GetU32(&offset);
+ m_regs.fpscr = data.GetU64(&offset);
+ for (unsigned i = 0; i < llvm::array_lengthof(m_regs.d); ++i)
+ m_regs.d[i] = data.GetU64(&offset);
+ lldbassert(k_num_regs == k_num_reg_infos);
+}
+
+size_t RegisterContextMinidump_ARM::GetRegisterCount() { return k_num_regs; }
+
+const RegisterInfo *
+RegisterContextMinidump_ARM::GetRegisterInfoAtIndex(size_t reg) {
+ if (reg < k_num_reg_infos) {
+ if (m_apple) {
+ if (reg == reg_r7)
+ return &g_reg_info_apple_fp;
+ } else {
+ if (reg == reg_r11)
+ return &g_reg_info_fp;
+ }
+ return &g_reg_infos[reg];
+ }
+ return nullptr;
+}
+
+size_t RegisterContextMinidump_ARM::GetRegisterSetCount() {
+ return k_num_reg_sets;
+}
+
+const RegisterSet *RegisterContextMinidump_ARM::GetRegisterSet(size_t set) {
+ if (set < k_num_reg_sets)
+ return &g_reg_sets[set];
+ return nullptr;
+}
+
+const char *RegisterContextMinidump_ARM::GetRegisterName(unsigned reg) {
+ if (reg < k_num_reg_infos)
+ return g_reg_infos[reg].name;
+ return nullptr;
+}
+
+bool RegisterContextMinidump_ARM::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Status error;
+ reg_value.SetFromMemoryData(
+ reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
+ reg_info->byte_size, lldb::eByteOrderLittle, error);
+ return error.Success();
+}
+
+bool RegisterContextMinidump_ARM::WriteRegister(const RegisterInfo *,
+ const RegisterValue &) {
+ return false;
+}
+
+uint32_t RegisterContextMinidump_ARM::ConvertRegisterKindToRegisterNumber(
+ lldb::RegisterKind kind, uint32_t num) {
+ for (size_t i = 0; i < k_num_regs; ++i) {
+ if (g_reg_infos[i].kinds[kind] == num)
+ return i;
+ }
+ return LLDB_INVALID_REGNUM;
+}
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
new file mode 100644
index 000000000000..959611a1491d
--- /dev/null
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM.h
@@ -0,0 +1,93 @@
+//===-- RegisterContextMinidump_ARM.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_RegisterContextMinidump_ARM_h_
+#define liblldb_RegisterContextMinidump_ARM_h_
+
+#include "MinidumpTypes.h"
+
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
+
+#include "lldb/Target/RegisterContext.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+// C includes
+// C++ includes
+
+namespace lldb_private {
+
+namespace minidump {
+
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+class RegisterContextMinidump_ARM : public lldb_private::RegisterContext {
+public:
+ RegisterContextMinidump_ARM(lldb_private::Thread &thread,
+ const DataExtractor &data, bool apple);
+
+ ~RegisterContextMinidump_ARM() override = default;
+
+ void InvalidateAllRegisters() override {
+ // Do nothing... registers are always valid...
+ }
+
+ size_t GetRegisterCount() override;
+
+ const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+ size_t GetRegisterSetCount() override;
+
+ const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
+
+ const char *GetRegisterName(unsigned reg);
+
+ bool ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
+
+ bool WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
+
+ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num) override;
+
+ // Reference: see breakpad/crashpad source
+ struct QRegValue {
+ uint64_t lo;
+ uint64_t hi;
+ };
+
+ struct Context {
+ uint32_t context_flags;
+ uint32_t r[16];
+ uint32_t cpsr;
+ uint64_t fpscr;
+ union {
+ uint64_t d[32];
+ uint32_t s[32];
+ QRegValue q[16];
+ };
+ uint32_t extra[8];
+ };
+
+protected:
+ enum class Flags : uint32_t {
+ ARM_Flag = 0x40000000,
+ Integer = ARM_Flag | 0x00000002,
+ FloatingPoint = ARM_Flag | 0x00000004,
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ FloatingPoint)
+ };
+ Context m_regs;
+ const bool m_apple; // True if this is an Apple ARM where FP is R7
+};
+
+} // end namespace minidump
+} // end namespace lldb_private
+#endif // liblldb_RegisterContextMinidump_ARM_h_
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
new file mode 100644
index 000000000000..3582e7d01867
--- /dev/null
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.cpp
@@ -0,0 +1,834 @@
+//===-- RegisterContextMinidump_ARM64.cpp -----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMinidump_ARM64.h"
+
+#include "Utility/ARM64_DWARF_Registers.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/lldb-enumerations.h"
+
+// C includes
+#include <assert.h>
+
+// C++ includes
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace minidump;
+
+#define INV LLDB_INVALID_REGNUM
+#define OFFSET(r) (offsetof(RegisterContextMinidump_ARM64::Context, r))
+
+#define DEF_X(i) \
+ { \
+ "x" #i, nullptr, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
+ {INV, arm64_dwarf::x##i, INV, INV, reg_x##i}, nullptr, nullptr, \
+ nullptr, 0 \
+ }
+
+#define DEF_W(i) \
+ { \
+ "w" #i, nullptr, 4, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
+ {INV, INV, INV, INV, reg_w##i}, nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_X_ARG(i, n) \
+ { \
+ "x" #i, "arg" #n, 8, OFFSET(x) + i * 8, eEncodingUint, eFormatHex, \
+ {INV, arm64_dwarf::x##i, LLDB_REGNUM_GENERIC_ARG1 + i, INV, reg_x##i}, \
+ nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_V(i) \
+ { \
+ "v" #i, nullptr, 16, OFFSET(v) + i * 16, eEncodingVector, \
+ eFormatVectorOfUInt8, {INV, arm64_dwarf::v##i, INV, INV, reg_v##i}, \
+ nullptr, nullptr, nullptr, 0 \
+ }
+
+#define DEF_D(i) \
+ { \
+ "d" #i, nullptr, 8, OFFSET(v) + i * 16, eEncodingVector, \
+ eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_d##i}, nullptr, \
+ nullptr, nullptr, 0 \
+ }
+
+#define DEF_S(i) \
+ { \
+ "s" #i, nullptr, 4, OFFSET(v) + i * 16, eEncodingVector, \
+ eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_s##i}, nullptr, \
+ nullptr, nullptr, 0 \
+ }
+
+#define DEF_H(i) \
+ { \
+ "h" #i, nullptr, 2, OFFSET(v) + i * 16, eEncodingVector, \
+ eFormatVectorOfUInt8, {INV, INV, INV, INV, reg_h##i}, nullptr, \
+ nullptr, nullptr, 0 \
+ }
+
+// Zero based LLDB register numbers for this register context
+enum {
+ // General Purpose Registers
+ reg_x0 = 0,
+ reg_x1,
+ reg_x2,
+ reg_x3,
+ reg_x4,
+ reg_x5,
+ reg_x6,
+ reg_x7,
+ reg_x8,
+ reg_x9,
+ reg_x10,
+ reg_x11,
+ reg_x12,
+ reg_x13,
+ reg_x14,
+ reg_x15,
+ reg_x16,
+ reg_x17,
+ reg_x18,
+ reg_x19,
+ reg_x20,
+ reg_x21,
+ reg_x22,
+ reg_x23,
+ reg_x24,
+ reg_x25,
+ reg_x26,
+ reg_x27,
+ reg_x28,
+ reg_fp,
+ reg_lr,
+ reg_sp,
+ reg_pc,
+ reg_w0,
+ reg_w1,
+ reg_w2,
+ reg_w3,
+ reg_w4,
+ reg_w5,
+ reg_w6,
+ reg_w7,
+ reg_w8,
+ reg_w9,
+ reg_w10,
+ reg_w11,
+ reg_w12,
+ reg_w13,
+ reg_w14,
+ reg_w15,
+ reg_w16,
+ reg_w17,
+ reg_w18,
+ reg_w19,
+ reg_w20,
+ reg_w21,
+ reg_w22,
+ reg_w23,
+ reg_w24,
+ reg_w25,
+ reg_w26,
+ reg_w27,
+ reg_w28,
+ reg_w29,
+ reg_w30,
+ reg_w31,
+ reg_cpsr,
+ // Floating Point Registers
+ reg_fpsr,
+ reg_fpcr,
+ reg_v0,
+ reg_v1,
+ reg_v2,
+ reg_v3,
+ reg_v4,
+ reg_v5,
+ reg_v6,
+ reg_v7,
+ reg_v8,
+ reg_v9,
+ reg_v10,
+ reg_v11,
+ reg_v12,
+ reg_v13,
+ reg_v14,
+ reg_v15,
+ reg_v16,
+ reg_v17,
+ reg_v18,
+ reg_v19,
+ reg_v20,
+ reg_v21,
+ reg_v22,
+ reg_v23,
+ reg_v24,
+ reg_v25,
+ reg_v26,
+ reg_v27,
+ reg_v28,
+ reg_v29,
+ reg_v30,
+ reg_v31,
+ reg_d0,
+ reg_d1,
+ reg_d2,
+ reg_d3,
+ reg_d4,
+ reg_d5,
+ reg_d6,
+ reg_d7,
+ reg_d8,
+ reg_d9,
+ reg_d10,
+ reg_d11,
+ reg_d12,
+ reg_d13,
+ reg_d14,
+ reg_d15,
+ reg_d16,
+ reg_d17,
+ reg_d18,
+ reg_d19,
+ reg_d20,
+ reg_d21,
+ reg_d22,
+ reg_d23,
+ reg_d24,
+ reg_d25,
+ reg_d26,
+ reg_d27,
+ reg_d28,
+ reg_d29,
+ reg_d30,
+ reg_d31,
+ reg_s0,
+ reg_s1,
+ reg_s2,
+ reg_s3,
+ reg_s4,
+ reg_s5,
+ reg_s6,
+ reg_s7,
+ reg_s8,
+ reg_s9,
+ reg_s10,
+ reg_s11,
+ reg_s12,
+ reg_s13,
+ reg_s14,
+ reg_s15,
+ reg_s16,
+ reg_s17,
+ reg_s18,
+ reg_s19,
+ reg_s20,
+ reg_s21,
+ reg_s22,
+ reg_s23,
+ reg_s24,
+ reg_s25,
+ reg_s26,
+ reg_s27,
+ reg_s28,
+ reg_s29,
+ reg_s30,
+ reg_s31,
+ reg_h0,
+ reg_h1,
+ reg_h2,
+ reg_h3,
+ reg_h4,
+ reg_h5,
+ reg_h6,
+ reg_h7,
+ reg_h8,
+ reg_h9,
+ reg_h10,
+ reg_h11,
+ reg_h12,
+ reg_h13,
+ reg_h14,
+ reg_h15,
+ reg_h16,
+ reg_h17,
+ reg_h18,
+ reg_h19,
+ reg_h20,
+ reg_h21,
+ reg_h22,
+ reg_h23,
+ reg_h24,
+ reg_h25,
+ reg_h26,
+ reg_h27,
+ reg_h28,
+ reg_h29,
+ reg_h30,
+ reg_h31,
+ k_num_regs
+};
+
+// Register info definitions for this register context
+static RegisterInfo g_reg_infos[] = {
+ DEF_X_ARG(0, 1),
+ DEF_X_ARG(1, 2),
+ DEF_X_ARG(2, 3),
+ DEF_X_ARG(3, 4),
+ DEF_X_ARG(4, 5),
+ DEF_X_ARG(5, 6),
+ DEF_X_ARG(6, 7),
+ DEF_X_ARG(7, 8),
+ DEF_X(8),
+ DEF_X(9),
+ DEF_X(10),
+ DEF_X(11),
+ DEF_X(12),
+ DEF_X(13),
+ DEF_X(14),
+ DEF_X(15),
+ DEF_X(16),
+ DEF_X(17),
+ DEF_X(18),
+ DEF_X(19),
+ DEF_X(20),
+ DEF_X(21),
+ DEF_X(22),
+ DEF_X(23),
+ DEF_X(24),
+ DEF_X(25),
+ DEF_X(26),
+ DEF_X(27),
+ DEF_X(28),
+ {"fp",
+ "x29",
+ 8,
+ OFFSET(x) + 29 * 8,
+ eEncodingUint,
+ eFormatHex,
+ {INV, arm64_dwarf::x29, LLDB_REGNUM_GENERIC_FP, INV, reg_fp},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"lr",
+ "x30",
+ 8,
+ OFFSET(x) + 30 * 8,
+ eEncodingUint,
+ eFormatHex,
+ {INV, arm64_dwarf::x30, LLDB_REGNUM_GENERIC_RA, INV, reg_lr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"sp",
+ "x31",
+ 8,
+ OFFSET(x) + 31 * 8,
+ eEncodingUint,
+ eFormatHex,
+ {INV, arm64_dwarf::x31, LLDB_REGNUM_GENERIC_SP, INV, reg_sp},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"pc",
+ nullptr,
+ 8,
+ OFFSET(pc),
+ eEncodingUint,
+ eFormatHex,
+ {INV, arm64_dwarf::pc, LLDB_REGNUM_GENERIC_PC, INV, reg_pc},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ // w0 - w31
+ DEF_W(0),
+ DEF_W(1),
+ DEF_W(2),
+ DEF_W(3),
+ DEF_W(4),
+ DEF_W(5),
+ DEF_W(6),
+ DEF_W(7),
+ DEF_W(8),
+ DEF_W(9),
+ DEF_W(10),
+ DEF_W(11),
+ DEF_W(12),
+ DEF_W(13),
+ DEF_W(14),
+ DEF_W(15),
+ DEF_W(16),
+ DEF_W(17),
+ DEF_W(18),
+ DEF_W(19),
+ DEF_W(20),
+ DEF_W(21),
+ DEF_W(22),
+ DEF_W(23),
+ DEF_W(24),
+ DEF_W(25),
+ DEF_W(26),
+ DEF_W(27),
+ DEF_W(28),
+ DEF_W(29),
+ DEF_W(30),
+ DEF_W(31),
+ {"cpsr",
+ "psr",
+ 4,
+ OFFSET(cpsr),
+ eEncodingUint,
+ eFormatHex,
+ {INV, arm64_dwarf::cpsr, LLDB_REGNUM_GENERIC_FLAGS, INV, reg_cpsr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"fpsr",
+ nullptr,
+ 4,
+ OFFSET(fpsr),
+ eEncodingUint,
+ eFormatHex,
+ {INV, INV, INV, INV, reg_fpsr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ {"fpcr",
+ nullptr,
+ 4,
+ OFFSET(fpcr),
+ eEncodingUint,
+ eFormatHex,
+ {INV, INV, INV, INV, reg_fpcr},
+ nullptr,
+ nullptr,
+ nullptr,
+ 0},
+ // v0 - v31
+ DEF_V(0),
+ DEF_V(1),
+ DEF_V(2),
+ DEF_V(3),
+ DEF_V(4),
+ DEF_V(5),
+ DEF_V(6),
+ DEF_V(7),
+ DEF_V(8),
+ DEF_V(9),
+ DEF_V(10),
+ DEF_V(11),
+ DEF_V(12),
+ DEF_V(13),
+ DEF_V(14),
+ DEF_V(15),
+ DEF_V(16),
+ DEF_V(17),
+ DEF_V(18),
+ DEF_V(19),
+ DEF_V(20),
+ DEF_V(21),
+ DEF_V(22),
+ DEF_V(23),
+ DEF_V(24),
+ DEF_V(25),
+ DEF_V(26),
+ DEF_V(27),
+ DEF_V(28),
+ DEF_V(29),
+ DEF_V(30),
+ DEF_V(31),
+ // d0 - d31
+ DEF_D(0),
+ DEF_D(1),
+ DEF_D(2),
+ DEF_D(3),
+ DEF_D(4),
+ DEF_D(5),
+ DEF_D(6),
+ DEF_D(7),
+ DEF_D(8),
+ DEF_D(9),
+ DEF_D(10),
+ DEF_D(11),
+ DEF_D(12),
+ DEF_D(13),
+ DEF_D(14),
+ DEF_D(15),
+ DEF_D(16),
+ DEF_D(17),
+ DEF_D(18),
+ DEF_D(19),
+ DEF_D(20),
+ DEF_D(21),
+ DEF_D(22),
+ DEF_D(23),
+ DEF_D(24),
+ DEF_D(25),
+ DEF_D(26),
+ DEF_D(27),
+ DEF_D(28),
+ DEF_D(29),
+ DEF_D(30),
+ DEF_D(31),
+ // s0 - s31
+ DEF_S(0),
+ DEF_S(1),
+ DEF_S(2),
+ DEF_S(3),
+ DEF_S(4),
+ DEF_S(5),
+ DEF_S(6),
+ DEF_S(7),
+ DEF_S(8),
+ DEF_S(9),
+ DEF_S(10),
+ DEF_S(11),
+ DEF_S(12),
+ DEF_S(13),
+ DEF_S(14),
+ DEF_S(15),
+ DEF_S(16),
+ DEF_S(17),
+ DEF_S(18),
+ DEF_S(19),
+ DEF_S(20),
+ DEF_S(21),
+ DEF_S(22),
+ DEF_S(23),
+ DEF_S(24),
+ DEF_S(25),
+ DEF_S(26),
+ DEF_S(27),
+ DEF_S(28),
+ DEF_S(29),
+ DEF_S(30),
+ DEF_S(31),
+ // h0 - h31
+ DEF_H(0),
+ DEF_H(1),
+ DEF_H(2),
+ DEF_H(3),
+ DEF_H(4),
+ DEF_H(5),
+ DEF_H(6),
+ DEF_H(7),
+ DEF_H(8),
+ DEF_H(9),
+ DEF_H(10),
+ DEF_H(11),
+ DEF_H(12),
+ DEF_H(13),
+ DEF_H(14),
+ DEF_H(15),
+ DEF_H(16),
+ DEF_H(17),
+ DEF_H(18),
+ DEF_H(19),
+ DEF_H(20),
+ DEF_H(21),
+ DEF_H(22),
+ DEF_H(23),
+ DEF_H(24),
+ DEF_H(25),
+ DEF_H(26),
+ DEF_H(27),
+ DEF_H(28),
+ DEF_H(29),
+ DEF_H(30),
+ DEF_H(31),
+};
+
+constexpr size_t k_num_reg_infos = llvm::array_lengthof(g_reg_infos);
+
+// ARM64 general purpose registers.
+const uint32_t g_gpr_regnums[] = {
+ reg_x0,
+ reg_x1,
+ reg_x2,
+ reg_x3,
+ reg_x4,
+ reg_x5,
+ reg_x6,
+ reg_x7,
+ reg_x8,
+ reg_x9,
+ reg_x10,
+ reg_x11,
+ reg_x12,
+ reg_x13,
+ reg_x14,
+ reg_x15,
+ reg_x16,
+ reg_x17,
+ reg_x18,
+ reg_x19,
+ reg_x20,
+ reg_x21,
+ reg_x22,
+ reg_x23,
+ reg_x24,
+ reg_x25,
+ reg_x26,
+ reg_x27,
+ reg_x28,
+ reg_fp,
+ reg_lr,
+ reg_sp,
+ reg_w0,
+ reg_w1,
+ reg_w2,
+ reg_w3,
+ reg_w4,
+ reg_w5,
+ reg_w6,
+ reg_w7,
+ reg_w8,
+ reg_w9,
+ reg_w10,
+ reg_w11,
+ reg_w12,
+ reg_w13,
+ reg_w14,
+ reg_w15,
+ reg_w16,
+ reg_w17,
+ reg_w18,
+ reg_w19,
+ reg_w20,
+ reg_w21,
+ reg_w22,
+ reg_w23,
+ reg_w24,
+ reg_w25,
+ reg_w26,
+ reg_w27,
+ reg_w28,
+ reg_w29,
+ reg_w30,
+ reg_w31,
+ reg_pc,
+ reg_cpsr,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+const uint32_t g_fpu_regnums[] = {
+ reg_v0,
+ reg_v1,
+ reg_v2,
+ reg_v3,
+ reg_v4,
+ reg_v5,
+ reg_v6,
+ reg_v7,
+ reg_v8,
+ reg_v9,
+ reg_v10,
+ reg_v11,
+ reg_v12,
+ reg_v13,
+ reg_v14,
+ reg_v15,
+ reg_v16,
+ reg_v17,
+ reg_v18,
+ reg_v19,
+ reg_v20,
+ reg_v21,
+ reg_v22,
+ reg_v23,
+ reg_v24,
+ reg_v25,
+ reg_v26,
+ reg_v27,
+ reg_v28,
+ reg_v29,
+ reg_v30,
+ reg_v31,
+ reg_d0,
+ reg_d1,
+ reg_d2,
+ reg_d3,
+ reg_d4,
+ reg_d5,
+ reg_d6,
+ reg_d7,
+ reg_d8,
+ reg_d9,
+ reg_d10,
+ reg_d11,
+ reg_d12,
+ reg_d13,
+ reg_d14,
+ reg_d15,
+ reg_d16,
+ reg_d17,
+ reg_d18,
+ reg_d19,
+ reg_d20,
+ reg_d21,
+ reg_d22,
+ reg_d23,
+ reg_d24,
+ reg_d25,
+ reg_d26,
+ reg_d27,
+ reg_d28,
+ reg_d29,
+ reg_d30,
+ reg_d31,
+ reg_s0,
+ reg_s1,
+ reg_s2,
+ reg_s3,
+ reg_s4,
+ reg_s5,
+ reg_s6,
+ reg_s7,
+ reg_s8,
+ reg_s9,
+ reg_s10,
+ reg_s11,
+ reg_s12,
+ reg_s13,
+ reg_s14,
+ reg_s15,
+ reg_s16,
+ reg_s17,
+ reg_s18,
+ reg_s19,
+ reg_s20,
+ reg_s21,
+ reg_s22,
+ reg_s23,
+ reg_s24,
+ reg_s25,
+ reg_s26,
+ reg_s27,
+ reg_s28,
+ reg_s29,
+ reg_s30,
+ reg_s31,
+ reg_h0,
+ reg_h1,
+ reg_h2,
+ reg_h3,
+ reg_h4,
+ reg_h5,
+ reg_h6,
+ reg_h7,
+ reg_h8,
+ reg_h9,
+ reg_h10,
+ reg_h11,
+ reg_h12,
+ reg_h13,
+ reg_h14,
+ reg_h15,
+ reg_h16,
+ reg_h17,
+ reg_h18,
+ reg_h19,
+ reg_h20,
+ reg_h21,
+ reg_h22,
+ reg_h23,
+ reg_h24,
+ reg_h25,
+ reg_h26,
+ reg_h27,
+ reg_h28,
+ reg_h29,
+ reg_h30,
+ reg_h31,
+ reg_fpsr,
+ reg_fpcr,
+ LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+
+// Skip the last LLDB_INVALID_REGNUM in each count below by subtracting 1
+constexpr size_t k_num_gpr_regs = llvm::array_lengthof(g_gpr_regnums) - 1;
+constexpr size_t k_num_fpu_regs = llvm::array_lengthof(g_fpu_regnums) - 1;
+
+static RegisterSet g_reg_sets[] = {
+ {"General Purpose Registers", "gpr", k_num_gpr_regs, g_gpr_regnums},
+ {"Floating Point Registers", "fpu", k_num_fpu_regs, g_fpu_regnums},
+};
+
+constexpr size_t k_num_reg_sets = llvm::array_lengthof(g_reg_sets);
+
+RegisterContextMinidump_ARM64::RegisterContextMinidump_ARM64(
+ Thread &thread, const DataExtractor &data)
+ : RegisterContext(thread, 0) {
+ lldb::offset_t offset = 0;
+ m_regs.context_flags = data.GetU64(&offset);
+ for (unsigned i = 0; i < 32; ++i)
+ m_regs.x[i] = data.GetU64(&offset);
+ m_regs.pc = data.GetU64(&offset);
+ m_regs.cpsr = data.GetU32(&offset);
+ m_regs.fpsr = data.GetU32(&offset);
+ m_regs.fpcr = data.GetU32(&offset);
+ auto regs_data = data.GetData(&offset, sizeof(m_regs.v));
+ if (regs_data)
+ memcpy(m_regs.v, regs_data, sizeof(m_regs.v));
+ assert(k_num_regs == k_num_reg_infos);
+}
+size_t RegisterContextMinidump_ARM64::GetRegisterCount() { return k_num_regs; }
+
+const RegisterInfo *
+RegisterContextMinidump_ARM64::GetRegisterInfoAtIndex(size_t reg) {
+ if (reg < k_num_reg_infos)
+ return &g_reg_infos[reg];
+ return nullptr;
+}
+
+size_t RegisterContextMinidump_ARM64::GetRegisterSetCount() {
+ return k_num_reg_sets;
+}
+
+const RegisterSet *RegisterContextMinidump_ARM64::GetRegisterSet(size_t set) {
+ if (set < k_num_reg_sets)
+ return &g_reg_sets[set];
+ return nullptr;
+}
+
+const char *RegisterContextMinidump_ARM64::GetRegisterName(unsigned reg) {
+ if (reg < k_num_reg_infos)
+ return g_reg_infos[reg].name;
+ return nullptr;
+}
+
+bool RegisterContextMinidump_ARM64::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) {
+ Status error;
+ reg_value.SetFromMemoryData(
+ reg_info, (const uint8_t *)&m_regs + reg_info->byte_offset,
+ reg_info->byte_size, lldb::eByteOrderLittle, error);
+ return error.Success();
+}
+
+bool RegisterContextMinidump_ARM64::WriteRegister(const RegisterInfo *,
+ const RegisterValue &) {
+ return false;
+}
+
+uint32_t RegisterContextMinidump_ARM64::ConvertRegisterKindToRegisterNumber(
+ lldb::RegisterKind kind, uint32_t num) {
+ for (size_t i = 0; i < k_num_regs; ++i) {
+ if (g_reg_infos[i].kinds[kind] == num)
+ return i;
+ }
+ return LLDB_INVALID_REGNUM;
+}
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
new file mode 100644
index 000000000000..ee47b1577e52
--- /dev/null
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_ARM64.h
@@ -0,0 +1,83 @@
+//===-- RegisterContextMinidump_ARM64.h -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMinidump_ARM64_h_
+#define liblldb_RegisterContextMinidump_ARM64_h_
+
+#include "MinidumpTypes.h"
+
+#include "Plugins/Process/Utility/RegisterInfoInterface.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitmaskEnum.h"
+
+// C includes
+// C++ includes
+
+namespace lldb_private {
+
+namespace minidump {
+
+LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
+
+class RegisterContextMinidump_ARM64 : public lldb_private::RegisterContext {
+public:
+ RegisterContextMinidump_ARM64(lldb_private::Thread &thread,
+ const DataExtractor &data);
+
+ ~RegisterContextMinidump_ARM64() override = default;
+
+ void InvalidateAllRegisters() override {
+ // Do nothing... registers are always valid...
+ }
+
+ size_t GetRegisterCount() override;
+
+ const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+ size_t GetRegisterSetCount() override;
+
+ const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
+
+ const char *GetRegisterName(unsigned reg);
+
+ bool ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &reg_value) override;
+
+ bool WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &reg_value) override;
+
+ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num) override;
+
+ // Reference: see breakpad/crashpad source
+ struct Context {
+ uint64_t context_flags;
+ uint64_t x[32];
+ uint64_t pc;
+ uint32_t cpsr;
+ uint32_t fpsr;
+ uint32_t fpcr;
+ uint8_t v[32 * 16]; // 32 128-bit floating point registers
+ };
+
+protected:
+ enum class Flags : uint32_t {
+ ARM64_Flag = 0x80000000,
+ Integer = ARM64_Flag | 0x00000002,
+ FloatingPoint = ARM64_Flag | 0x00000004,
+ LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ FloatingPoint)
+ };
+ Context m_regs;
+};
+
+} // end namespace minidump
+} // end namespace lldb_private
+#endif // liblldb_RegisterContextMinidump_ARM64_h_
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
index 7605f8b143af..1fdbb5e3f1e5 100644
--- a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.cpp
@@ -7,10 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "RegisterContextMinidump_x86_32.h"
-// Other libraries and framework includes
#include "lldb/Utility/DataBufferHeap.h"
// C includes
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h
index e18bb3b4f5d9..38c2ffca4938 100644
--- a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_32.h
@@ -10,10 +10,8 @@
#ifndef liblldb_RegisterContextMinidump_x86_32_h_
#define liblldb_RegisterContextMinidump_x86_32_h_
-// Project includes
#include "MinidumpTypes.h"
-// Other libraries and framework includes
#include "Plugins/Process/Utility/RegisterInfoInterface.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
index ba1cb6dbf3ef..eaa155de8eb9 100644
--- a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.cpp
@@ -7,10 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "RegisterContextMinidump_x86_64.h"
-// Other libraries and framework includes
#include "lldb/Utility/DataBufferHeap.h"
// C includes
diff --git a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h
index 9ba2ee9f29ad..30ce9065e141 100644
--- a/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h
+++ b/source/Plugins/Process/minidump/RegisterContextMinidump_x86_64.h
@@ -10,10 +10,8 @@
#ifndef liblldb_RegisterContextMinidump_h_
#define liblldb_RegisterContextMinidump_h_
-// Project includes
#include "MinidumpTypes.h"
-// Other libraries and framework includes
#include "Plugins/Process/Utility/RegisterInfoInterface.h"
#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
diff --git a/source/Plugins/Process/minidump/ThreadMinidump.cpp b/source/Plugins/Process/minidump/ThreadMinidump.cpp
index 3fafb6134e7f..f4c136577719 100644
--- a/source/Plugins/Process/minidump/ThreadMinidump.cpp
+++ b/source/Plugins/Process/minidump/ThreadMinidump.cpp
@@ -7,14 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "ThreadMinidump.h"
#include "ProcessMinidump.h"
+#include "RegisterContextMinidump_ARM.h"
+#include "RegisterContextMinidump_ARM64.h"
#include "RegisterContextMinidump_x86_32.h"
#include "RegisterContextMinidump_x86_64.h"
-// Other libraries and framework includes
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.h"
@@ -27,8 +27,6 @@
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
-// C Includes
-// C++ Includes
using namespace lldb;
using namespace lldb_private;
@@ -54,7 +52,6 @@ RegisterContextSP
ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) {
RegisterContextSP reg_ctx_sp;
uint32_t concrete_frame_idx = 0;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_THREAD));
if (frame)
concrete_frame_idx = frame->GetConcreteFrameIndex();
@@ -88,15 +85,22 @@ ThreadMinidump::CreateRegisterContextForFrame(StackFrame *frame) {
*this, reg_interface, gpregset, {}));
break;
}
- default:
+ case llvm::Triple::aarch64: {
+ DataExtractor data(m_gpregset_data.data(), m_gpregset_data.size(),
+ lldb::eByteOrderLittle, 8);
+ m_thread_reg_ctx_sp.reset(new RegisterContextMinidump_ARM64(*this, data));
break;
}
-
- if (!reg_interface) {
- if (log)
- log->Printf("elf-core::%s:: Architecture(%d) not supported",
- __FUNCTION__, arch.GetMachine());
- assert(false && "Architecture not supported");
+ case llvm::Triple::arm: {
+ DataExtractor data(m_gpregset_data.data(), m_gpregset_data.size(),
+ lldb::eByteOrderLittle, 8);
+ const bool apple = arch.GetTriple().getVendor() == llvm::Triple::Apple;
+ m_thread_reg_ctx_sp.reset(
+ new RegisterContextMinidump_ARM(*this, data, apple));
+ break;
+ }
+ default:
+ break;
}
reg_ctx_sp = m_thread_reg_ctx_sp;
diff --git a/source/Plugins/Process/minidump/ThreadMinidump.h b/source/Plugins/Process/minidump/ThreadMinidump.h
index 74ac44f74dcf..45364facaa56 100644
--- a/source/Plugins/Process/minidump/ThreadMinidump.h
+++ b/source/Plugins/Process/minidump/ThreadMinidump.h
@@ -10,14 +10,10 @@
#ifndef liblldb_ThreadMinidump_h_
#define liblldb_ThreadMinidump_h_
-// Project includes
#include "MinidumpTypes.h"
-// Other libraries and framework includes
#include "lldb/Target/Thread.h"
-// C Includes
-// C++ Includes
namespace lldb_private {
diff --git a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
index 824579472b5e..8937d9843f87 100644
--- a/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
+++ b/source/Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ScriptInterpreterNone_h_
#define liblldb_ScriptInterpreterNone_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Interpreter/ScriptInterpreter.h"
namespace lldb_private {
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 90d8ab97fb73..7e96dd9893c8 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -222,9 +222,7 @@ PythonBytes::~PythonBytes() {}
bool PythonBytes::Check(PyObject *py_obj) {
if (!py_obj)
return false;
- if (PyBytes_Check(py_obj))
- return true;
- return false;
+ return PyBytes_Check(py_obj);
}
void PythonBytes::Reset(PyRefType type, PyObject *py_obj) {
@@ -294,9 +292,7 @@ PythonByteArray::~PythonByteArray() {}
bool PythonByteArray::Check(PyObject *py_obj) {
if (!py_obj)
return false;
- if (PyByteArray_Check(py_obj))
- return true;
- return false;
+ return PyByteArray_Check(py_obj);
}
void PythonByteArray::Reset(PyRefType type, PyObject *py_obj) {
@@ -939,7 +935,8 @@ PythonFile::PythonFile() : PythonObject() {}
PythonFile::PythonFile(File &file, const char *mode) { Reset(file, mode); }
PythonFile::PythonFile(const char *path, const char *mode) {
- lldb_private::File file(path, GetOptionsFromMode(mode));
+ lldb_private::File file;
+ FileSystem::Instance().Open(file, FileSpec(path), GetOptionsFromMode(mode));
Reset(file, mode);
}
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index beeb64782367..7cd98df28ee0 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -15,10 +15,6 @@
// LLDB Python header must be included first
#include "lldb-python.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Flags.h"
#include "lldb/Host/File.h"
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index b8eb36a2baf6..41cb443d4f1e 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -27,6 +27,7 @@
#include <string>
#include "lldb/API/SBValue.h"
+#include "lldb/API/SBFrame.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
@@ -91,6 +92,10 @@ static ScriptInterpreterPython::SWIGPythonCallModuleInit
g_swig_call_module_init = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateOSPlugin
g_swig_create_os_plugin = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateFrameRecognizer
+ g_swig_create_frame_recognizer = nullptr;
+static ScriptInterpreterPython::SWIGPythonGetRecognizedArguments
+ g_swig_get_recognized_arguments = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process
g_swig_run_script_keyword_process = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread
@@ -107,6 +112,10 @@ static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan
g_swig_thread_plan_script = nullptr;
static ScriptInterpreterPython::SWIGPythonCallThreadPlan
g_swig_call_thread_plan = nullptr;
+static ScriptInterpreterPython::SWIGPythonCreateScriptedBreakpointResolver
+ g_swig_bkpt_resolver_script = nullptr;
+static ScriptInterpreterPython::SWIGPythonCallBreakpointResolver
+ g_swig_call_bkpt_resolver = nullptr;
static bool g_initialized = false;
@@ -128,6 +137,9 @@ public:
InitializePythonHome();
+ // Register _lldb as a built-in module.
+ PyImport_AppendInittab("_lldb", g_swig_init_callback);
+
// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
// call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.
@@ -196,7 +208,7 @@ ScriptInterpreterPython::Locker::Locker(ScriptInterpreterPython *py_interpreter,
m_python_interpreter(py_interpreter) {
DoAcquireLock();
if ((on_entry & InitSession) == InitSession) {
- if (DoInitSession(on_entry, in, out, err) == false) {
+ if (!DoInitSession(on_entry, in, out, err)) {
// Don't teardown the session if we didn't init it.
m_teardown_session = false;
}
@@ -817,11 +829,15 @@ bool ScriptInterpreterPython::ExecuteOneLine(
error_file_sp);
} else {
input_file_sp.reset(new StreamFile());
- input_file_sp->GetFile().Open(FileSystem::DEV_NULL,
- File::eOpenOptionRead);
+ FileSystem::Instance().Open(input_file_sp->GetFile(),
+ FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionRead);
+
output_file_sp.reset(new StreamFile());
- output_file_sp->GetFile().Open(FileSystem::DEV_NULL,
- File::eOpenOptionWrite);
+ FileSystem::Instance().Open(output_file_sp->GetFile(),
+ FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionWrite);
+
error_file_sp = output_file_sp;
}
@@ -1491,6 +1507,62 @@ bool ScriptInterpreterPython::GenerateTypeSynthClass(StringList &user_input,
return true;
}
+StructuredData::GenericSP ScriptInterpreterPython::CreateFrameRecognizer(
+ const char *class_name) {
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
+
+ void *ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+ ret_val =
+ g_swig_create_frame_recognizer(class_name, m_dictionary_name.c_str());
+ }
+
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
+
+lldb::ValueObjectListSP ScriptInterpreterPython::GetRecognizedArguments(
+ const StructuredData::ObjectSP &os_plugin_object_sp,
+ lldb::StackFrameSP frame_sp) {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ if (!os_plugin_object_sp) return ValueObjectListSP();
+
+ StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
+ if (!generic) return nullptr;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)generic->GetValue());
+
+ if (!implementor.IsAllocated()) return ValueObjectListSP();
+
+ PythonObject py_return(
+ PyRefType::Owned,
+ (PyObject *)g_swig_get_recognized_arguments(implementor.get(), frame_sp));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ if (py_return.get()) {
+ PythonList result_list(PyRefType::Borrowed, py_return.get());
+ ValueObjectListSP result = ValueObjectListSP(new ValueObjectList());
+ for (size_t i = 0; i < result_list.GetSize(); i++) {
+ PyObject *item = result_list.GetItemAtIndex(i).get();
+ lldb::SBValue *sb_value_ptr =
+ (lldb::SBValue *)g_swig_cast_to_sbvalue(item);
+ auto valobj_sp = g_swig_get_valobj_sp_from_sbvalue(sb_value_ptr);
+ if (valobj_sp) result->Append(valobj_sp);
+ }
+ return result;
+ }
+ return ValueObjectListSP();
+}
+
StructuredData::GenericSP ScriptInterpreterPython::OSPlugin_CreatePluginObject(
const char *class_name, lldb::ProcessSP process_sp) {
if (class_name == nullptr || class_name[0] == '\0')
@@ -1868,10 +1940,88 @@ lldb::StateType ScriptInterpreterPython::ScriptedThreadPlanGetRunState(
return lldb::eStateRunning;
}
+StructuredData::GenericSP
+ScriptInterpreterPython::CreateScriptedBreakpointResolver(
+ const char *class_name,
+ StructuredDataImpl *args_data,
+ lldb::BreakpointSP &bkpt_sp) {
+
+ if (class_name == nullptr || class_name[0] == '\0')
+ return StructuredData::GenericSP();
+
+ if (!bkpt_sp.get())
+ return StructuredData::GenericSP();
+
+ Debugger &debugger = bkpt_sp->GetTarget().GetDebugger();
+ ScriptInterpreter *script_interpreter =
+ debugger.GetCommandInterpreter().GetScriptInterpreter();
+ ScriptInterpreterPython *python_interpreter =
+ static_cast<ScriptInterpreterPython *>(script_interpreter);
+
+ if (!script_interpreter)
+ return StructuredData::GenericSP();
+
+ void *ret_val;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+
+ ret_val = g_swig_bkpt_resolver_script(
+ class_name, python_interpreter->m_dictionary_name.c_str(),
+ args_data, bkpt_sp);
+ }
+
+ return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
+}
+
+bool
+ScriptInterpreterPython::ScriptedBreakpointResolverSearchCallback(
+ StructuredData::GenericSP implementor_sp,
+ SymbolContext *sym_ctx) {
+ bool should_continue = false;
+
+ if (implementor_sp) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ should_continue
+ = g_swig_call_bkpt_resolver(implementor_sp->GetValue(), "__callback__",
+ sym_ctx);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ return should_continue;
+}
+
+lldb::SearchDepth
+ScriptInterpreterPython::ScriptedBreakpointResolverSearchDepth(
+ StructuredData::GenericSP implementor_sp) {
+ int depth_as_int = lldb::eSearchDepthModule;
+ if (implementor_sp) {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
+ depth_as_int
+ = g_swig_call_bkpt_resolver(implementor_sp->GetValue(), "__get_depth__", nullptr);
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+ if (depth_as_int == lldb::eSearchDepthInvalid)
+ return lldb::eSearchDepthModule;
+
+ if (depth_as_int <= lldb::kLastSearchDepthKind)
+ return (lldb::SearchDepth) depth_as_int;
+ else
+ return lldb::eSearchDepthModule;
+}
+
StructuredData::ObjectSP
ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec,
lldb_private::Status &error) {
- if (!file_spec.Exists()) {
+ if (!FileSystem::Instance().Exists(file_spec)) {
error.SetErrorString("no such file");
return StructuredData::ObjectSP();
}
@@ -2603,7 +2753,8 @@ bool ScriptInterpreterPython::LoadScriptingModule(
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
{
- FileSpec target_file(pathname, true);
+ FileSpec target_file(pathname);
+ FileSystem::Instance().Resolve(target_file);
std::string basename(target_file.GetFilename().GetCString());
StreamString command_stream;
@@ -2687,7 +2838,7 @@ bool ScriptInterpreterPython::LoadScriptingModule(
bool was_imported = (was_imported_globally || was_imported_locally);
- if (was_imported == true && can_reload == false) {
+ if (was_imported && !can_reload) {
error.SetErrorString("module already imported");
return false;
}
@@ -3100,6 +3251,8 @@ void ScriptInterpreterPython::InitializeInterpreter(
SWIGPythonCallCommandObject swig_call_command_object,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonCreateFrameRecognizer swig_create_frame_recognizer,
+ SWIGPythonGetRecognizedArguments swig_get_recognized_arguments,
SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
@@ -3107,7 +3260,9 @@ void ScriptInterpreterPython::InitializeInterpreter(
SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
SWIGPython_GetDynamicSetting swig_plugin_get,
SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
- SWIGPythonCallThreadPlan swig_call_thread_plan) {
+ SWIGPythonCallThreadPlan swig_call_thread_plan,
+ SWIGPythonCreateScriptedBreakpointResolver swig_bkpt_resolver_script,
+ SWIGPythonCallBreakpointResolver swig_call_bkpt_resolver) {
g_swig_init_callback = swig_init_callback;
g_swig_breakpoint_callback = swig_breakpoint_callback;
g_swig_watchpoint_callback = swig_watchpoint_callback;
@@ -3126,6 +3281,8 @@ void ScriptInterpreterPython::InitializeInterpreter(
g_swig_call_command_object = swig_call_command_object;
g_swig_call_module_init = swig_call_module_init;
g_swig_create_os_plugin = swig_create_os_plugin;
+ g_swig_create_frame_recognizer = swig_create_frame_recognizer;
+ g_swig_get_recognized_arguments = swig_get_recognized_arguments;
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;
@@ -3134,6 +3291,8 @@ void ScriptInterpreterPython::InitializeInterpreter(
g_swig_plugin_get = swig_plugin_get;
g_swig_thread_plan_script = swig_thread_plan_script;
g_swig_call_thread_plan = swig_call_thread_plan;
+ g_swig_bkpt_resolver_script = swig_bkpt_resolver_script;
+ g_swig_call_bkpt_resolver = swig_call_bkpt_resolver;
}
void ScriptInterpreterPython::InitializePrivate() {
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
index b13979dc069b..a047359883ce 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h
@@ -16,14 +16,10 @@
#else
-// C Includes
-// C++ Includes
#include <memory>
#include <string>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "PythonDataObjects.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/IOHandler.h"
@@ -81,10 +77,25 @@ public:
const char *method_name,
Event *event_sp, bool &got_error);
+ typedef void *(*SWIGPythonCreateScriptedBreakpointResolver)(
+ const char *python_class_name, const char *session_dictionary_name,
+ lldb_private::StructuredDataImpl *args_impl,
+ lldb::BreakpointSP &bkpt_sp);
+
+ typedef unsigned int (*SWIGPythonCallBreakpointResolver)(void *implementor,
+ const char *method_name,
+ lldb_private::SymbolContext *sym_ctx);
+
typedef void *(*SWIGPythonCreateOSPlugin)(const char *python_class_name,
const char *session_dictionary_name,
const lldb::ProcessSP &process_sp);
+ typedef void *(*SWIGPythonCreateFrameRecognizer)(
+ const char *python_class_name, const char *session_dictionary_name);
+
+ typedef void *(*SWIGPythonGetRecognizedArguments)(
+ void *implementor, const lldb::StackFrameSP &frame_sp);
+
typedef size_t (*SWIGPythonCalculateNumChildren)(void *implementor,
uint32_t max);
@@ -208,6 +219,26 @@ public:
lldb::StateType
ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp,
bool &script_error) override;
+
+ StructuredData::GenericSP
+ CreateScriptedBreakpointResolver(const char *class_name,
+ StructuredDataImpl *args_data,
+ lldb::BreakpointSP &bkpt_sp) override;
+ bool
+ ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP
+ implementor_sp,
+ SymbolContext *sym_ctx) override;
+
+ lldb::SearchDepth
+ ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP
+ implementor_sp) override;
+
+ StructuredData::GenericSP
+ CreateFrameRecognizer(const char *class_name) override;
+
+ lldb::ValueObjectListSP
+ GetRecognizedArguments(const StructuredData::ObjectSP &implementor,
+ lldb::StackFrameSP frame_sp) override;
StructuredData::GenericSP
OSPlugin_CreatePluginObject(const char *class_name,
@@ -404,6 +435,8 @@ public:
SWIGPythonCallCommandObject swig_call_command_object,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
+ SWIGPythonCreateFrameRecognizer swig_create_frame_recognizer,
+ SWIGPythonGetRecognizedArguments swig_get_recognized_arguments,
SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
@@ -411,7 +444,9 @@ public:
SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
SWIGPython_GetDynamicSetting swig_plugin_get,
SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
- SWIGPythonCallThreadPlan swig_call_thread_plan);
+ SWIGPythonCallThreadPlan swig_call_thread_plan,
+ SWIGPythonCreateScriptedBreakpointResolver swig_bkpt_resolver_script,
+ SWIGPythonCallBreakpointResolver swig_call_breakpoint_resolver);
const char *GetDictionaryName() { return m_dictionary_name.c_str(); }
diff --git a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index e33e26507fb1..6e3792bff9c4 100644
--- a/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -112,14 +112,14 @@ void SetGlobalEnableOptions(const DebuggerSP &debugger_sp,
/// Code to handle the StructuredDataDarwinLog settings
//------------------------------------------------------------------
-static PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{
"enable-on-startup", // name
OptionValue::eTypeBoolean, // type
true, // global
false, // default uint value
nullptr, // default cstring value
- nullptr, // enum values
+ {}, // enum values
"Enable Darwin os_log collection when debugged process is launched "
"or attached." // description
},
@@ -129,13 +129,11 @@ static PropertyDefinition g_properties[] = {
true, // global
0, // default uint value
"", // default cstring value
- nullptr, // enum values
+ {}, // enum values
"Specify the options to 'plugin structured-data darwin-log enable' "
"that should be applied when automatically enabling logging on "
"startup/attach." // description
- },
- // Last entry sentinel.
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ }};
enum { ePropertyEnableOnStartup = 0, ePropertyAutoEnableOptions = 1 };
@@ -402,23 +400,23 @@ static void RegisterFilterOperations() {
/// This resets the logging with whatever settings are currently set.
// -------------------------------------------------------------------------
-static OptionDefinition g_enable_option_table[] = {
+static constexpr OptionDefinition g_enable_option_table[] = {
// Source stream include/exclude options (the first-level filter). This one
// should be made as small as possible as everything that goes through here
// must be processed by the process monitor.
{LLDB_OPT_SET_ALL, false, "any-process", 'a', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Specifies log messages from other related processes should be "
"included."},
{LLDB_OPT_SET_ALL, false, "debug", 'd', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone,
+ {}, 0, eArgTypeNone,
"Specifies debug-level log messages should be included. Specifying"
" --debug implies --info."},
{LLDB_OPT_SET_ALL, false, "info", 'i', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone,
+ {}, 0, eArgTypeNone,
"Specifies info-level log messages should be included."},
{LLDB_OPT_SET_ALL, false, "filter", 'f', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgRawInput,
+ nullptr, {}, 0, eArgRawInput,
// There doesn't appear to be a great way for me to have these multi-line,
// formatted tables in help. This looks mostly right but there are extra
// linefeeds added at seemingly random spots, and indentation isn't
@@ -452,52 +450,52 @@ static OptionDefinition g_enable_option_table[] = {
"Prefer character classes like [[:digit:]] to \\d and the like, as "
"getting the backslashes escaped through properly is error-prone."},
{LLDB_OPT_SET_ALL, false, "live-stream", 'l',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Specify whether logging events are live-streamed or buffered. "
"True indicates live streaming, false indicates buffered. The "
"default is true (live streaming). Live streaming will deliver "
"log messages with less delay, but buffered capture mode has less "
"of an observer effect."},
{LLDB_OPT_SET_ALL, false, "no-match-accepts", 'n',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Specify whether a log message that doesn't match any filter rule "
"is accepted or rejected, where true indicates accept. The "
"default is true."},
{LLDB_OPT_SET_ALL, false, "echo-to-stderr", 'e',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Specify whether os_log()/NSLog() messages are echoed to the "
"target program's stderr. When DarwinLog is enabled, we shut off "
"the mirroring of os_log()/NSLog() to the program's stderr. "
"Setting this flag to true will restore the stderr mirroring."
"The default is false."},
{LLDB_OPT_SET_ALL, false, "broadcast-events", 'b',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Specify if the plugin should broadcast events. Broadcasting "
"log events is a requirement for displaying the log entries in "
"LLDB command-line. It is also required if LLDB clients want to "
"process log events. The default is true."},
// Message formatting options
{LLDB_OPT_SET_ALL, false, "timestamp-relative", 'r',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Include timestamp in the message header when printing a log "
"message. The timestamp is relative to the first displayed "
"message."},
{LLDB_OPT_SET_ALL, false, "subsystem", 's', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
- "Include the subsystem in the the message header when displaying "
+ nullptr, {}, 0, eArgTypeNone,
+ "Include the subsystem in the message header when displaying "
"a log message."},
{LLDB_OPT_SET_ALL, false, "category", 'c', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Include the category in the message header when displaying "
"a log message."},
{LLDB_OPT_SET_ALL, false, "activity-chain", 'C', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Include the activity parent-child chain in the message header "
"when displaying a log message. The activity hierarchy is "
"displayed as {grandparent-activity}:"
"{parent-activity}:{activity}[:...]."},
{LLDB_OPT_SET_ALL, false, "all-fields", 'A', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Shortcut to specify that all header fields should be displayed."}};
class EnableOptions : public Options {
@@ -1679,7 +1677,7 @@ void StructuredDataDarwinLog::AddInitCompletionHook(Process &process) {
// Build up the module list.
FileSpecList module_spec_list;
auto module_file_spec =
- FileSpec(GetGlobalProperties()->GetLoggingModuleName(), false);
+ FileSpec(GetGlobalProperties()->GetLoggingModuleName());
module_spec_list.Append(module_file_spec);
// We aren't specifying a source file set.
diff --git a/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt b/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt
new file mode 100644
index 000000000000..e93d0618a0e4
--- /dev/null
+++ b/source/Plugins/SymbolFile/Breakpad/CMakeLists.txt
@@ -0,0 +1,12 @@
+add_lldb_library(lldbPluginSymbolFileBreakpad PLUGIN
+ SymbolFileBreakpad.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbUtility
+ lldbPluginObjectFileBreakpad
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
new file mode 100644
index 000000000000..2cca7a66b014
--- /dev/null
+++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -0,0 +1,223 @@
+//===-- SymbolFileBreakpad.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Utility/Log.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::breakpad;
+
+namespace {
+class LineIterator {
+public:
+ // begin iterator for sections of given type
+ LineIterator(ObjectFile &obj, ConstString section_type)
+ : m_obj(&obj), m_section_type(section_type), m_next_section_idx(0) {
+ ++*this;
+ }
+
+ // end iterator
+ explicit LineIterator(ObjectFile &obj)
+ : m_obj(&obj),
+ m_next_section_idx(m_obj->GetSectionList()->GetNumSections(0)) {}
+
+ friend bool operator!=(const LineIterator &lhs, const LineIterator &rhs) {
+ assert(lhs.m_obj == rhs.m_obj);
+ if (lhs.m_next_section_idx != rhs.m_next_section_idx)
+ return true;
+ if (lhs.m_next_text.data() != rhs.m_next_text.data())
+ return true;
+ assert(lhs.m_current_text == rhs.m_current_text);
+ assert(rhs.m_next_text == rhs.m_next_text);
+ return false;
+ }
+
+ const LineIterator &operator++();
+ llvm::StringRef operator*() const { return m_current_text; }
+
+private:
+ ObjectFile *m_obj;
+ ConstString m_section_type;
+ uint32_t m_next_section_idx;
+ llvm::StringRef m_current_text;
+ llvm::StringRef m_next_text;
+};
+} // namespace
+
+const LineIterator &LineIterator::operator++() {
+ const SectionList &list = *m_obj->GetSectionList();
+ size_t num_sections = list.GetNumSections(0);
+ while (m_next_text.empty() && m_next_section_idx < num_sections) {
+ Section &sect = *list.GetSectionAtIndex(m_next_section_idx++);
+ if (sect.GetName() != m_section_type)
+ continue;
+ DataExtractor data;
+ m_obj->ReadSectionData(&sect, data);
+ m_next_text =
+ llvm::StringRef(reinterpret_cast<const char *>(data.GetDataStart()),
+ data.GetByteSize());
+ }
+ std::tie(m_current_text, m_next_text) = m_next_text.split('\n');
+ return *this;
+}
+
+static llvm::iterator_range<LineIterator> lines(ObjectFile &obj,
+ ConstString section_type) {
+ return llvm::make_range(LineIterator(obj, section_type), LineIterator(obj));
+}
+
+void SymbolFileBreakpad::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+}
+
+void SymbolFileBreakpad::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString SymbolFileBreakpad::GetPluginNameStatic() {
+ static ConstString g_name("breakpad");
+ return g_name;
+}
+
+uint32_t SymbolFileBreakpad::CalculateAbilities() {
+ if (!m_obj_file)
+ return 0;
+ if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic())
+ return 0;
+
+ return CompileUnits | Functions;
+}
+
+uint32_t SymbolFileBreakpad::GetNumCompileUnits() {
+ // TODO
+ return 0;
+}
+
+CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {
+ // TODO
+ return nullptr;
+}
+
+size_t SymbolFileBreakpad::ParseFunctions(CompileUnit &comp_unit) {
+ // TODO
+ return 0;
+}
+
+bool SymbolFileBreakpad::ParseLineTable(CompileUnit &comp_unit) {
+ // TODO
+ return 0;
+}
+
+uint32_t
+SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
+ SymbolContextItem resolve_scope,
+ SymbolContext &sc) {
+ // TODO
+ return 0;
+}
+
+uint32_t SymbolFileBreakpad::FindFunctions(
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ FunctionNameType name_type_mask, bool include_inlines, bool append,
+ SymbolContextList &sc_list) {
+ // TODO
+ if (!append)
+ sc_list.Clear();
+ return sc_list.GetSize();
+}
+
+uint32_t SymbolFileBreakpad::FindFunctions(const RegularExpression &regex,
+ bool include_inlines, bool append,
+ SymbolContextList &sc_list) {
+ // TODO
+ if (!append)
+ sc_list.Clear();
+ return sc_list.GetSize();
+}
+
+uint32_t SymbolFileBreakpad::FindTypes(
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, uint32_t max_matches,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+ if (!append)
+ types.Clear();
+ return types.GetSize();
+}
+
+size_t
+SymbolFileBreakpad::FindTypes(const std::vector<CompilerContext> &context,
+ bool append, TypeMap &types) {
+ if (!append)
+ types.Clear();
+ return types.GetSize();
+}
+
+void SymbolFileBreakpad::AddSymbols(Symtab &symtab) {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
+ Module &module = *m_obj_file->GetModule();
+ addr_t base = module.GetObjectFile()->GetBaseAddress().GetFileAddress();
+ if (base == LLDB_INVALID_ADDRESS) {
+ LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping "
+ "symtab population.");
+ return;
+ }
+
+ const SectionList &list = *module.GetSectionList();
+ for (llvm::StringRef line : lines(*m_obj_file, ConstString("PUBLIC"))) {
+ // PUBLIC [m] address param_size name
+ // skip PUBLIC keyword
+ line = getToken(line).second;
+ llvm::StringRef token;
+ std::tie(token, line) = getToken(line);
+ if (token == "m")
+ std::tie(token, line) = getToken(line);
+
+ addr_t address;
+ if (!to_integer(token, address, 16))
+ continue;
+ address += base;
+
+ // skip param_size
+ line = getToken(line).second;
+
+ llvm::StringRef name = line.trim();
+
+ SectionSP section_sp = list.FindSectionContainingFileAddress(address);
+ if (!section_sp) {
+ LLDB_LOG(log,
+ "Ignoring symbol {0}, whose address ({1}) is outside of the "
+ "object file. Mismatched symbol file?",
+ name, address);
+ continue;
+ }
+
+ symtab.AddSymbol(Symbol(
+ /*symID*/ 0, Mangled(name, /*is_mangled*/ false), eSymbolTypeCode,
+ /*is_global*/ true, /*is_debug*/ false, /*is_trampoline*/ false,
+ /*is_artificial*/ false,
+ AddressRange(section_sp, address - section_sp->GetFileAddress(), 0),
+ /*size_is_valid*/ 0, /*contains_linker_annotations*/ false,
+ /*flags*/ 0));
+ }
+
+ // TODO: Process FUNC records as well.
+
+ symtab.CalculateSymbolSizes();
+}
diff --git a/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
new file mode 100644
index 000000000000..68e8d11c7dd7
--- /dev/null
+++ b/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -0,0 +1,146 @@
+//===-- SymbolFileBreakpad.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_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
+#define LLDB_PLUGINS_SYMBOLFILE_BREAKPAD_SYMBOLFILEBREAKPAD_H
+
+#include "lldb/Symbol/SymbolFile.h"
+
+namespace lldb_private {
+
+namespace breakpad {
+
+class SymbolFileBreakpad : public SymbolFile {
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+ static void Terminate();
+ static void DebuggerInitialize(Debugger &debugger) {}
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic() {
+ return "Breakpad debug symbol file reader.";
+ }
+
+ static SymbolFile *CreateInstance(ObjectFile *obj_file) {
+ return new SymbolFileBreakpad(obj_file);
+ }
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SymbolFileBreakpad(ObjectFile *object_file) : SymbolFile(object_file) {}
+
+ ~SymbolFileBreakpad() override {}
+
+ uint32_t CalculateAbilities() override;
+
+ void InitializeObject() override {}
+
+ //------------------------------------------------------------------
+ // Compile Unit function calls
+ //------------------------------------------------------------------
+
+ uint32_t GetNumCompileUnits() override;
+
+ lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
+
+ lldb::LanguageType ParseLanguage(CompileUnit &comp_unit) override {
+ return lldb::eLanguageTypeUnknown;
+ }
+
+ size_t ParseFunctions(CompileUnit &comp_unit) override;
+
+ bool ParseLineTable(CompileUnit &comp_unit) override;
+
+ bool ParseDebugMacros(CompileUnit &comp_unit) override { return false; }
+
+ bool ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) override {
+ return false;
+ }
+ size_t ParseTypes(CompileUnit &cu) override { return 0; }
+
+ bool
+ ParseImportedModules(const SymbolContext &sc,
+ std::vector<ConstString> &imported_modules) override {
+ return false;
+ }
+
+ size_t ParseBlocksRecursive(Function &func) override { return 0; }
+
+ uint32_t FindGlobalVariables(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ uint32_t max_matches,
+ VariableList &variables) override {
+ return 0;
+ }
+
+ size_t ParseVariablesForContext(const SymbolContext &sc) override {
+ return 0;
+ }
+ Type *ResolveTypeUID(lldb::user_id_t type_uid) override { return nullptr; }
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override {
+ return llvm::None;
+ }
+
+ bool CompleteType(CompilerType &compiler_type) override { return false; }
+ uint32_t ResolveSymbolContext(const Address &so_addr,
+ lldb::SymbolContextItem resolve_scope,
+ SymbolContext &sc) override;
+
+ size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
+ TypeList &type_list) override {
+ return 0;
+ }
+
+ uint32_t FindFunctions(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ lldb::FunctionNameType name_type_mask,
+ bool include_inlines, bool append,
+ SymbolContextList &sc_list) override;
+
+ uint32_t FindFunctions(const RegularExpression &regex, bool include_inlines,
+ bool append, SymbolContextList &sc_list) override;
+
+ uint32_t FindTypes(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx, bool append,
+ uint32_t max_matches,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ TypeMap &types) override;
+
+ size_t FindTypes(const std::vector<CompilerContext> &context, bool append,
+ TypeMap &types) override;
+
+ TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override {
+ return nullptr;
+ }
+
+ CompilerDeclContext
+ FindNamespace(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx) override {
+ return CompilerDeclContext();
+ }
+
+ void AddSymbols(Symtab &symtab) override;
+
+ ConstString GetPluginName() override { return GetPluginNameStatic(); }
+ uint32_t GetPluginVersion() override { return 1; }
+
+private:
+};
+
+} // namespace breakpad
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/SymbolFile/CMakeLists.txt b/source/Plugins/SymbolFile/CMakeLists.txt
index 98510704ce73..ad1c92bd8469 100644
--- a/source/Plugins/SymbolFile/CMakeLists.txt
+++ b/source/Plugins/SymbolFile/CMakeLists.txt
@@ -1,3 +1,5 @@
+add_subdirectory(Breakpad)
add_subdirectory(DWARF)
add_subdirectory(Symtab)
+add_subdirectory(NativePDB)
add_subdirectory(PDB)
diff --git a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
index f62a496f808a..0e47ee34fe51 100644
--- a/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
+++ b/source/Plugins/SymbolFile/DWARF/CMakeLists.txt
@@ -4,9 +4,6 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
DIERef.cpp
DWARFAbbreviationDeclaration.cpp
DWARFASTParserClang.cpp
- DWARFASTParserGo.cpp
- DWARFASTParserJava.cpp
- DWARFASTParserOCaml.cpp
DWARFAttribute.cpp
DWARFBaseDIE.cpp
DWARFCompileUnit.cpp
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
index ae7c770d6ef7..24d5f26745dc 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParser.h
@@ -12,10 +12,16 @@
#include "DWARFDefines.h"
#include "lldb/Core/PluginInterface.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
class DWARFDIE;
+namespace lldb_private {
+class CompileUnit;
+class ExecutionContext;
+}
+class SymbolFileDWARF;
class DWARFASTParser {
public:
@@ -27,7 +33,7 @@ public:
bool *type_is_new_ptr) = 0;
virtual lldb_private::Function *
- ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
+ ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
const DWARFDIE &die) = 0;
virtual bool
@@ -45,6 +51,10 @@ public:
virtual std::vector<DWARFDIE>
GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) = 0;
+
+ static llvm::Optional<lldb_private::SymbolFile::ArrayInfo>
+ ParseChildArrayInfo(const DWARFDIE &parent_die,
+ const lldb_private::ExecutionContext *exe_ctx = nullptr);
};
#endif // SymbolFileDWARF_DWARFASTParser_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index fe6f1be3ca48..70d48e5f1dfa 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -125,7 +125,7 @@ ClangASTImporter &DWARFASTParserClang::GetClangASTImporter() {
}
/// Detect a forward declaration that is nested in a DW_TAG_module.
-static bool isClangModuleFwdDecl(const DWARFDIE &Die) {
+static bool IsClangModuleFwdDecl(const DWARFDIE &Die) {
if (!Die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
return false;
auto Parent = Die.GetParent();
@@ -142,30 +142,31 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWO(const DWARFDIE &die, Log *log) {
if (!dwo_module_sp)
return TypeSP();
- // This type comes from an external DWO module.
- std::vector<CompilerContext> dwo_context;
- die.GetDWOContext(dwo_context);
+ // If this type comes from a Clang module, look in the DWARF section
+ // of the pcm file in the module cache. Clang generates DWO skeleton
+ // units as breadcrumbs to find them.
+ std::vector<CompilerContext> decl_context;
+ die.GetDeclContext(decl_context);
TypeMap dwo_types;
- if (!dwo_module_sp->GetSymbolVendor()->FindTypes(dwo_context, true,
+ if (!dwo_module_sp->GetSymbolVendor()->FindTypes(decl_context, true,
dwo_types)) {
- if (!isClangModuleFwdDecl(die))
+ if (!IsClangModuleFwdDecl(die))
return TypeSP();
// Since this this type is defined in one of the Clang modules imported by
// this symbol file, search all of them.
- auto *SymFile = die.GetCU()->GetSymbolFileDWARF();
- for (const auto &NameModule : SymFile->getExternalTypeModules()) {
- if (!NameModule.second)
+ auto *sym_file = die.GetCU()->GetSymbolFileDWARF();
+ for (const auto &name_module : sym_file->getExternalTypeModules()) {
+ if (!name_module.second)
continue;
- SymbolVendor *SymVendor = NameModule.second->GetSymbolVendor();
- if (SymVendor->FindTypes(dwo_context, true, dwo_types))
+ SymbolVendor *sym_vendor = name_module.second->GetSymbolVendor();
+ if (sym_vendor->FindTypes(decl_context, true, dwo_types))
break;
}
}
- const size_t num_dwo_types = dwo_types.GetSize();
- if (num_dwo_types != 1)
+ if (dwo_types.GetSize() != 1)
return TypeSP();
// We found a real definition for this type in the Clang module, so lets use
@@ -307,14 +308,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
decl.SetColumn(form_value.Unsigned());
break;
case DW_AT_name:
-
type_name_cstr = form_value.AsCString();
- // Work around a bug in llvm-gcc where they give a name to a
- // reference type which doesn't include the "&"...
- if (tag == DW_TAG_reference_type) {
- if (strchr(type_name_cstr, '&') == NULL)
- type_name_cstr = NULL;
- }
if (type_name_cstr)
type_name_const_str.SetCString(type_name_cstr);
break;
@@ -421,8 +415,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (!clang_type &&
(encoding_data_type == Type::eEncodingIsPointerUID ||
- encoding_data_type == Type::eEncodingIsTypedefUID) &&
- sc.comp_unit != NULL) {
+ encoding_data_type == Type::eEncodingIsTypedefUID)) {
if (tag == DW_TAG_pointer_type) {
DWARFDIE target_die = die.GetReferencedDIE(DW_AT_type);
@@ -558,16 +551,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
switch (attr) {
case DW_AT_decl_file:
- if (die.GetCU()->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.
- decl.SetFile(FileSpec("<invalid>", false));
- } else
- decl.SetFile(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
- form_value.Unsigned()));
+ decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
+ form_value.Unsigned()));
break;
case DW_AT_decl_line:
@@ -671,7 +656,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
if (byte_size_valid && byte_size == 0 && type_name_cstr &&
- die.HasChildren() == false &&
+ !die.HasChildren() &&
sc.comp_unit->GetLanguage() == eLanguageTypeObjC) {
// Work around an issue with clang at the moment where forward
// declarations for objective C classes are emitted as:
@@ -909,7 +894,7 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
// has child classes or types that require the class to be created
// for use as their decl contexts the class will be ready to accept
// these child definitions.
- if (die.HasChildren() == false) {
+ if (!die.HasChildren()) {
// No children for this struct/union/class, lets finish it
if (ClangASTContext::StartTagDeclarationDefinition(clang_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
@@ -1308,10 +1293,10 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
if (die.HasChildren()) {
bool skip_artificial = true;
- ParseChildParameters(sc, containing_decl_ctx, die, skip_artificial,
- is_static, is_variadic, has_template_params,
- function_param_types, function_param_decls,
- type_quals);
+ ParseChildParameters(*sc.comp_unit, containing_decl_ctx, die,
+ skip_artificial, is_static, is_variadic,
+ has_template_params, function_param_types,
+ function_param_decls, type_quals);
}
bool ignore_containing_context = false;
@@ -1748,16 +1733,19 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
Type *element_type = dwarf->ResolveTypeUID(type_die_ref);
if (element_type) {
- std::vector<uint64_t> element_orders;
- ParseChildArrayInfo(sc, die, first_index, element_orders,
- byte_stride, bit_stride);
+ auto array_info = ParseChildArrayInfo(die);
+ if (array_info) {
+ first_index = array_info->first_index;
+ byte_stride = array_info->byte_stride;
+ bit_stride = array_info->bit_stride;
+ }
if (byte_stride == 0 && bit_stride == 0)
byte_stride = element_type->GetByteSize();
CompilerType array_element_type =
element_type->GetForwardCompilerType();
if (ClangASTContext::IsCXXClassType(array_element_type) &&
- array_element_type.GetCompleteType() == false) {
+ !array_element_type.GetCompleteType()) {
ModuleSP module_sp = die.GetModule();
if (module_sp) {
if (die.GetCU()->GetProducer() == eProducerClang)
@@ -1800,12 +1788,11 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
}
uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
- if (element_orders.size() > 0) {
+ if (array_info && array_info->element_orders.size() > 0) {
uint64_t num_elements = 0;
- std::vector<uint64_t>::const_reverse_iterator pos;
- std::vector<uint64_t>::const_reverse_iterator end =
- element_orders.rend();
- for (pos = element_orders.rbegin(); pos != end; ++pos) {
+ auto end = array_info->element_orders.rend();
+ for (auto pos = array_info->element_orders.rbegin(); pos != end;
+ ++pos) {
num_elements = *pos;
clang_type = m_ast.CreateArrayType(array_element_type,
num_elements, is_vector);
@@ -1824,6 +1811,8 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
NULL, DIERef(type_die_form).GetUID(dwarf), Type::eEncodingIsUID,
&decl, clang_type, Type::eResolveStateFull));
type_sp->SetEncodingType(element_type);
+ m_ast.SetMetadataAsUserID(clang_type.GetOpaqueQualType(),
+ die.GetID());
}
}
} break;
@@ -1861,12 +1850,14 @@ TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc,
clang_type = ClangASTContext::CreateMemberPointerType(
class_clang_type, pointee_clang_type);
- byte_size = clang_type.GetByteSize(nullptr);
-
- type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
- byte_size, NULL, LLDB_INVALID_UID,
- Type::eEncodingIsUID, NULL, clang_type,
- Type::eResolveStateForward));
+ if (llvm::Optional<uint64_t> clang_type_size =
+ clang_type.GetByteSize(nullptr)) {
+ byte_size = *clang_type_size;
+ type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
+ byte_size, NULL, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, NULL, clang_type,
+ Type::eResolveStateForward));
+ }
}
break;
@@ -2056,7 +2047,10 @@ bool DWARFASTParserClang::ParseTemplateDIE(
clang_type.IsIntegerOrEnumerationType(is_signed);
if (tag == DW_TAG_template_value_parameter && uval64_valid) {
- llvm::APInt apint(clang_type.GetBitSize(nullptr), uval64, is_signed);
+ llvm::Optional<uint64_t> size = clang_type.GetBitSize(nullptr);
+ if (!size)
+ return false;
+ llvm::APInt apint(*size, uval64, is_signed);
template_param_infos.args.push_back(
clang::TemplateArgument(*ast, llvm::APSInt(apint, !is_signed),
ClangUtil::GetQualType(clang_type)));
@@ -2108,95 +2102,6 @@ bool DWARFASTParserClang::ParseTemplateParameterInfos(
return template_param_infos.args.size() == template_param_infos.names.size();
}
-// Checks whether m1 is an overload of m2 (as opposed to an override). This is
-// called by addOverridesForMethod to distinguish overrides (which share a
-// vtable entry) from overloads (which require distinct entries).
-static bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
- // FIXME: This should detect covariant return types, but currently doesn't.
- lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
- "Methods should have the same AST context");
- clang::ASTContext &context = m1->getASTContext();
-
- const auto *m1Type =
- llvm::cast<clang::FunctionProtoType>(
- context.getCanonicalType(m1->getType()));
-
- const auto *m2Type =
- llvm::cast<clang::FunctionProtoType>(
- context.getCanonicalType(m2->getType()));
-
- auto compareArgTypes =
- [&context](const clang::QualType &m1p, const clang::QualType &m2p) {
- return context.hasSameType(m1p.getUnqualifiedType(),
- m2p.getUnqualifiedType());
- };
-
- // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
- // as a fourth parameter to std::equal().
- return (m1->getNumParams() != m2->getNumParams()) ||
- !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
- m2Type->param_type_begin(), compareArgTypes);
-}
-
-// If decl is a virtual method, walk the base classes looking for methods that
-// decl overrides. This table of overridden methods is used by IRGen to
-// determine the vtable layout for decl's parent class.
-static void addOverridesForMethod(clang::CXXMethodDecl *decl) {
- if (!decl->isVirtual())
- return;
-
- clang::CXXBasePaths paths;
-
- auto find_overridden_methods =
- [decl](const clang::CXXBaseSpecifier *specifier, clang::CXXBasePath &path) {
- if (auto *base_record =
- llvm::dyn_cast<clang::CXXRecordDecl>(
- specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
-
- clang::DeclarationName name = decl->getDeclName();
-
- // If this is a destructor, check whether the base class destructor is
- // virtual.
- if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
- if (auto *baseDtorDecl = base_record->getDestructor()) {
- if (baseDtorDecl->isVirtual()) {
- path.Decls = baseDtorDecl;
- return true;
- } else
- return false;
- }
-
- // Otherwise, search for name in the base class.
- for (path.Decls = base_record->lookup(name); !path.Decls.empty();
- path.Decls = path.Decls.slice(1)) {
- if (auto *method_decl =
- llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
- if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
- path.Decls = method_decl;
- return true;
- }
- }
- }
-
- return false;
- };
-
- if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
- for (auto *overridden_decl : paths.found_decls())
- decl->addOverriddenMethod(
- llvm::cast<clang::CXXMethodDecl>(overridden_decl));
- }
-}
-
-// If clang_type is a CXXRecordDecl, builds the method override list for each
-// of its virtual methods.
-static void addMethodOverrides(ClangASTContext &ast, CompilerType &clang_type) {
- if (auto *record =
- ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType()))
- for (auto *method : record->methods())
- addOverridesForMethod(method);
-}
-
bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
lldb_private::Type *type,
CompilerType &clang_type) {
@@ -2287,14 +2192,14 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
}
SymbolContext sc(die.GetLLDBCompileUnit());
- std::vector<clang::CXXBaseSpecifier *> base_classes;
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
std::vector<int> member_accessibilities;
bool is_a_class = false;
// Parse members and base classes first
DWARFDIECollection member_function_dies;
DelayedPropertyList delayed_properties;
- ParseChildMembers(sc, die, clang_type, class_language, base_classes,
+ ParseChildMembers(sc, die, clang_type, class_language, bases,
member_accessibilities, member_function_dies,
delayed_properties, default_accessibility, is_a_class,
layout_info);
@@ -2358,17 +2263,17 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
&member_accessibilities.front(), member_accessibilities.size());
}
- if (!base_classes.empty()) {
+ if (!bases.empty()) {
// Make sure all base classes refer to complete types and not forward
// declarations. If we don't do this, clang will crash with an
- // assertion in the call to clang_type.SetBaseClassesForClassType()
- for (auto &base_class : base_classes) {
+ // assertion in the call to clang_type.TransferBaseClasses()
+ for (const auto &base_class : bases) {
clang::TypeSourceInfo *type_source_info =
base_class->getTypeSourceInfo();
if (type_source_info) {
CompilerType base_class_type(
&m_ast, type_source_info->getType().getAsOpaquePtr());
- if (base_class_type.GetCompleteType() == false) {
+ if (!base_class_type.GetCompleteType()) {
auto module = dwarf->GetObjectFile()->GetModule();
module->ReportError(":: Class '%s' has a base class '%s' which "
"does not have a complete definition.",
@@ -2381,7 +2286,7 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
// We have no choice other than to pretend that the base class
// is complete. If we don't do this, clang will crash when we
// call setBases() inside of
- // "clang_type.SetBaseClassesForClassType()" below. Since we
+ // "clang_type.TransferBaseClasses()" below. Since we
// provide layout assistance, all ivars in this class and other
// classes will be fine, this is the best we can do short of
// crashing.
@@ -2393,19 +2298,14 @@ bool DWARFASTParserClang::CompleteTypeFromDWARF(const DWARFDIE &die,
}
}
}
- m_ast.SetBaseClassesForClassType(clang_type.GetOpaqueQualType(),
- &base_classes.front(),
- base_classes.size());
-
- // Clang will copy each CXXBaseSpecifier in "base_classes" so we have
- // to free them all.
- ClangASTContext::DeleteBaseClassSpecifiers(&base_classes.front(),
- base_classes.size());
+
+ m_ast.TransferBaseClasses(clang_type.GetOpaqueQualType(),
+ std::move(bases));
}
}
}
- addMethodOverrides(m_ast, clang_type);
+ m_ast.AddMethodOverridesForCXXRecordType(clang_type.GetOpaqueQualType());
ClangASTContext::BuildIndirectFields(clang_type);
ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
@@ -2604,9 +2504,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
if (name && name[0] && got_value) {
m_ast.AddEnumerationValueToEnumerationType(
- clang_type.GetOpaqueQualType(),
- m_ast.GetEnumerationIntegerType(clang_type.GetOpaqueQualType()),
- decl, name, enum_value, enumerator_byte_size * 8);
+ clang_type, decl, name, enum_value, enumerator_byte_size * 8);
++enumerators_added;
}
}
@@ -2663,7 +2561,7 @@ protected:
};
#endif
-Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
+Function *DWARFASTParserClang::ParseFunctionFromDWARF(CompileUnit &comp_unit,
const DWARFDIE &die) {
DWARFRangeList func_ranges;
const char *name = NULL;
@@ -2724,9 +2622,9 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
clang::DeclContext *containing_decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
- ParseChildParameters(sc, containing_decl_ctx, die, true, is_static,
- is_variadic, has_template_params, param_types,
- param_decls, type_quals);
+ ParseChildParameters(comp_unit, containing_decl_ctx, die, true,
+ is_static, is_variadic, has_template_params,
+ param_types, param_decls, type_quals);
sstr << "(";
for (size_t i = 0; i < param_types.size(); i++) {
if (i > 0)
@@ -2747,7 +2645,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
std::unique_ptr<Declaration> decl_ap;
if (decl_file != 0 || decl_line != 0 || decl_column != 0)
decl_ap.reset(new Declaration(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
+ comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file),
decl_line, decl_column));
SymbolFileDWARF *dwarf = die.GetDWARF();
@@ -2758,7 +2656,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
const user_id_t func_user_id = die.GetID();
- func_sp.reset(new Function(sc.comp_unit,
+ func_sp.reset(new Function(&comp_unit,
func_user_id, // UserID is the DIE offset
func_user_id, func_name, func_type,
func_range)); // first address range
@@ -2766,7 +2664,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
if (func_sp.get() != NULL) {
if (frame_base.IsValid())
func_sp->GetFrameBaseExpression() = frame_base;
- sc.comp_unit->AddFunction(func_sp);
+ comp_unit.AddFunction(func_sp);
return func_sp.get();
}
}
@@ -2778,7 +2676,7 @@ Function *DWARFASTParserClang::ParseFunctionFromDWARF(const SymbolContext &sc,
bool DWARFASTParserClang::ParseChildMembers(
const SymbolContext &sc, const DWARFDIE &parent_die,
CompilerType &class_clang_type, const LanguageType class_language,
- std::vector<clang::CXXBaseSpecifier *> &base_classes,
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
std::vector<int> &member_accessibilities,
DWARFDIECollection &member_function_dies,
DelayedPropertyList &delayed_properties, AccessType &default_accessibility,
@@ -2977,15 +2875,6 @@ bool DWARFASTParserClang::ParseChildMembers(
class_language == eLanguageTypeObjC_plus_plus)
accessibility = eAccessNone;
- if (member_idx == 0 && !is_artificial && name &&
- (strstr(name, "_vptr$") == name)) {
- // Not all compilers will mark the vtable pointer member as
- // artificial (llvm-gcc). We can't have the virtual members in our
- // classes otherwise it throws off all child offsets since we end up
- // having and extra pointer sized member in our class layouts.
- is_artificial = true;
- }
-
// Handle static members
if (is_external && member_byte_offset == UINT32_MAX) {
Type *var_type = die.ResolveTypeUID(DIERef(encoding_form));
@@ -3000,7 +2889,7 @@ bool DWARFASTParserClang::ParseChildMembers(
break;
}
- if (is_artificial == false) {
+ if (!is_artificial) {
Type *member_type = die.ResolveTypeUID(DIERef(encoding_form));
clang::FieldDecl *field_decl = NULL;
@@ -3141,7 +3030,7 @@ bool DWARFASTParserClang::ParseChildMembers(
if (anon_field_info.IsValid()) {
clang::FieldDecl *unnamed_bitfield_decl =
ClangASTContext::AddFieldToRecordType(
- class_clang_type, NULL,
+ class_clang_type, llvm::StringRef(),
m_ast.GetBuiltinTypeForEncodingAndBitSize(
eEncodingSint, word_width),
accessibility, anon_field_info.bit_size);
@@ -3198,7 +3087,7 @@ bool DWARFASTParserClang::ParseChildMembers(
}
if (ClangASTContext::IsCXXClassType(member_clang_type) &&
- member_clang_type.GetCompleteType() == false) {
+ !member_clang_type.GetCompleteType()) {
if (die.GetCU()->GetProducer() == eProducerClang)
module_sp->ReportError(
"DWARF DIE at 0x%8.8x (class %s) has a member variable "
@@ -3383,9 +3272,14 @@ bool DWARFASTParserClang::ParseChildMembers(
if (class_language == eLanguageTypeObjC) {
ast->SetObjCSuperClass(class_clang_type, base_class_clang_type);
} else {
- base_classes.push_back(ast->CreateBaseClassSpecifier(
- base_class_clang_type.GetOpaqueQualType(), accessibility,
- is_virtual, is_base_of_class));
+ std::unique_ptr<clang::CXXBaseSpecifier> result =
+ ast->CreateBaseClassSpecifier(
+ base_class_clang_type.GetOpaqueQualType(), accessibility,
+ is_virtual, is_base_of_class);
+ if (!result)
+ break;
+
+ base_classes.push_back(std::move(result));
if (is_virtual) {
// Do not specify any offset for virtual inheritance. The DWARF
@@ -3419,7 +3313,7 @@ bool DWARFASTParserClang::ParseChildMembers(
}
size_t DWARFASTParserClang::ParseChildParameters(
- const SymbolContext &sc, clang::DeclContext *containing_decl_ctx,
+ CompileUnit &comp_unit, clang::DeclContext *containing_decl_ctx,
const DWARFDIE &parent_die, bool skip_artificial, bool &is_static,
bool &is_variadic, bool &has_template_params,
std::vector<CompilerType> &function_param_types,
@@ -3451,7 +3345,7 @@ size_t DWARFASTParserClang::ParseChildParameters(
if (attributes.ExtractFormValueAtIndex(i, form_value)) {
switch (attr) {
case DW_AT_decl_file:
- decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
+ decl.SetFile(comp_unit.GetSupportFiles().GetFileSpecAtIndex(
form_value.Unsigned()));
break;
case DW_AT_decl_line:
@@ -3517,8 +3411,9 @@ size_t DWARFASTParserClang::ParseChildParameters(
function_param_types.push_back(type->GetForwardCompilerType());
clang::ParmVarDecl *param_var_decl =
- m_ast.CreateParameterDeclaration(
- name, type->GetForwardCompilerType(), storage);
+ m_ast.CreateParameterDeclaration(containing_decl_ctx, name,
+ type->GetForwardCompilerType(),
+ storage);
assert(param_var_decl);
function_param_decls.push_back(param_var_decl);
@@ -3551,12 +3446,12 @@ size_t DWARFASTParserClang::ParseChildParameters(
return arg_idx;
}
-void DWARFASTParserClang::ParseChildArrayInfo(
- const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
- std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
- uint32_t &bit_stride) {
+llvm::Optional<SymbolFile::ArrayInfo>
+DWARFASTParser::ParseChildArrayInfo(const DWARFDIE &parent_die,
+ const ExecutionContext *exe_ctx) {
+ SymbolFile::ArrayInfo array_info;
if (!parent_die)
- return;
+ return llvm::None;
for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
die = die.GetSibling()) {
@@ -3580,15 +3475,31 @@ void DWARFASTParserClang::ParseChildArrayInfo(
break;
case DW_AT_count:
- num_elements = form_value.Unsigned();
+ if (DWARFDIE var_die = die.GetReferencedDIE(DW_AT_count)) {
+ if (var_die.Tag() == DW_TAG_variable)
+ if (exe_ctx) {
+ if (auto frame = exe_ctx->GetFrameSP()) {
+ Status error;
+ lldb::VariableSP var_sp;
+ auto valobj_sp = frame->GetValueForVariableExpressionPath(
+ var_die.GetName(), eNoDynamicValues, 0, var_sp,
+ error);
+ if (valobj_sp) {
+ num_elements = valobj_sp->GetValueAsUnsigned(0);
+ break;
+ }
+ }
+ }
+ } else
+ num_elements = form_value.Unsigned();
break;
case DW_AT_bit_stride:
- bit_stride = form_value.Unsigned();
+ array_info.bit_stride = form_value.Unsigned();
break;
case DW_AT_byte_stride:
- byte_stride = form_value.Unsigned();
+ array_info.byte_stride = form_value.Unsigned();
break;
case DW_AT_lower_bound:
@@ -3622,11 +3533,12 @@ void DWARFASTParserClang::ParseChildArrayInfo(
num_elements = upper_bound - lower_bound + 1;
}
- element_orders.push_back(num_elements);
+ array_info.element_orders.push_back(num_elements);
}
} break;
}
}
+ return array_info;
}
Type *DWARFASTParserClang::GetTypeForDIE(const DWARFDIE &die) {
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
index 57c1fc07b2b6..63e058d7bf21 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
@@ -10,15 +10,11 @@
#ifndef SymbolFileDWARF_DWARFASTParserClang_h_
#define SymbolFileDWARF_DWARFASTParserClang_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-// Project includes
#include "DWARFASTParser.h"
#include "DWARFDefines.h"
#include "lldb/Core/ClangForward.h"
@@ -26,8 +22,12 @@
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
+namespace lldb_private {
+class CompileUnit;
+}
class DWARFDebugInfoEntry;
class DWARFDIECollection;
+class SymbolFileDWARF;
class DWARFASTParserClang : public DWARFASTParser {
public:
@@ -41,7 +41,7 @@ public:
bool *type_is_new_ptr) override;
lldb_private::Function *
- ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
+ ParseFunctionFromDWARF(lldb_private::CompileUnit &comp_unit,
const DWARFDIE &die) override;
bool
@@ -80,19 +80,19 @@ protected:
lldb_private::ClangASTContext::TemplateParameterInfos
&template_param_infos);
- bool
- ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
- lldb_private::CompilerType &class_compiler_type,
- const lldb::LanguageType class_language,
- std::vector<clang::CXXBaseSpecifier *> &base_classes,
- std::vector<int> &member_accessibilities,
- DWARFDIECollection &member_function_dies,
- DelayedPropertyList &delayed_properties,
- lldb::AccessType &default_accessibility, bool &is_a_class,
- lldb_private::ClangASTImporter::LayoutInfo &layout_info);
+ bool ParseChildMembers(
+ const lldb_private::SymbolContext &sc, const DWARFDIE &die,
+ lldb_private::CompilerType &class_compiler_type,
+ const lldb::LanguageType class_language,
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes,
+ std::vector<int> &member_accessibilities,
+ DWARFDIECollection &member_function_dies,
+ DelayedPropertyList &delayed_properties,
+ lldb::AccessType &default_accessibility, bool &is_a_class,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info);
size_t
- ParseChildParameters(const lldb_private::SymbolContext &sc,
+ ParseChildParameters(lldb_private::CompileUnit &comp_unit,
clang::DeclContext *containing_decl_ctx,
const DWARFDIE &parent_die, bool skip_artificial,
bool &is_static, bool &is_variadic,
@@ -101,11 +101,6 @@ protected:
std::vector<clang::ParmVarDecl *> &function_param_decls,
unsigned &type_quals);
- void ParseChildArrayInfo(const lldb_private::SymbolContext &sc,
- const DWARFDIE &parent_die, int64_t &first_index,
- std::vector<uint64_t> &element_orders,
- uint32_t &byte_stride, uint32_t &bit_stride);
-
size_t ParseChildEnumerators(const lldb_private::SymbolContext &sc,
lldb_private::CompilerType &compiler_type,
bool is_signed, uint32_t enumerator_byte_size,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
deleted file mode 100644
index 328212e4b684..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp
+++ /dev/null
@@ -1,772 +0,0 @@
-//===-- DWARFASTParserGo.cpp ---------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFASTParserGo.h"
-
-#include "DWARFASTParserGo.h"
-#include "DWARFDIE.h"
-#include "DWARFDIECollection.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFDeclContext.h"
-#include "DWARFDefines.h"
-#include "SymbolFileDWARF.h"
-#include "SymbolFileDWARFDebugMap.h"
-#include "UniqueDWARFASTType.h"
-
-#include "clang/Basic/Specifiers.h"
-
-#include "lldb/Core/Module.h"
-#include "lldb/Core/Value.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/TypeList.h"
-
-//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
-
-#ifdef ENABLE_DEBUG_PRINTF
-#include <stdio.h>
-#define DEBUG_PRINTF(fmt, ...) printf(fmt, __VA_ARGS__)
-#else
-#define DEBUG_PRINTF(fmt, ...)
-#endif
-
-#define DW_AT_go_kind 0x2900
-#define DW_AT_go_key 0x2901
-#define DW_AT_go_elem 0x2902
-
-using namespace lldb;
-using namespace lldb_private;
-DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast) : m_ast(ast) {}
-
-DWARFASTParserGo::~DWARFASTParserGo() {}
-
-TypeSP DWARFASTParserGo::ParseTypeFromDWARF(
- const lldb_private::SymbolContext &sc, const DWARFDIE &die,
- lldb_private::Log *log, bool *type_is_new_ptr) {
- TypeSP type_sp;
-
- if (type_is_new_ptr)
- *type_is_new_ptr = false;
-
- if (die) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = "
- "'%s')",
- die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.GetName());
- }
-
- Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
- TypeList *type_list = dwarf->GetTypeList();
- if (type_ptr == NULL) {
- if (type_is_new_ptr)
- *type_is_new_ptr = true;
-
- const dw_tag_t tag = die.Tag();
-
- bool is_forward_declaration = false;
- DWARFAttributes attributes;
- const char *type_name_cstr = NULL;
- ConstString type_name_const_str;
- Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
- uint64_t byte_size = 0;
- uint64_t go_kind = 0;
- Declaration decl;
-
- Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
- CompilerType compiler_type;
- DWARFFormValue form_value;
-
- dw_attr_t attr;
-
- switch (tag) {
- case DW_TAG_base_type:
- case DW_TAG_pointer_type:
- case DW_TAG_typedef:
- case DW_TAG_unspecified_type: {
- // Set a bit that lets us know that we are currently parsing this
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- const size_t num_attributes = die.GetAttributes(attributes);
- lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
-
- if (num_attributes > 0) {
- uint32_t i;
- for (i = 0; i < num_attributes; ++i) {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- type_name_cstr = form_value.AsCString();
- if (type_name_cstr)
- type_name_const_str.SetCString(type_name_cstr);
- break;
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- break;
- case DW_AT_encoding:
- // = form_value.Unsigned();
- break;
- case DW_AT_type:
- encoding_uid = form_value.Reference();
- break;
- case DW_AT_go_kind:
- go_kind = form_value.Unsigned();
- break;
- default:
- // Do we care about DW_AT_go_key or DW_AT_go_elem?
- break;
- }
- }
- }
- }
-
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n",
- die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr,
- encoding_uid);
-
- switch (tag) {
- default:
- break;
-
- case DW_TAG_unspecified_type:
- resolve_state = Type::eResolveStateFull;
- compiler_type = m_ast.CreateVoidType(type_name_const_str);
- break;
-
- case DW_TAG_base_type:
- resolve_state = Type::eResolveStateFull;
- compiler_type =
- m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size);
- break;
-
- case DW_TAG_pointer_type:
- encoding_data_type = Type::eEncodingIsPointerUID;
- break;
- case DW_TAG_typedef:
- encoding_data_type = Type::eEncodingIsTypedefUID;
- CompilerType impl;
- Type *type = dwarf->ResolveTypeUID(encoding_uid);
- if (type) {
- if (go_kind == 0 && type->GetName() == type_name_const_str) {
- // Go emits extra typedefs as a forward declaration. Ignore
- // these.
- dwarf->m_die_to_type[die.GetDIE()] = type;
- return type->shared_from_this();
- }
- impl = type->GetForwardCompilerType();
- compiler_type =
- m_ast.CreateTypedefType(go_kind, type_name_const_str, impl);
- }
- break;
- }
-
- type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
- byte_size, NULL, encoding_uid,
- encoding_data_type, &decl, compiler_type,
- resolve_state));
-
- dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
- } break;
-
- case DW_TAG_structure_type: {
- // Set a bit that lets us know that we are currently parsing this
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
- bool byte_size_valid = false;
-
- const size_t num_attributes = die.GetAttributes(attributes);
- if (num_attributes > 0) {
- uint32_t i;
- for (i = 0; i < num_attributes; ++i) {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- type_name_cstr = form_value.AsCString();
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- byte_size_valid = true;
- break;
-
- case DW_AT_go_kind:
- go_kind = form_value.Unsigned();
- break;
-
- // TODO: Should we use SLICETYPE's DW_AT_go_elem?
- default:
- break;
- }
- }
- }
- }
-
- // TODO(ribrdb): Do we need this?
-
- // UniqueDWARFASTType is large, so don't create a local variables on
- // the stack, put it on the heap. This function is often called
- // recursively and clang isn't good and sharing the stack space for
- // variables in different blocks.
- std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(
- new UniqueDWARFASTType());
-
- // Only try and unique the type if it has a name.
- if (type_name_const_str &&
- dwarf->GetUniqueDWARFASTTypeMap().Find(
- type_name_const_str, die, decl,
- byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) {
- // We have already parsed this type or from another compile unit. GCC
- // loves to use the "one definition rule" which can result in
- // multiple definitions of the same class over and over in each
- // compile unit.
- type_sp = unique_ast_entry_ap->m_type_sp;
- if (type_sp) {
- dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
- return type_sp;
- }
- }
-
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
-
- bool compiler_type_was_created = false;
- compiler_type.SetCompilerType(
- &m_ast,
- dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE()));
- if (!compiler_type) {
- compiler_type_was_created = true;
- compiler_type =
- m_ast.CreateStructType(go_kind, type_name_const_str, byte_size);
- }
-
- type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
- byte_size, NULL, LLDB_INVALID_UID,
- Type::eEncodingIsUID, &decl, compiler_type,
- Type::eResolveStateForward));
-
- // Add our type to the unique type map so we don't end up creating many
- // copies of the same type over and over in the ASTContext for our
- // module
- unique_ast_entry_ap->m_type_sp = type_sp;
- unique_ast_entry_ap->m_die = die;
- unique_ast_entry_ap->m_declaration = decl;
- unique_ast_entry_ap->m_byte_size = byte_size;
- dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str,
- *unique_ast_entry_ap);
-
- if (!is_forward_declaration) {
- // Always start the definition for a class type so that if the class
- // has child classes or types that require the class to be created
- // for use as their decl contexts the class will be ready to accept
- // these child definitions.
- if (die.HasChildren() == false) {
- // No children for this struct/union/class, lets finish it
- m_ast.CompleteStructType(compiler_type);
- } else if (compiler_type_was_created) {
- // Leave this as a forward declaration until we need to know the
- // details of the type. lldb_private::Type will automatically call
- // the SymbolFile virtual function
- // "SymbolFileDWARF::CompleteType(Type *)" When the definition
- // needs to be defined.
- dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] =
- compiler_type.GetOpaqueQualType();
- dwarf->m_forward_decl_clang_type_to_die[compiler_type
- .GetOpaqueQualType()] =
- die.GetDIERef();
- // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true);
- }
- }
- } break;
-
- case DW_TAG_subprogram:
- case DW_TAG_subroutine_type: {
- // Set a bit that lets us know that we are currently parsing this
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- bool is_variadic = false;
- clang::StorageClass storage =
- clang::SC_None; //, Extern, Static, PrivateExtern
-
- const size_t num_attributes = die.GetAttributes(attributes);
- if (num_attributes > 0) {
- uint32_t i;
- for (i = 0; i < num_attributes; ++i) {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- type_name_cstr = form_value.AsCString();
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_external:
- if (form_value.Unsigned()) {
- if (storage == clang::SC_None)
- storage = clang::SC_Extern;
- else
- storage = clang::SC_PrivateExtern;
- }
- break;
-
- case DW_AT_high_pc:
- case DW_AT_low_pc:
- break;
- }
- }
- }
- }
-
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
-
- std::vector<CompilerType> function_param_types;
-
- // Parse the function children for the parameters
-
- if (die.HasChildren()) {
- ParseChildParameters(sc, die, is_variadic, function_param_types);
- }
-
- // compiler_type will get the function prototype clang type after this
- // call
- compiler_type = m_ast.CreateFunctionType(
- type_name_const_str, function_param_types.data(),
- function_param_types.size(), is_variadic);
-
- type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, 0, NULL,
- LLDB_INVALID_UID, Type::eEncodingIsUID, &decl,
- compiler_type, Type::eResolveStateFull));
- assert(type_sp.get());
- } break;
-
- case DW_TAG_array_type: {
- // Set a bit that lets us know that we are currently parsing this
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
- int64_t first_index = 0;
- uint32_t byte_stride = 0;
- uint32_t bit_stride = 0;
- const size_t num_attributes = die.GetAttributes(attributes);
-
- if (num_attributes > 0) {
- uint32_t i;
- for (i = 0; i < num_attributes; ++i) {
- attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- type_name_cstr = form_value.AsCString();
- type_name_const_str.SetCString(type_name_cstr);
- break;
-
- case DW_AT_type:
- type_die_offset = form_value.Reference();
- break;
- case DW_AT_byte_size:
- break; // byte_size = form_value.Unsigned(); break;
- case DW_AT_go_kind:
- go_kind = form_value.Unsigned();
- break;
- default:
- break;
- }
- }
- }
-
- DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(),
- DW_TAG_value_to_name(tag), type_name_cstr);
-
- Type *element_type = dwarf->ResolveTypeUID(type_die_offset);
-
- if (element_type) {
- std::vector<uint64_t> element_orders;
- ParseChildArrayInfo(sc, die, first_index, element_orders,
- byte_stride, bit_stride);
- if (byte_stride == 0)
- byte_stride = element_type->GetByteSize();
- CompilerType array_element_type =
- element_type->GetForwardCompilerType();
- if (element_orders.size() > 0) {
- if (element_orders.size() > 1)
- printf("golang: unsupported multi-dimensional array %s\n",
- type_name_cstr);
- compiler_type = m_ast.CreateArrayType(
- type_name_const_str, array_element_type, element_orders[0]);
- } else {
- compiler_type = m_ast.CreateArrayType(type_name_const_str,
- array_element_type, 0);
- }
- type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str,
- byte_stride, NULL, type_die_offset,
- Type::eEncodingIsUID, &decl, compiler_type,
- Type::eResolveStateFull));
- type_sp->SetEncodingType(element_type);
- }
- }
- } break;
-
- default:
- dwarf->GetObjectFile()->GetModule()->ReportError(
- "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), "
- "please file a bug and attach the file at the "
- "start of this error message",
- die.GetOffset(), tag, DW_TAG_value_to_name(tag));
- break;
- }
-
- if (type_sp.get()) {
- DWARFDIE sc_parent_die =
- SymbolFileDWARF::GetParentSymbolContextDIE(die);
- dw_tag_t sc_parent_tag = sc_parent_die.Tag();
-
- SymbolContextScope *symbol_context_scope = NULL;
- if (sc_parent_tag == DW_TAG_compile_unit ||
- sc_parent_tag == DW_TAG_partial_unit) {
- symbol_context_scope = sc.comp_unit;
- } else if (sc.function != NULL && sc_parent_die) {
- symbol_context_scope =
- sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
- if (symbol_context_scope == NULL)
- symbol_context_scope = sc.function;
- }
-
- if (symbol_context_scope != NULL) {
- type_sp->SetSymbolContextScope(symbol_context_scope);
- }
-
- // We are ready to put this type into the uniqued list up at the module
- // level
- type_list->Insert(type_sp);
-
- dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
- }
- } else if (type_ptr != DIE_IS_BEING_PARSED) {
- type_sp = type_ptr->shared_from_this();
- }
- }
- return type_sp;
-}
-
-size_t DWARFASTParserGo::ParseChildParameters(
- const SymbolContext &sc,
-
- const DWARFDIE &parent_die, bool &is_variadic,
- std::vector<CompilerType> &function_param_types) {
- if (!parent_die)
- return 0;
-
- size_t arg_idx = 0;
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
-
- dw_tag_t tag = die.Tag();
- switch (tag) {
- case DW_TAG_formal_parameter: {
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- if (num_attributes > 0) {
- Declaration decl;
- DWARFFormValue param_type_die_offset;
-
- uint32_t i;
- for (i = 0; i < num_attributes; ++i) {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- // = form_value.AsCString();
- break;
- case DW_AT_type:
- param_type_die_offset = form_value;
- break;
- case DW_AT_location:
- // if (form_value.BlockData())
- // {
- // const DWARFDataExtractor&
- // debug_info_data =
- // debug_info();
- // uint32_t block_length =
- // form_value.Unsigned();
- // DWARFDataExtractor
- // location(debug_info_data,
- // form_value.BlockData() -
- // debug_info_data.GetDataStart(),
- // block_length);
- // }
- // else
- // {
- // }
- // break;
- default:
- break;
- }
- }
- }
-
- Type *type = parent_die.ResolveTypeUID(DIERef(param_type_die_offset));
- if (type) {
- function_param_types.push_back(type->GetForwardCompilerType());
- }
- }
- arg_idx++;
- } break;
-
- case DW_TAG_unspecified_parameters:
- is_variadic = true;
- break;
-
- default:
- break;
- }
- }
- return arg_idx;
-}
-
-void DWARFASTParserGo::ParseChildArrayInfo(
- const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
- std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
- uint32_t &bit_stride) {
- if (!parent_die)
- return;
-
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
- const dw_tag_t tag = die.Tag();
- switch (tag) {
- case DW_TAG_subrange_type: {
- DWARFAttributes attributes;
- const size_t num_child_attributes = die.GetAttributes(attributes);
- if (num_child_attributes > 0) {
- uint64_t num_elements = 0;
- uint32_t i;
- for (i = 0; i < num_child_attributes; ++i) {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_count:
- num_elements = form_value.Unsigned();
- break;
-
- default:
- case DW_AT_type:
- break;
- }
- }
- }
-
- element_orders.push_back(num_elements);
- }
- } break;
- }
- }
-}
-
-bool DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die,
- lldb_private::Type *type,
- CompilerType &compiler_type) {
- if (!die)
- return false;
-
- const dw_tag_t tag = die.Tag();
-
- SymbolFileDWARF *dwarf = die.GetDWARF();
- Log *log =
- nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
- if (log)
- dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace(
- log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
- die.GetID(), DW_TAG_value_to_name(tag), type->GetName().AsCString());
- assert(compiler_type);
- DWARFAttributes attributes;
-
- switch (tag) {
- case DW_TAG_structure_type: {
- {
- if (die.HasChildren()) {
- SymbolContext sc(die.GetLLDBCompileUnit());
-
- ParseChildMembers(sc, die, compiler_type);
- }
- }
- m_ast.CompleteStructType(compiler_type);
- return (bool)compiler_type;
- }
-
- default:
- assert(false && "not a forward go type decl!");
- break;
- }
-
- return false;
-}
-
-size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc,
- const DWARFDIE &parent_die,
- CompilerType &class_compiler_type) {
- size_t count = 0;
- uint32_t member_idx = 0;
-
- ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
- GoASTContext *ast =
- llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem());
- if (ast == nullptr)
- return 0;
-
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
- dw_tag_t tag = die.Tag();
-
- switch (tag) {
- case DW_TAG_member: {
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- if (num_attributes > 0) {
- Declaration decl;
- const char *name = NULL;
-
- DWARFFormValue encoding_uid;
- uint32_t member_byte_offset = UINT32_MAX;
- uint32_t i;
- for (i = 0; i < num_attributes; ++i) {
- const dw_attr_t attr = attributes.AttributeAtIndex(i);
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- name = form_value.AsCString();
- break;
- case DW_AT_type:
- encoding_uid = form_value;
- break;
- case DW_AT_data_member_location:
- if (form_value.BlockData()) {
- Value initialValue(0);
- Value memberOffset(0);
- const DWARFDataExtractor &debug_info_data = die.GetData();
- uint32_t block_length = form_value.Unsigned();
- uint32_t block_offset =
- form_value.BlockData() - debug_info_data.GetDataStart();
- if (DWARFExpression::Evaluate(
- NULL, // ExecutionContext *
- NULL, // RegisterContext *
- module_sp, debug_info_data, die.GetCU(), block_offset,
- block_length, eRegisterKindDWARF, &initialValue, NULL,
- memberOffset, NULL)) {
- member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
- }
- } else {
- // With DWARF 3 and later, if the value is an integer constant,
- // this form value is the offset in bytes from the beginning of
- // the containing entity.
- member_byte_offset = form_value.Unsigned();
- }
- break;
-
- default:
- break;
- }
- }
- }
-
- Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid));
- if (member_type) {
- CompilerType member_go_type = member_type->GetFullCompilerType();
- ConstString name_const_str(name);
- m_ast.AddFieldToStruct(class_compiler_type, name_const_str,
- member_go_type, member_byte_offset);
- }
- }
- ++member_idx;
- } break;
-
- default:
- break;
- }
- }
-
- return count;
-}
-
-Function *DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc,
- const DWARFDIE &die) {
- DWARFRangeList func_ranges;
- const char *name = NULL;
- const char *mangled = NULL;
- int decl_file = 0;
- int decl_line = 0;
- int decl_column = 0;
- int call_file = 0;
- int call_line = 0;
- int call_column = 0;
- DWARFExpression frame_base(die.GetCU());
-
- assert(die.Tag() == DW_TAG_subprogram);
-
- if (die.Tag() != DW_TAG_subprogram)
- return NULL;
-
- if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
- decl_column, call_file, call_line, call_column,
- &frame_base)) {
- // Union of all ranges in the function DIE (if the function is
- // discontiguous)
- AddressRange func_range;
- lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
- lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
- if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
- lowest_func_addr <= highest_func_addr) {
- ModuleSP module_sp(die.GetModule());
- func_range.GetBaseAddress().ResolveAddressUsingFileSections(
- lowest_func_addr, module_sp->GetSectionList());
- if (func_range.GetBaseAddress().IsValid())
- func_range.SetByteSize(highest_func_addr - lowest_func_addr);
- }
-
- if (func_range.GetBaseAddress().IsValid()) {
- Mangled func_name;
- func_name.SetValue(ConstString(name), false);
-
- FunctionSP func_sp;
- std::unique_ptr<Declaration> decl_ap;
- if (decl_file != 0 || decl_line != 0 || decl_column != 0)
- decl_ap.reset(new Declaration(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
- decl_line, decl_column));
-
- SymbolFileDWARF *dwarf = die.GetDWARF();
- // Supply the type _only_ if it has already been parsed
- Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
-
- assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
-
- if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
- const user_id_t func_user_id = die.GetID();
- func_sp.reset(new Function(sc.comp_unit,
- func_user_id, // UserID is the DIE offset
- func_user_id, func_name, func_type,
- func_range)); // first address range
-
- if (func_sp.get() != NULL) {
- if (frame_base.IsValid())
- func_sp->GetFrameBaseExpression() = frame_base;
- sc.comp_unit->AddFunction(func_sp);
- return func_sp.get();
- }
- }
- }
- }
- return NULL;
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
deleted file mode 100644
index 2a7c3871a309..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.h
+++ /dev/null
@@ -1,84 +0,0 @@
-//===-- DWARFASTParserGo.h --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFASTParserGo_h_
-#define SymbolFileDWARF_DWARFASTParserGo_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-
-// Project includes
-#include "DWARFASTParser.h"
-#include "DWARFDIE.h"
-#include "DWARFDefines.h"
-#include "lldb/Core/PluginInterface.h"
-#include "lldb/Symbol/GoASTContext.h"
-
-class DWARFDebugInfoEntry;
-class DWARFDIECollection;
-
-class DWARFASTParserGo : public DWARFASTParser {
-public:
- DWARFASTParserGo(lldb_private::GoASTContext &ast);
-
- ~DWARFASTParserGo() override;
-
- lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die, lldb_private::Log *log,
- bool *type_is_new_ptr) override;
-
- lldb_private::Function *
- ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die) override;
-
- bool CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
- lldb_private::CompilerType &go_type) override;
-
- lldb_private::CompilerDeclContext
- GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDeclContext();
- }
-
- lldb_private::CompilerDeclContext
- GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDeclContext();
- }
-
- lldb_private::CompilerDecl
- GetDeclForUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDecl();
- }
-
- std::vector<DWARFDIE> GetDIEForDeclContext(
- lldb_private::CompilerDeclContext decl_context) override {
- return std::vector<DWARFDIE>();
- }
-
-private:
- size_t ParseChildParameters(
- const lldb_private::SymbolContext &sc, const DWARFDIE &parent_die,
- bool &is_variadic,
- std::vector<lldb_private::CompilerType> &function_param_types);
- void ParseChildArrayInfo(const lldb_private::SymbolContext &sc,
- const DWARFDIE &parent_die, int64_t &first_index,
- std::vector<uint64_t> &element_orders,
- uint32_t &byte_stride, uint32_t &bit_stride);
-
- size_t ParseChildMembers(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die,
- lldb_private::CompilerType &class_compiler_type);
-
- lldb_private::GoASTContext &m_ast;
-};
-
-#endif // SymbolFileDWARF_DWARFASTParserGo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
deleted file mode 100644
index 476394487985..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
+++ /dev/null
@@ -1,510 +0,0 @@
-//===-- DWARFASTParserJava.cpp ----------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DWARFASTParserJava.h"
-#include "DWARFAttribute.h"
-#include "DWARFUnit.h"
-#include "DWARFDebugInfoEntry.h"
-#include "DWARFDebugInfoEntry.h"
-#include "DWARFDeclContext.h"
-#include "SymbolFileDWARF.h"
-
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/SymbolContextScope.h"
-#include "lldb/Symbol/TypeList.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-DWARFASTParserJava::DWARFASTParserJava(JavaASTContext &ast) : m_ast(ast) {}
-
-DWARFASTParserJava::~DWARFASTParserJava() {}
-
-TypeSP DWARFASTParserJava::ParseBaseTypeFromDIE(const DWARFDIE &die) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- ConstString type_name;
- uint64_t byte_size = 0;
-
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- for (uint32_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- type_name.SetCString(form_value.AsCString());
- break;
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- break;
- case DW_AT_encoding:
- break;
- default:
- assert(false && "Unsupported attribute for DW_TAG_base_type");
- }
- }
- }
-
- Declaration decl;
- CompilerType compiler_type = m_ast.CreateBaseType(type_name);
- return std::make_shared<Type>(die.GetID(), dwarf, type_name, byte_size,
- nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
- decl, compiler_type, Type::eResolveStateFull);
-}
-
-TypeSP DWARFASTParserJava::ParseArrayTypeFromDIE(const DWARFDIE &die) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- ConstString linkage_name;
- DWARFFormValue type_attr_value;
- lldb::addr_t data_offset = LLDB_INVALID_ADDRESS;
- DWARFExpression length_expression(die.GetCU());
-
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- for (uint32_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_linkage_name:
- linkage_name.SetCString(form_value.AsCString());
- break;
- case DW_AT_type:
- type_attr_value = form_value;
- break;
- case DW_AT_data_member_location:
- data_offset = form_value.Unsigned();
- break;
- case DW_AT_declaration:
- break;
- default:
- assert(false && "Unsupported attribute for DW_TAG_array_type");
- }
- }
- }
-
- for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid();
- child_die = child_die.GetSibling()) {
- if (child_die.Tag() == DW_TAG_subrange_type) {
- DWARFAttributes attributes;
- const size_t num_attributes = child_die.GetAttributes(attributes);
- for (uint32_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_count:
- if (form_value.BlockData())
- length_expression.CopyOpcodeData(
- form_value.BlockData(), form_value.Unsigned(),
- child_die.GetCU()->GetByteOrder(),
- child_die.GetCU()->GetAddressByteSize());
- break;
- default:
- assert(false && "Unsupported attribute for DW_TAG_subrange_type");
- }
- }
- }
- } else {
- assert(false && "Unsupported child for DW_TAG_array_type");
- }
- }
-
- DIERef type_die_ref(type_attr_value);
- Type *element_type = dwarf->ResolveTypeUID(type_die_ref);
- if (!element_type)
- return nullptr;
-
- CompilerType element_compiler_type = element_type->GetForwardCompilerType();
- CompilerType array_compiler_type = m_ast.CreateArrayType(
- linkage_name, element_compiler_type, length_expression, data_offset);
-
- Declaration decl;
- TypeSP type_sp(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(),
- -1, nullptr, type_die_ref.GetUID(dwarf),
- Type::eEncodingIsUID, &decl, array_compiler_type,
- Type::eResolveStateFull));
- type_sp->SetEncodingType(element_type);
- return type_sp;
-}
-
-TypeSP DWARFASTParserJava::ParseReferenceTypeFromDIE(const DWARFDIE &die) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- Declaration decl;
- DWARFFormValue type_attr_value;
-
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- for (uint32_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_type:
- type_attr_value = form_value;
- break;
- default:
- assert(false && "Unsupported attribute for DW_TAG_array_type");
- }
- }
- }
-
- DIERef type_die_ref(type_attr_value);
- Type *pointee_type = dwarf->ResolveTypeUID(type_die_ref);
- if (!pointee_type)
- return nullptr;
-
- CompilerType pointee_compiler_type = pointee_type->GetForwardCompilerType();
- CompilerType reference_compiler_type =
- m_ast.CreateReferenceType(pointee_compiler_type);
- TypeSP type_sp(
- new Type(die.GetID(), dwarf, reference_compiler_type.GetTypeName(), -1,
- nullptr, type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl,
- reference_compiler_type, Type::eResolveStateFull));
- type_sp->SetEncodingType(pointee_type);
- return type_sp;
-}
-
-lldb::TypeSP DWARFASTParserJava::ParseClassTypeFromDIE(const DWARFDIE &die,
- bool &is_new_type) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- Declaration decl;
- ConstString name;
- ConstString linkage_name;
- bool is_forward_declaration = false;
- uint32_t byte_size = 0;
-
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- for (uint32_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- name.SetCString(form_value.AsCString());
- break;
- case DW_AT_declaration:
- is_forward_declaration = form_value.Boolean();
- break;
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- break;
- case DW_AT_linkage_name:
- linkage_name.SetCString(form_value.AsCString());
- break;
- default:
- assert(false && "Unsupported attribute for DW_TAG_class_type");
- }
- }
- }
-
- UniqueDWARFASTType unique_ast_entry;
- if (name) {
- std::string qualified_name;
- if (die.GetQualifiedName(qualified_name)) {
- name.SetCString(qualified_name.c_str());
- if (dwarf->GetUniqueDWARFASTTypeMap().Find(name, die, Declaration(), -1,
- unique_ast_entry)) {
- if (unique_ast_entry.m_type_sp) {
- dwarf->GetDIEToType()[die.GetDIE()] =
- unique_ast_entry.m_type_sp.get();
- is_new_type = false;
- return unique_ast_entry.m_type_sp;
- }
- }
- }
- }
-
- if (is_forward_declaration) {
- DWARFDeclContext die_decl_ctx;
- die.GetDWARFDeclContext(die_decl_ctx);
-
- TypeSP type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx);
- if (type_sp) {
- // We found a real definition for this type elsewhere so lets use it
- dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get();
- is_new_type = false;
- return type_sp;
- }
- }
-
- CompilerType compiler_type(
- &m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE()));
- if (!compiler_type)
- compiler_type = m_ast.CreateObjectType(name, linkage_name, byte_size);
-
- is_new_type = true;
- TypeSP type_sp(new Type(die.GetID(), dwarf, name,
- -1, // byte size isn't specified
- nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
- &decl, compiler_type, Type::eResolveStateForward));
-
- // Add our type to the unique type map
- unique_ast_entry.m_type_sp = type_sp;
- unique_ast_entry.m_die = die;
- unique_ast_entry.m_declaration = decl;
- unique_ast_entry.m_byte_size = -1;
- dwarf->GetUniqueDWARFASTTypeMap().Insert(name, unique_ast_entry);
-
- if (!is_forward_declaration) {
- // Leave this as a forward declaration until we need to know the details of
- // the type
- dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] =
- compiler_type.GetOpaqueQualType();
- dwarf->GetForwardDeclClangTypeToDie()[compiler_type.GetOpaqueQualType()] =
- die.GetDIERef();
- }
- return type_sp;
-}
-
-lldb::TypeSP DWARFASTParserJava::ParseTypeFromDWARF(
- const lldb_private::SymbolContext &sc, const DWARFDIE &die,
- lldb_private::Log *log, bool *type_is_new_ptr) {
- if (type_is_new_ptr)
- *type_is_new_ptr = false;
-
- if (!die)
- return nullptr;
-
- SymbolFileDWARF *dwarf = die.GetDWARF();
-
- Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
- if (type_ptr == DIE_IS_BEING_PARSED)
- return nullptr;
- if (type_ptr != nullptr)
- return type_ptr->shared_from_this();
-
- TypeSP type_sp;
- if (type_is_new_ptr)
- *type_is_new_ptr = true;
-
- switch (die.Tag()) {
- case DW_TAG_base_type: {
- type_sp = ParseBaseTypeFromDIE(die);
- break;
- }
- case DW_TAG_array_type: {
- type_sp = ParseArrayTypeFromDIE(die);
- break;
- }
- case DW_TAG_class_type: {
- bool is_new_type = false;
- type_sp = ParseClassTypeFromDIE(die, is_new_type);
- if (!is_new_type)
- return type_sp;
- break;
- }
- case DW_TAG_reference_type: {
- type_sp = ParseReferenceTypeFromDIE(die);
- break;
- }
- }
-
- if (!type_sp)
- return nullptr;
-
- DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
- dw_tag_t sc_parent_tag = sc_parent_die.Tag();
-
- SymbolContextScope *symbol_context_scope = nullptr;
- if (sc_parent_tag == DW_TAG_compile_unit ||
- sc_parent_tag == DW_TAG_partial_unit) {
- symbol_context_scope = sc.comp_unit;
- } else if (sc.function != nullptr && sc_parent_die) {
- symbol_context_scope =
- sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
- if (symbol_context_scope == nullptr)
- symbol_context_scope = sc.function;
- }
-
- if (symbol_context_scope != nullptr)
- type_sp->SetSymbolContextScope(symbol_context_scope);
-
- dwarf->GetTypeList()->Insert(type_sp);
- dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
-
- return type_sp;
-}
-
-lldb_private::Function *DWARFASTParserJava::ParseFunctionFromDWARF(
- const lldb_private::SymbolContext &sc, const DWARFDIE &die) {
- assert(die.Tag() == DW_TAG_subprogram);
-
- const char *name = nullptr;
- const char *mangled = nullptr;
- int decl_file = 0;
- int decl_line = 0;
- int decl_column = 0;
- int call_file = 0;
- int call_line = 0;
- int call_column = 0;
- DWARFRangeList func_ranges;
- DWARFExpression frame_base(die.GetCU());
-
- if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
- decl_column, call_file, call_line, call_column,
- &frame_base)) {
- // Union of all ranges in the function DIE (if the function is
- // discontiguous)
- AddressRange func_range;
- lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
- lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
- if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
- lowest_func_addr <= highest_func_addr) {
- ModuleSP module_sp(die.GetModule());
- func_range.GetBaseAddress().ResolveAddressUsingFileSections(
- lowest_func_addr, module_sp->GetSectionList());
- if (func_range.GetBaseAddress().IsValid())
- func_range.SetByteSize(highest_func_addr - lowest_func_addr);
- }
-
- if (func_range.GetBaseAddress().IsValid()) {
- std::unique_ptr<Declaration> decl_ap;
- if (decl_file != 0 || decl_line != 0 || decl_column != 0)
- decl_ap.reset(new Declaration(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
- decl_line, decl_column));
-
- if (die.GetDWARF()->FixupAddress(func_range.GetBaseAddress())) {
- FunctionSP func_sp(new Function(sc.comp_unit, die.GetID(), die.GetID(),
- Mangled(ConstString(name), false),
- nullptr, // No function types in java
- func_range));
- if (frame_base.IsValid())
- func_sp->GetFrameBaseExpression() = frame_base;
- sc.comp_unit->AddFunction(func_sp);
-
- return func_sp.get();
- }
- }
- }
- return nullptr;
-}
-
-bool DWARFASTParserJava::CompleteTypeFromDWARF(
- const DWARFDIE &die, lldb_private::Type *type,
- lldb_private::CompilerType &java_type) {
- switch (die.Tag()) {
- case DW_TAG_class_type: {
- if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 0) {
- if (die.HasChildren())
- ParseChildMembers(die, java_type);
- m_ast.CompleteObjectType(java_type);
- return java_type.IsValid();
- }
- } break;
- default:
- assert(false && "Not a forward java type declaration!");
- break;
- }
- return false;
-}
-
-void DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die,
- CompilerType &compiler_type) {
- DWARFUnit *dwarf_cu = parent_die.GetCU();
- for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid();
- die = die.GetSibling()) {
- switch (die.Tag()) {
- case DW_TAG_member: {
- const char *name = nullptr;
- DWARFFormValue encoding_uid;
- uint32_t member_byte_offset = UINT32_MAX;
- DWARFExpression member_location_expression(dwarf_cu);
-
- DWARFAttributes attributes;
- size_t num_attributes = die.GetAttributes(attributes);
- for (size_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attributes.AttributeAtIndex(i)) {
- case DW_AT_name:
- name = form_value.AsCString();
- break;
- case DW_AT_type:
- encoding_uid = form_value;
- break;
- case DW_AT_data_member_location:
- if (form_value.BlockData())
- member_location_expression.CopyOpcodeData(
- form_value.BlockData(), form_value.Unsigned(),
- dwarf_cu->GetByteOrder(), dwarf_cu->GetAddressByteSize());
- else
- member_byte_offset = form_value.Unsigned();
- break;
- case DW_AT_artificial:
- static_cast<void>(form_value.Boolean());
- break;
- case DW_AT_accessibility:
- // TODO: Handle when needed
- break;
- default:
- assert(false && "Unhandled attribute for DW_TAG_member");
- break;
- }
- }
- }
-
- if (strcmp(name, ".dynamic_type") == 0)
- m_ast.SetDynamicTypeId(compiler_type, member_location_expression);
- else {
- if (Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid)))
- m_ast.AddMemberToObject(compiler_type, ConstString(name),
- member_type->GetFullCompilerType(),
- member_byte_offset);
- }
- break;
- }
- case DW_TAG_inheritance: {
- DWARFFormValue encoding_uid;
- uint32_t member_byte_offset = UINT32_MAX;
-
- DWARFAttributes attributes;
- size_t num_attributes = die.GetAttributes(attributes);
- for (size_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attributes.AttributeAtIndex(i)) {
- case DW_AT_type:
- encoding_uid = form_value;
- break;
- case DW_AT_data_member_location:
- member_byte_offset = form_value.Unsigned();
- break;
- case DW_AT_accessibility:
- // In java all base class is public so we can ignore this attribute
- break;
- default:
- assert(false && "Unhandled attribute for DW_TAG_member");
- break;
- }
- }
- }
- if (Type *base_type = die.ResolveTypeUID(DIERef(encoding_uid)))
- m_ast.AddBaseClassToObject(compiler_type,
- base_type->GetFullCompilerType(),
- member_byte_offset);
- break;
- }
- default:
- break;
- }
- }
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h
deleted file mode 100644
index 01d81833d517..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.h
+++ /dev/null
@@ -1,81 +0,0 @@
-//===-- DWARFASTParserJava.h ------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SymbolFileDWARF_DWARFASTParserJava_h_
-#define SymbolFileDWARF_DWARFASTParserJava_h_
-
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-
-// Project includes
-#include "DWARFASTParser.h"
-#include "DWARFDIE.h"
-#include "DWARFDefines.h"
-#include "lldb/Core/PluginInterface.h"
-#include "lldb/Symbol/JavaASTContext.h"
-
-class DWARFDebugInfoEntry;
-class DWARFDIECollection;
-
-class DWARFASTParserJava : public DWARFASTParser {
-public:
- DWARFASTParserJava(lldb_private::JavaASTContext &ast);
- ~DWARFASTParserJava() override;
-
- lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die, lldb_private::Log *log,
- bool *type_is_new_ptr) override;
-
- lldb_private::Function *
- ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die) override;
-
- bool CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
- lldb_private::CompilerType &java_type) override;
-
- lldb_private::CompilerDeclContext
- GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDeclContext();
- }
-
- lldb_private::CompilerDeclContext
- GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDeclContext();
- }
-
- lldb_private::CompilerDecl
- GetDeclForUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDecl();
- }
-
- std::vector<DWARFDIE> GetDIEForDeclContext(
- lldb_private::CompilerDeclContext decl_context) override {
- return std::vector<DWARFDIE>();
- }
-
- void ParseChildMembers(const DWARFDIE &parent_die,
- lldb_private::CompilerType &class_compiler_type);
-
-private:
- lldb_private::JavaASTContext &m_ast;
-
- lldb::TypeSP ParseBaseTypeFromDIE(const DWARFDIE &die);
-
- lldb::TypeSP ParseArrayTypeFromDIE(const DWARFDIE &die);
-
- lldb::TypeSP ParseReferenceTypeFromDIE(const DWARFDIE &die);
-
- lldb::TypeSP ParseClassTypeFromDIE(const DWARFDIE &die, bool &is_new_type);
-};
-
-#endif // SymbolFileDWARF_DWARFASTParserJava_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
deleted file mode 100644
index 3ef5c2eb8626..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-//===-- DWARFASTParserOCaml.cpp ---------------------------------*- C++ -*-===//
-
-#include "DWARFASTParserOCaml.h"
-
-#include "lldb/Core/Module.h"
-#include "lldb/Symbol/CompileUnit.h"
-#include "lldb/Symbol/Function.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Symbol/TypeList.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Status.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-DWARFASTParserOCaml::DWARFASTParserOCaml(OCamlASTContext &ast) : m_ast(ast) {}
-
-DWARFASTParserOCaml::~DWARFASTParserOCaml() {}
-
-TypeSP DWARFASTParserOCaml::ParseBaseTypeFromDIE(const DWARFDIE &die) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;
-
- ConstString type_name;
- uint64_t byte_size = 0;
-
- DWARFAttributes attributes;
- const size_t num_attributes = die.GetAttributes(attributes);
- for (uint32_t i = 0; i < num_attributes; ++i) {
- DWARFFormValue form_value;
- dw_attr_t attr = attributes.AttributeAtIndex(i);
- if (attributes.ExtractFormValueAtIndex(i, form_value)) {
- switch (attr) {
- case DW_AT_name:
- type_name.SetCString(form_value.AsCString());
- break;
- case DW_AT_byte_size:
- byte_size = form_value.Unsigned();
- break;
- case DW_AT_encoding:
- break;
- default:
- assert(false && "Unsupported attribute for DW_TAG_base_type");
- }
- }
- }
-
- Declaration decl;
- CompilerType compiler_type = m_ast.CreateBaseType(type_name, byte_size);
- return std::make_shared<Type>(die.GetID(), dwarf, type_name, byte_size,
- nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
- decl, compiler_type, Type::eResolveStateFull);
-}
-
-lldb::TypeSP DWARFASTParserOCaml::ParseTypeFromDWARF(const SymbolContext &sc,
- const DWARFDIE &die,
- Log *log,
- bool *type_is_new_ptr) {
- if (type_is_new_ptr)
- *type_is_new_ptr = false;
-
- if (!die)
- return nullptr;
-
- SymbolFileDWARF *dwarf = die.GetDWARF();
-
- Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE());
- if (type_ptr == DIE_IS_BEING_PARSED)
- return nullptr;
- if (type_ptr != nullptr)
- return type_ptr->shared_from_this();
-
- TypeSP type_sp;
- if (type_is_new_ptr)
- *type_is_new_ptr = true;
-
- switch (die.Tag()) {
- case DW_TAG_base_type: {
- type_sp = ParseBaseTypeFromDIE(die);
- break;
- }
- case DW_TAG_array_type: {
- break;
- }
- case DW_TAG_class_type: {
- break;
- }
- case DW_TAG_reference_type: {
- break;
- }
- }
-
- if (!type_sp)
- return nullptr;
-
- DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die);
- dw_tag_t sc_parent_tag = sc_parent_die.Tag();
-
- SymbolContextScope *symbol_context_scope = nullptr;
- if (sc_parent_tag == DW_TAG_compile_unit ||
- sc_parent_tag == DW_TAG_partial_unit) {
- symbol_context_scope = sc.comp_unit;
- } else if (sc.function != nullptr && sc_parent_die) {
- symbol_context_scope =
- sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID());
- if (symbol_context_scope == nullptr)
- symbol_context_scope = sc.function;
- }
-
- if (symbol_context_scope != nullptr)
- type_sp->SetSymbolContextScope(symbol_context_scope);
-
- dwarf->GetTypeList()->Insert(type_sp);
- dwarf->m_die_to_type[die.GetDIE()] = type_sp.get();
-
- return type_sp;
-}
-
-Function *DWARFASTParserOCaml::ParseFunctionFromDWARF(const SymbolContext &sc,
- const DWARFDIE &die) {
- DWARFRangeList func_ranges;
- const char *name = NULL;
- const char *mangled = NULL;
- int decl_file = 0;
- int decl_line = 0;
- int decl_column = 0;
- int call_file = 0;
- int call_line = 0;
- int call_column = 0;
- DWARFExpression frame_base(die.GetCU());
-
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (die) {
- SymbolFileDWARF *dwarf = die.GetDWARF();
- if (log) {
- dwarf->GetObjectFile()->GetModule()->LogMessage(
- log, "DWARFASTParserOCaml::ParseFunctionFromDWARF (die = 0x%8.8x) %s "
- "name = '%s')",
- die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.GetName());
- }
- }
-
- assert(die.Tag() == DW_TAG_subprogram);
-
- if (die.Tag() != DW_TAG_subprogram)
- return NULL;
-
- if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
- decl_column, call_file, call_line, call_column,
- &frame_base)) {
- AddressRange func_range;
- lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
- lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
- if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
- lowest_func_addr <= highest_func_addr) {
- ModuleSP module_sp(die.GetModule());
- func_range.GetBaseAddress().ResolveAddressUsingFileSections(
- lowest_func_addr, module_sp->GetSectionList());
- if (func_range.GetBaseAddress().IsValid())
- func_range.SetByteSize(highest_func_addr - lowest_func_addr);
- }
-
- if (func_range.GetBaseAddress().IsValid()) {
- Mangled func_name;
-
- func_name.SetValue(ConstString(name), true);
-
- FunctionSP func_sp;
- std::unique_ptr<Declaration> decl_ap;
- if (decl_file != 0 || decl_line != 0 || decl_column != 0)
- decl_ap.reset(new Declaration(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
- decl_line, decl_column));
-
- SymbolFileDWARF *dwarf = die.GetDWARF();
- Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE());
-
- assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
-
- if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
- const user_id_t func_user_id = die.GetID();
- func_sp.reset(new Function(sc.comp_unit,
- func_user_id, // UserID is the DIE offset
- func_user_id, func_name, func_type,
- func_range)); // first address range
-
- if (func_sp.get() != NULL) {
- if (frame_base.IsValid())
- func_sp->GetFrameBaseExpression() = frame_base;
- sc.comp_unit->AddFunction(func_sp);
- return func_sp.get();
- }
- }
- }
- }
-
- return NULL;
-}
-
-lldb_private::CompilerDeclContext
-DWARFASTParserOCaml::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
- return CompilerDeclContext();
-}
-
-lldb_private::CompilerDeclContext
-DWARFASTParserOCaml::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
- return CompilerDeclContext();
-}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h b/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
deleted file mode 100644
index 09cb5e14934f..000000000000
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===-- DWARFASTParserOCaml.h -----------------------------------*- C++ -*-===//
-
-#ifndef SymbolFileDWARF_DWARFASTParserOCaml_h_
-#define SymbolFileDWARF_DWARFASTParserOCaml_h_
-
-#include "DWARFASTParser.h"
-#include "DWARFDIE.h"
-#include "DWARFDebugInfo.h"
-#include "DWARFDefines.h"
-#include "SymbolFileDWARF.h"
-
-#include "lldb/Symbol/OCamlASTContext.h"
-
-class DWARFDebugInfoEntry;
-class DWARFDIECollection;
-
-class DWARFASTParserOCaml : public DWARFASTParser {
-public:
- DWARFASTParserOCaml(lldb_private::OCamlASTContext &ast);
-
- virtual ~DWARFASTParserOCaml();
-
- lldb::TypeSP ParseBaseTypeFromDIE(const DWARFDIE &die);
-
- lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die, lldb_private::Log *log,
- bool *type_is_new_ptr) override;
-
- lldb_private::Function *
- ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die) override;
-
- bool
- CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
- lldb_private::CompilerType &compiler_type) override {
- return false;
- }
-
- lldb_private::CompilerDecl
- GetDeclForUIDFromDWARF(const DWARFDIE &die) override {
- return lldb_private::CompilerDecl();
- }
-
- lldb_private::CompilerDeclContext
- GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override;
-
- lldb_private::CompilerDeclContext
- GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override;
-
- std::vector<DWARFDIE> GetDIEForDeclContext(
- lldb_private::CompilerDeclContext decl_context) override {
- return {};
- }
-
-protected:
- lldb_private::OCamlASTContext &m_ast;
-};
-
-#endif // SymbolFileDWARF_DWARFASTParserOCaml_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
index a765be0b46d0..d78b9ab10f5a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -41,9 +41,13 @@ bool DWARFAbbreviationDeclaration::Extract(const DWARFDataExtractor &data,
while (data.ValidOffset(*offset_ptr)) {
dw_attr_t attr = data.GetULEB128(offset_ptr);
dw_form_t form = data.GetULEB128(offset_ptr);
+ DWARFFormValue::ValueType val;
+
+ if (form == DW_FORM_implicit_const)
+ val.value.sval = data.GetULEB128(offset_ptr);
if (attr && form)
- m_attributes.push_back(DWARFAttribute(attr, form));
+ m_attributes.push_back(DWARFAttribute(attr, form, val));
else
break;
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
index b2296c455d6a..afce52558f45 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -35,20 +35,11 @@ public:
dw_form_t GetFormByIndex(uint32_t idx) const {
return m_attributes.size() > idx ? m_attributes[idx].get_form() : 0;
}
- bool GetAttrAndFormByIndex(uint32_t idx, dw_attr_t &attr,
- dw_form_t &form) const {
- if (m_attributes.size() > idx) {
- m_attributes[idx].get(attr, form);
- return true;
- }
- attr = form = 0;
- return false;
- }
- // idx is assumed to be valid when calling GetAttrAndFormByIndexUnchecked()
- void GetAttrAndFormByIndexUnchecked(uint32_t idx, dw_attr_t &attr,
- dw_form_t &form) const {
- m_attributes[idx].get(attr, form);
+ // idx is assumed to be valid when calling GetAttrAndFormByIndex()
+ void GetAttrAndFormValueByIndex(uint32_t idx, dw_attr_t &attr,
+ DWARFFormValue &form_value) const {
+ m_attributes[idx].get(attr, form_value.FormRef(), form_value.ValueRef());
}
dw_form_t GetFormByIndexUnchecked(uint32_t idx) const {
return m_attributes[idx].get_form();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
index 2586d1f18530..dd830eb7b9dd 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.cpp
@@ -26,10 +26,10 @@ uint32_t DWARFAttributes::FindAttributeIndex(dw_attr_t attr) const {
return UINT32_MAX;
}
-void DWARFAttributes::Append(const DWARFUnit *cu,
- dw_offset_t attr_die_offset, dw_attr_t attr,
- dw_form_t form) {
- AttributeValue attr_value = {cu, attr_die_offset, {attr, form}};
+void DWARFAttributes::Append(const DWARFUnit *cu, dw_offset_t attr_die_offset,
+ dw_attr_t attr, dw_form_t form) {
+ AttributeValue attr_value = {
+ cu, attr_die_offset, {attr, form, DWARFFormValue::ValueType()}};
m_infos.push_back(attr_value);
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
index db4324cf7725..2399861d7fc3 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -11,15 +11,17 @@
#define SymbolFileDWARF_DWARFAttribute_h_
#include "DWARFDefines.h"
+#include "DWARFFormValue.h"
#include "llvm/ADT/SmallVector.h"
#include <vector>
class DWARFUnit;
-class DWARFFormValue;
class DWARFAttribute {
public:
- DWARFAttribute(dw_attr_t attr, dw_form_t form) : m_attr(attr), m_form(form) {}
+ DWARFAttribute(dw_attr_t attr, dw_form_t form,
+ DWARFFormValue::ValueType value)
+ : m_attr(attr), m_form(form), m_value(value) {}
void set(dw_attr_t attr, dw_form_t form) {
m_attr = attr;
@@ -29,9 +31,11 @@ public:
void set_form(dw_form_t form) { m_form = form; }
dw_attr_t get_attr() const { return m_attr; }
dw_form_t get_form() const { return m_form; }
- void get(dw_attr_t &attr, dw_form_t &form) const {
+ void get(dw_attr_t &attr, dw_form_t &form,
+ DWARFFormValue::ValueType &val) const {
attr = m_attr;
form = m_form;
+ val = m_value;
}
bool operator==(const DWARFAttribute &rhs) const {
return m_attr == rhs.m_attr && m_form == rhs.m_form;
@@ -43,6 +47,7 @@ public:
protected:
dw_attr_t m_attr;
dw_form_t m_form;
+ DWARFFormValue::ValueType m_value;
};
class DWARFAttributes {
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
index 8541f1cfe1f6..b9a7231286e3 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -34,8 +34,18 @@ DWARFUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
cu_sp->m_length = debug_info.GetDWARFInitialLength(offset_ptr);
cu_sp->m_is_dwarf64 = debug_info.IsDWARF64();
cu_sp->m_version = debug_info.GetU16(offset_ptr);
- abbr_offset = debug_info.GetDWARFOffset(offset_ptr);
- cu_sp->m_addr_size = debug_info.GetU8(offset_ptr);
+
+ if (cu_sp->m_version == 5) {
+ cu_sp->m_unit_type = debug_info.GetU8(offset_ptr);
+ cu_sp->m_addr_size = debug_info.GetU8(offset_ptr);
+ abbr_offset = debug_info.GetDWARFOffset(offset_ptr);
+
+ if (cu_sp->m_unit_type == llvm::dwarf::DW_UT_skeleton)
+ cu_sp->m_dwo_id = debug_info.GetU64(offset_ptr);
+ } else {
+ abbr_offset = debug_info.GetDWARFOffset(offset_ptr);
+ cu_sp->m_addr_size = debug_info.GetU8(offset_ptr);
+ }
bool length_OK =
debug_info.ValidOffset(cu_sp->GetNextCompileUnitOffset() - 1);
@@ -65,6 +75,23 @@ void DWARFCompileUnit::Dump(Stream *s) const {
GetNextCompileUnitOffset());
}
+uint32_t DWARFCompileUnit::GetHeaderByteSize() const {
+ if (m_version < 5)
+ return m_is_dwarf64 ? 23 : 11;
+
+ switch (m_unit_type) {
+ case llvm::dwarf::DW_UT_compile:
+ case llvm::dwarf::DW_UT_partial:
+ return 12;
+ case llvm::dwarf::DW_UT_skeleton:
+ case llvm::dwarf::DW_UT_split_compile:
+ return 20;
+ case llvm::dwarf::DW_UT_type:
+ case llvm::dwarf::DW_UT_split_type:
+ return 24;
+ }
+ llvm_unreachable("invalid UnitType.");
+}
const lldb_private::DWARFDataExtractor &DWARFCompileUnit::GetData() const {
return m_dwarf->get_debug_info_data();
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
index d20f31505ed4..b92a155e0335 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -35,9 +35,7 @@ public:
/// @return
/// Byte size of the compile unit header
//------------------------------------------------------------------
- uint32_t GetHeaderByteSize() const override {
- return m_is_dwarf64 ? 23 : 11;
- }
+ uint32_t GetHeaderByteSize() const override;
private:
DWARFCompileUnit(SymbolFileDWARF *dwarf2Data);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
index d9754e911017..22b70b2d6852 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -166,13 +166,13 @@ void DWARFDIE::GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const {
}
}
-void DWARFDIE::GetDWOContext(std::vector<CompilerContext> &context) const {
+void DWARFDIE::GetDeclContext(std::vector<CompilerContext> &context) const {
const dw_tag_t tag = Tag();
if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit)
return;
DWARFDIE parent = GetParent();
if (parent)
- parent.GetDWOContext(context);
+ parent.GetDeclContext(context);
switch (tag) {
case DW_TAG_module:
context.push_back(
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
index ecbf4912634e..b0d06a886ac1 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -90,7 +90,10 @@ public:
void GetDWARFDeclContext(DWARFDeclContext &dwarf_decl_ctx) const;
- void GetDWOContext(std::vector<lldb_private::CompilerContext> &context) const;
+ /// Return this DIE's decl context as it is needed to look up types
+ /// in Clang's -gmodules debug info format.
+ void
+ GetDeclContext(std::vector<lldb_private::CompilerContext> &context) const;
//----------------------------------------------------------------------
// Getting attribute values from the DIE.
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
index ce0bfb3931d5..1f342035f135 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDataExtractor.h
@@ -10,7 +10,6 @@
#ifndef liblldb_DWARFDataExtractor_h_
#define liblldb_DWARFDataExtractor_h_
-// Other libraries and framework includes.
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/DataExtractor.h"
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
index 6524cb3ce483..e7a8635f0532 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -19,7 +19,7 @@ class SymbolFileDWARF;
class DWARFDebugAranges {
protected:
- typedef lldb_private::RangeDataArray<dw_addr_t, uint32_t, dw_offset_t, 1>
+ typedef lldb_private::RangeDataVector<dw_addr_t, uint32_t, dw_offset_t>
RangeToDIE;
public:
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
index d32aef6e162c..7531aeac709a 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -40,9 +40,8 @@ bool DWARFDebugInfoEntry::FastExtract(
m_offset = *offset_ptr;
m_parent_idx = 0;
m_sibling_idx = 0;
- m_empty_children = false;
const uint64_t abbr_idx = debug_info_data.GetULEB128(offset_ptr);
- assert(abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE));
+ lldbassert(abbr_idx <= UINT16_MAX);
m_abbr_idx = abbr_idx;
// assert (fixed_form_sizes); // For best performance this should be
@@ -119,21 +118,33 @@ bool DWARFDebugInfoEntry::FastExtract(
break;
// 1 byte values
+ case DW_FORM_addrx1:
case DW_FORM_data1:
case DW_FORM_flag:
case DW_FORM_ref1:
+ case DW_FORM_strx1:
form_size = 1;
break;
// 2 byte values
+ case DW_FORM_addrx2:
case DW_FORM_data2:
case DW_FORM_ref2:
+ case DW_FORM_strx2:
form_size = 2;
break;
+ // 3 byte values
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ form_size = 3;
+ break;
+
// 4 byte values
+ case DW_FORM_addrx4:
case DW_FORM_data4:
case DW_FORM_ref4:
+ case DW_FORM_strx4:
form_size = 4;
break;
@@ -145,11 +156,14 @@ bool DWARFDebugInfoEntry::FastExtract(
break;
// signed or unsigned LEB 128 values
+ case DW_FORM_addrx:
+ case DW_FORM_rnglistx:
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
case DW_FORM_GNU_addr_index:
case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
debug_info_data.Skip_LEB128(&offset);
break;
@@ -166,6 +180,10 @@ bool DWARFDebugInfoEntry::FastExtract(
debug_info_data.GetU32(&offset);
break;
+ case DW_FORM_implicit_const:
+ form_size = 0;
+ break;
+
default:
*offset_ptr = m_offset;
return false;
@@ -208,7 +226,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
m_offset = offset;
const uint64_t abbr_idx = debug_info_data.GetULEB128(&offset);
- assert(abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE));
+ lldbassert(abbr_idx <= UINT16_MAX);
m_abbr_idx = abbr_idx;
if (abbr_idx) {
const DWARFAbbreviationDeclaration *abbrevDecl =
@@ -225,15 +243,14 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
// Skip all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
- uint32_t i;
- dw_attr_t attr;
- dw_form_t form;
- for (i = 0; i < numAttributes; ++i) {
- abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+ for (uint32_t i = 0; i < numAttributes; ++i) {
+ DWARFFormValue form_value(cu);
+ dw_attr_t attr;
+ abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
+ dw_form_t form = form_value.Form();
if (isCompileUnitTag &&
((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc))) {
- DWARFFormValue form_value(cu, form);
if (form_value.ExtractValue(debug_info_data, &offset)) {
if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
const_cast<DWARFUnit *>(cu)->SetBaseAddress(
@@ -279,6 +296,7 @@ bool DWARFDebugInfoEntry::Extract(SymbolFileDWARF *dwarf2Data,
// 0 sized form
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
form_size = 0;
break;
@@ -370,6 +388,13 @@ void DWARFDebugInfoEntry::DumpAncestry(SymbolFileDWARF *dwarf2Data,
Dump(dwarf2Data, cu, s, recurse_depth);
}
+static dw_offset_t GetRangesOffset(const DWARFDebugRangesBase *debug_ranges,
+ DWARFFormValue &form_value) {
+ if (form_value.Form() == DW_FORM_rnglistx)
+ return debug_ranges->GetOffset(form_value.Unsigned());
+ return form_value.Unsigned();
+}
+
//----------------------------------------------------------------------
// GetDIENamesAndRanges
//
@@ -409,14 +434,13 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
return false;
const uint32_t numAttributes = abbrevDecl->NumAttributes();
- uint32_t i;
- dw_attr_t attr;
- dw_form_t form;
bool do_offset = false;
- for (i = 0; i < numAttributes; ++i) {
- abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
- DWARFFormValue form_value(cu, form);
+ for (uint32_t i = 0; i < numAttributes; ++i) {
+ DWARFFormValue form_value(cu);
+ dw_attr_t attr;
+ abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
+
if (form_value.ExtractValue(debug_info_data, &offset)) {
switch (attr) {
case DW_AT_low_pc:
@@ -446,20 +470,15 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
break;
case DW_AT_ranges: {
- const DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
- if (debug_ranges) {
- debug_ranges->FindRanges(cu->GetRangesBase(), form_value.Unsigned(), ranges);
- // All DW_AT_ranges are relative to the base address of the compile
- // unit. We add the compile unit base address to make sure all the
- // addresses are properly fixed up.
- ranges.Slide(cu->GetBaseAddress());
- } else {
+ const DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges();
+ if (debug_ranges)
+ debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value), ranges);
+ else
cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError(
"{0x%8.8x}: DIE has DW_AT_ranges(0x%" PRIx64
") attribute yet DWARF has no .debug_ranges, please file a bug "
"and attach the file at the start of this error message",
m_offset, form_value.Unsigned());
- }
} break;
case DW_AT_name:
@@ -521,7 +540,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
block_length);
} else {
const DWARFDataExtractor &debug_loc_data =
- dwarf2Data->get_debug_loc_data();
+ dwarf2Data->DebugLocData();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
size_t loc_list_length = DWARFExpression::LocationListSize(
@@ -606,14 +625,13 @@ void DWARFDebugInfoEntry::Dump(SymbolFileDWARF *dwarf2Data,
// Dump all data in the .debug_info for the attributes
const uint32_t numAttributes = abbrevDecl->NumAttributes();
- uint32_t i;
- dw_attr_t attr;
- dw_form_t form;
- for (i = 0; i < numAttributes; ++i) {
- abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+ for (uint32_t i = 0; i < numAttributes; ++i) {
+ DWARFFormValue form_value(cu);
+ dw_attr_t attr;
+ abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr,
- form);
+ form_value);
}
const DWARFDebugInfoEntry *child = GetFirstChild();
@@ -663,23 +681,21 @@ void DWARFDebugInfoEntry::DumpLocation(SymbolFileDWARF *dwarf2Data,
void DWARFDebugInfoEntry::DumpAttribute(
SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const DWARFDataExtractor &debug_info_data, lldb::offset_t *offset_ptr,
- Stream &s, dw_attr_t attr, dw_form_t form) {
+ Stream &s, dw_attr_t attr, DWARFFormValue &form_value) {
bool show_form = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
s.Printf(" ");
s.Indent(DW_AT_value_to_name(attr));
if (show_form) {
- s.Printf("[%s", DW_FORM_value_to_name(form));
+ s.Printf("[%s", DW_FORM_value_to_name(form_value.Form()));
}
- DWARFFormValue form_value(cu, form);
-
if (!form_value.ExtractValue(debug_info_data, offset_ptr))
return;
if (show_form) {
- if (form == DW_FORM_indirect) {
+ if (form_value.Form() == DW_FORM_indirect) {
s.Printf(" [%s]", DW_FORM_value_to_name(form_value.Form()));
}
@@ -719,7 +735,7 @@ void DWARFDebugInfoEntry::DumpAttribute(
uint64_t debug_loc_offset = form_value.Unsigned();
if (dwarf2Data) {
DWARFExpression::PrintDWARFLocationList(
- s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
+ s, cu, dwarf2Data->DebugLocData(), debug_loc_offset);
}
}
} break;
@@ -740,11 +756,13 @@ void DWARFDebugInfoEntry::DumpAttribute(
} break;
case DW_AT_ranges: {
- lldb::offset_t ranges_offset = form_value.Unsigned();
+ if (!dwarf2Data)
+ break;
+ lldb::offset_t ranges_offset =
+ GetRangesOffset(dwarf2Data->DebugRanges(), form_value);
dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
- if (dwarf2Data)
- DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(),
- &ranges_offset, base_addr);
+ DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(),
+ &ranges_offset, base_addr);
} break;
default:
@@ -786,11 +804,11 @@ size_t DWARFDebugInfoEntry::GetAttributes(
cu->GetAddressByteSize(), cu->IsDWARF64());
const uint32_t num_attributes = abbrevDecl->NumAttributes();
- uint32_t i;
- dw_attr_t attr;
- dw_form_t form;
- for (i = 0; i < num_attributes; ++i) {
- abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+ for (uint32_t i = 0; i < num_attributes; ++i) {
+ DWARFFormValue form_value(cu);
+ dw_attr_t attr;
+ abbrevDecl->GetAttrAndFormValueByIndex(i, attr, form_value);
+ const dw_form_t form = form_value.Form();
// If we are tracking down DW_AT_specification or DW_AT_abstract_origin
// attributes, the depth will be non-zero. We need to omit certain
@@ -811,7 +829,6 @@ size_t DWARFDebugInfoEntry::GetAttributes(
}
if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin)) {
- DWARFFormValue form_value(cu, form);
if (form_value.ExtractValue(debug_info_data, &offset)) {
dw_offset_t die_offset = form_value.Reference();
DWARFDIE spec_die =
@@ -1055,14 +1072,11 @@ size_t DWARFDebugInfoEntry::GetAttributeAddressRanges(
bool check_specification_or_abstract_origin) const {
ranges.Clear();
- dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(
- dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET,
- check_specification_or_abstract_origin);
- if (debug_ranges_offset != DW_INVALID_OFFSET) {
- DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
-
- debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
- ranges.Slide(cu->GetBaseAddress());
+ DWARFFormValue form_value;
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_ranges, form_value)) {
+ if (DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges())
+ debug_ranges->FindRanges(cu, GetRangesOffset(debug_ranges, form_value),
+ ranges);
} else if (check_hi_lo_pc) {
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
@@ -1713,16 +1727,13 @@ bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address,
((function_die != NULL) || (block_die != NULL));
}
} else {
- dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(
- dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
- if (debug_ranges_offset != DW_INVALID_OFFSET) {
+ DWARFFormValue form_value;
+ if (GetAttributeValue(dwarf2Data, cu, DW_AT_ranges, form_value)) {
DWARFRangeList ranges;
- DWARFDebugRanges *debug_ranges = dwarf2Data->DebugRanges();
- debug_ranges->FindRanges(cu->GetRangesBase(), debug_ranges_offset, ranges);
- // All DW_AT_ranges are relative to the base address of the compile
- // unit. We add the compile unit base address to make sure all the
- // addresses are properly fixed up.
- ranges.Slide(cu->GetBaseAddress());
+ DWARFDebugRangesBase *debug_ranges = dwarf2Data->DebugRanges();
+ debug_ranges->FindRanges(
+ cu, GetRangesOffset(debug_ranges, form_value), ranges);
+
if (ranges.FindEntryThatContains(address)) {
found_address = true;
// puts("***MATCH***");
@@ -1829,7 +1840,6 @@ void DWARFDebugInfoEntry::DumpDIECollection(
bool DWARFDebugInfoEntry::operator==(const DWARFDebugInfoEntry &rhs) const {
return m_offset == rhs.m_offset && m_parent_idx == rhs.m_parent_idx &&
m_sibling_idx == rhs.m_sibling_idx &&
- m_empty_children == rhs.m_empty_children &&
m_abbr_idx == rhs.m_abbr_idx && m_has_children == rhs.m_has_children &&
m_tag == rhs.m_tag;
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
index 97cb3046eb3e..ec19fc814fba 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -43,7 +43,6 @@ typedef UInt32ToDIEMMap::const_iterator UInt32ToDIEMMapConstIter;
class DWARFDeclContext;
#define DIE_SIBLING_IDX_BITSIZE 31
-#define DIE_ABBR_IDX_BITSIZE 15
class DWARFDebugInfoEntry {
public:
@@ -57,8 +56,7 @@ public:
DWARFDebugInfoEntry()
: m_offset(DW_INVALID_OFFSET), m_parent_idx(0), m_sibling_idx(0),
- m_empty_children(false), m_abbr_idx(0), m_has_children(false),
- m_tag(0) {}
+ m_has_children(false), m_abbr_idx(0), m_tag(0) {}
explicit operator bool() const { return m_offset != DW_INVALID_OFFSET; }
bool operator==(const DWARFDebugInfoEntry &rhs) const;
@@ -178,7 +176,7 @@ public:
DumpAttribute(SymbolFileDWARF *dwarf2Data, const DWARFUnit *cu,
const lldb_private::DWARFDataExtractor &debug_info_data,
lldb::offset_t *offset_ptr, lldb_private::Stream &s,
- dw_attr_t attr, dw_form_t form);
+ dw_attr_t attr, DWARFFormValue &form_value);
// This one dumps the comp unit name, objfile name and die offset for this die
// so the stream S.
void DumpLocation(SymbolFileDWARF *dwarf2Data, DWARFUnit *cu,
@@ -227,10 +225,10 @@ public:
// we don't need to store our child pointer, if we have a child it will
// be the next entry in the list...
DWARFDebugInfoEntry *GetFirstChild() {
- return (HasChildren() && !m_empty_children) ? this + 1 : NULL;
+ return HasChildren() ? this + 1 : NULL;
}
const DWARFDebugInfoEntry *GetFirstChild() const {
- return (HasChildren() && !m_empty_children) ? this + 1 : NULL;
+ return HasChildren() ? this + 1 : NULL;
}
void GetDeclContextDIEs(DWARFUnit *cu,
@@ -271,10 +269,6 @@ public:
void SetParentIndex(uint32_t idx) { m_parent_idx = idx; }
- bool GetEmptyChildren() const { return m_empty_children; }
-
- void SetEmptyChildren(bool b) { m_empty_children = b; }
-
static void
DumpDIECollection(lldb_private::Stream &strm,
DWARFDebugInfoEntry::collection &die_collection);
@@ -285,13 +279,13 @@ protected:
uint32_t m_parent_idx; // How many to subtract from "this" to get the parent.
// If zero this die has no parent
uint32_t m_sibling_idx : 31, // How many to add to "this" to get the sibling.
- m_empty_children : 1; // If a DIE says it had children, yet it just
- // contained a NULL tag, this will be set.
- uint32_t m_abbr_idx : DIE_ABBR_IDX_BITSIZE,
- m_has_children : 1, // Set to 1 if this DIE has children
- m_tag : 16; // A copy of the DW_TAG value so we don't
- // have to go through the compile unit
- // abbrev table
+ // If it is zero, then the DIE doesn't have children, or the
+ // DWARF claimed it had children but the DIE only contained
+ // a single NULL terminating child.
+ m_has_children : 1;
+ uint16_t m_abbr_idx;
+ uint16_t m_tag; // A copy of the DW_TAG value so we don't have to go through
+ // the compile unit abbrev table
};
#endif // SymbolFileDWARF_DWARFDebugInfoEntry_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
index 317ea4c22c66..d9f50122bd6f 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -41,7 +41,7 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data) {
if (line_table_sp.get() == NULL)
break;
- if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get())) {
+ if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get(), nullptr)) {
// Make sure we don't don't loop infinitely
if (offset <= debug_line_offset)
break;
@@ -127,7 +127,7 @@ DWARFDebugLine::DumpStatementTable(Log *log,
"--------\n",
debug_line_offset);
- if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log))
+ if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log, nullptr))
return offset;
else
return debug_line_offset + 1; // Skip to next byte in .debug_line section
@@ -366,17 +366,38 @@ void DWARFDebugLine::Parse(const DWARFDataExtractor &debug_line_data,
void *userData) {
lldb::offset_t offset = 0;
if (debug_line_data.ValidOffset(offset)) {
- if (!ParseStatementTable(debug_line_data, &offset, callback, userData))
+ if (!ParseStatementTable(debug_line_data, &offset, callback, userData, nullptr))
++offset; // Skip to next byte in .debug_line section
}
}
+namespace {
+struct EntryDescriptor {
+ dw_sleb128_t code;
+ dw_sleb128_t form;
+};
+
+static std::vector<EntryDescriptor>
+ReadDescriptors(const DWARFDataExtractor &debug_line_data,
+ lldb::offset_t *offset_ptr) {
+ std::vector<EntryDescriptor> ret;
+ uint8_t n = debug_line_data.GetU8(offset_ptr);
+ for (uint8_t i = 0; i < n; ++i) {
+ EntryDescriptor ent;
+ ent.code = debug_line_data.GetULEB128(offset_ptr);
+ ent.form = debug_line_data.GetULEB128(offset_ptr);
+ ret.push_back(ent);
+ }
+ return ret;
+}
+} // namespace
+
//----------------------------------------------------------------------
// DWARFDebugLine::ParsePrologue
//----------------------------------------------------------------------
bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
lldb::offset_t *offset_ptr,
- Prologue *prologue) {
+ Prologue *prologue, DWARFUnit *dwarf_cu) {
const lldb::offset_t prologue_offset = *offset_ptr;
// DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr);
@@ -386,9 +407,14 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
const char *s;
prologue->total_length = debug_line_data.GetDWARFInitialLength(offset_ptr);
prologue->version = debug_line_data.GetU16(offset_ptr);
- if (prologue->version < 2 || prologue->version > 4)
+ if (prologue->version < 2 || prologue->version > 5)
return false;
+ if (prologue->version >= 5) {
+ prologue->address_size = debug_line_data.GetU8(offset_ptr);
+ prologue->segment_selector_size = debug_line_data.GetU8(offset_ptr);
+ }
+
prologue->prologue_length = debug_line_data.GetDWARFOffset(offset_ptr);
const lldb::offset_t end_prologue_offset =
prologue->prologue_length + *offset_ptr;
@@ -410,25 +436,83 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
prologue->standard_opcode_lengths.push_back(op_len);
}
- while (*offset_ptr < end_prologue_offset) {
- s = debug_line_data.GetCStr(offset_ptr);
- if (s && s[0])
- prologue->include_directories.push_back(s);
- else
- break;
- }
+ if (prologue->version >= 5) {
+ std::vector<EntryDescriptor> dirEntryFormatV =
+ ReadDescriptors(debug_line_data, offset_ptr);
+ uint8_t dirCount = debug_line_data.GetULEB128(offset_ptr);
+ for (int i = 0; i < dirCount; ++i) {
+ for (EntryDescriptor &ent : dirEntryFormatV) {
+ DWARFFormValue value(dwarf_cu, ent.form);
+ if (ent.code != DW_LNCT_path) {
+ if (!value.SkipValue(debug_line_data, offset_ptr))
+ return false;
+ continue;
+ }
- while (*offset_ptr < end_prologue_offset) {
- const char *name = debug_line_data.GetCStr(offset_ptr);
- if (name && name[0]) {
- FileNameEntry fileEntry;
- fileEntry.name = name;
- fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
- fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
- fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
- prologue->file_names.push_back(fileEntry);
- } else
- break;
+ if (!value.ExtractValue(debug_line_data, offset_ptr))
+ return false;
+ prologue->include_directories.push_back(value.AsCString());
+ }
+ }
+
+ std::vector<EntryDescriptor> filesEntryFormatV =
+ ReadDescriptors(debug_line_data, offset_ptr);
+ llvm::DenseSet<std::pair<uint64_t, uint64_t>> seen;
+ uint8_t n = debug_line_data.GetULEB128(offset_ptr);
+ for (int i = 0; i < n; ++i) {
+ FileNameEntry entry;
+ for (EntryDescriptor &ent : filesEntryFormatV) {
+ DWARFFormValue value(dwarf_cu, ent.form);
+ if (!value.ExtractValue(debug_line_data, offset_ptr))
+ return false;
+
+ switch (ent.code) {
+ case DW_LNCT_path:
+ entry.name = value.AsCString();
+ break;
+ case DW_LNCT_directory_index:
+ entry.dir_idx = value.Unsigned();
+ break;
+ case DW_LNCT_timestamp:
+ entry.mod_time = value.Unsigned();
+ break;
+ case DW_LNCT_size:
+ entry.length = value.Unsigned();
+ break;
+ case DW_LNCT_MD5:
+ assert(value.Unsigned() == 16);
+ std::uninitialized_copy_n(value.BlockData(), 16,
+ entry.checksum.Bytes.begin());
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (seen.insert(entry.checksum.words()).second)
+ prologue->file_names.push_back(entry);
+ }
+ } else {
+ while (*offset_ptr < end_prologue_offset) {
+ s = debug_line_data.GetCStr(offset_ptr);
+ if (s && s[0])
+ prologue->include_directories.push_back(s);
+ else
+ break;
+ }
+
+ while (*offset_ptr < end_prologue_offset) {
+ const char *name = debug_line_data.GetCStr(offset_ptr);
+ if (name && name[0]) {
+ FileNameEntry fileEntry;
+ fileEntry.name = name;
+ fileEntry.dir_idx = debug_line_data.GetULEB128(offset_ptr);
+ fileEntry.mod_time = debug_line_data.GetULEB128(offset_ptr);
+ fileEntry.length = debug_line_data.GetULEB128(offset_ptr);
+ prologue->file_names.push_back(fileEntry);
+ } else
+ break;
+ }
}
// XXX GNU as is broken for 64-Bit DWARF
@@ -445,11 +529,11 @@ bool DWARFDebugLine::ParsePrologue(const DWARFDataExtractor &debug_line_data,
bool DWARFDebugLine::ParseSupportFiles(
const lldb::ModuleSP &module_sp, const DWARFDataExtractor &debug_line_data,
const lldb_private::FileSpec &cu_comp_dir, dw_offset_t stmt_list,
- FileSpecList &support_files) {
+ FileSpecList &support_files, DWARFUnit *dwarf_cu) {
lldb::offset_t offset = stmt_list;
Prologue prologue;
- if (!ParsePrologue(debug_line_data, &offset, &prologue)) {
+ if (!ParsePrologue(debug_line_data, &offset, &prologue, dwarf_cu)) {
Host::SystemLog(Host::eSystemLogError, "error: parsing line table prologue "
"at 0x%8.8x (parsing ended around "
"0x%8.8" PRIx64 "\n",
@@ -463,7 +547,7 @@ bool DWARFDebugLine::ParseSupportFiles(
for (uint32_t file_idx = 1;
prologue.GetFile(file_idx, cu_comp_dir, file_spec); ++file_idx) {
if (module_sp->RemapSourceFile(file_spec.GetPath(), remapped_file))
- file_spec.SetFile(remapped_file, false, FileSpec::Style::native);
+ file_spec.SetFile(remapped_file, FileSpec::Style::native);
support_files.Append(file_spec);
}
return true;
@@ -478,7 +562,7 @@ bool DWARFDebugLine::ParseSupportFiles(
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
- DWARFDebugLine::State::Callback callback, void *userData) {
+ DWARFDebugLine::State::Callback callback, void *userData, DWARFUnit *dwarf_cu) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE));
Prologue::shared_ptr prologue(new Prologue());
@@ -489,7 +573,7 @@ bool DWARFDebugLine::ParseStatementTable(
func_cat, "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
debug_line_offset);
- if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get())) {
+ if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get(), dwarf_cu)) {
if (log)
log->Error("failed to parse DWARF line table prologue");
// Restore our offset and return false to indicate failure!
@@ -775,9 +859,9 @@ static void ParseStatementTableCallback(dw_offset_t offset,
//----------------------------------------------------------------------
bool DWARFDebugLine::ParseStatementTable(
const DWARFDataExtractor &debug_line_data, lldb::offset_t *offset_ptr,
- LineTable *line_table) {
+ LineTable *line_table, DWARFUnit *dwarf_cu) {
return ParseStatementTable(debug_line_data, offset_ptr,
- ParseStatementTableCallback, line_table);
+ ParseStatementTableCallback, line_table, dwarf_cu);
}
inline bool DWARFDebugLine::Prologue::IsValid() const {
@@ -866,7 +950,7 @@ bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx,
const lldb_private::FileSpec &comp_dir, FileSpec &file) const {
uint32_t idx = file_idx - 1; // File indexes are 1 based...
if (idx < file_names.size()) {
- file.SetFile(file_names[idx].name, false, FileSpec::Style::native);
+ file.SetFile(file_names[idx].name, FileSpec::Style::native);
if (file.IsRelative()) {
if (file_names[idx].dir_idx > 0) {
const uint32_t dir_idx = file_names[idx].dir_idx - 1;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
index 3ab15ac59028..04f72e03a2db 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -19,6 +19,9 @@
#include "DWARFDataExtractor.h"
#include "DWARFDefines.h"
+#include "llvm/Support/MD5.h"
+
+class DWARFUnit;
class SymbolFileDWARF;
//----------------------------------------------------------------------
@@ -36,6 +39,7 @@ public:
dw_sleb128_t dir_idx;
dw_sleb128_t mod_time;
dw_sleb128_t length;
+ llvm::MD5::MD5Result checksum;
};
//------------------------------------------------------------------
@@ -55,6 +59,10 @@ public:
// total_length field itself).
uint16_t
version; // Version identifier for the statement information format.
+
+ uint8_t address_size;
+ uint8_t segment_selector_size;
+
uint32_t prologue_length; // The number of bytes following the
// prologue_length field to the beginning of the
// first byte of the statement program itself.
@@ -201,14 +209,15 @@ public:
const lldb_private::DWARFDataExtractor &debug_line_data,
const lldb_private::FileSpec &cu_comp_dir,
dw_offset_t stmt_list,
- lldb_private::FileSpecList &support_files);
+ lldb_private::FileSpecList &support_files, DWARFUnit *dwarf_cu);
static bool
ParsePrologue(const lldb_private::DWARFDataExtractor &debug_line_data,
- lldb::offset_t *offset_ptr, Prologue *prologue);
+ lldb::offset_t *offset_ptr, Prologue *prologue,
+ DWARFUnit *dwarf_cu = nullptr);
static bool
ParseStatementTable(const lldb_private::DWARFDataExtractor &debug_line_data,
lldb::offset_t *offset_ptr, State::Callback callback,
- void *userData);
+ void *userData, DWARFUnit *dwarf_cu);
static dw_offset_t
DumpStatementTable(lldb_private::Log *log,
const lldb_private::DWARFDataExtractor &debug_line_data,
@@ -219,7 +228,8 @@ public:
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);
+ lldb::offset_t *offset_ptr, LineTable *line_table,
+ DWARFUnit *dwarf_cu);
static void Parse(const lldb_private::DWARFDataExtractor &debug_line_data,
DWARFDebugLine::State::Callback callback, void *userData);
// static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue,
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
index 1c31d1c42598..d79acdc5cfc4 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacro.cpp
@@ -25,7 +25,7 @@ DWARFDebugMacroHeader::ParseHeader(const DWARFDataExtractor &debug_macro_data,
header.m_version = debug_macro_data.GetU16(offset);
uint8_t flags = debug_macro_data.GetU8(offset);
- header.m_offset_is_64_bit = flags & OFFSET_SIZE_MASK ? true : false;
+ header.m_offset_is_64_bit = (flags & OFFSET_SIZE_MASK) != 0;
if (flags & DEBUG_LINE_OFFSET_MASK) {
if (header.m_offset_is_64_bit)
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
index 89e27efb3cc2..a0436dd7ffad 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "DWARFDebugRanges.h"
+#include "DWARFUnit.h"
#include "SymbolFileDWARF.h"
#include "lldb/Utility/Stream.h"
#include <assert.h>
@@ -29,8 +30,6 @@ static dw_addr_t GetBaseAddressMarker(uint32_t addr_size) {
DWARFDebugRanges::DWARFDebugRanges() : m_range_map() {}
-DWARFDebugRanges::~DWARFDebugRanges() {}
-
void DWARFDebugRanges::Extract(SymbolFileDWARF *dwarf2Data) {
DWARFRangeList range_list;
lldb::offset_t offset = 0;
@@ -112,14 +111,185 @@ void DWARFDebugRanges::Dump(Stream &s,
}
}
-bool DWARFDebugRanges::FindRanges(dw_addr_t debug_ranges_base,
+bool DWARFDebugRanges::FindRanges(const DWARFUnit *cu,
dw_offset_t debug_ranges_offset,
DWARFRangeList &range_list) const {
- dw_addr_t debug_ranges_address = debug_ranges_base + debug_ranges_offset;
+ dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
range_map_const_iterator pos = m_range_map.find(debug_ranges_address);
if (pos != m_range_map.end()) {
range_list = pos->second;
+
+ // All DW_AT_ranges are relative to the base address of the compile
+ // unit. We add the compile unit base address to make sure all the
+ // addresses are properly fixed up.
+ range_list.Slide(cu->GetBaseAddress());
+ return true;
+ }
+ return false;
+}
+
+uint64_t DWARFDebugRanges::GetOffset(size_t Index) const {
+ lldbassert(false && "DW_FORM_rnglistx is not present before DWARF5");
+ return 0;
+}
+
+bool DWARFDebugRngLists::ExtractRangeList(
+ const DWARFDataExtractor &data, uint8_t addrSize,
+ lldb::offset_t *offset_ptr, std::vector<RngListEntry> &rangeList) {
+ rangeList.clear();
+
+ bool error = false;
+ while (!error) {
+ switch (data.GetU8(offset_ptr)) {
+ case DW_RLE_end_of_list:
+ return true;
+
+ case DW_RLE_start_length: {
+ dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
+ dw_addr_t len = data.GetULEB128(offset_ptr);
+ rangeList.push_back({DW_RLE_start_length, begin, len});
+ break;
+ }
+
+ case DW_RLE_start_end: {
+ dw_addr_t begin = data.GetMaxU64(offset_ptr, addrSize);
+ dw_addr_t end = data.GetMaxU64(offset_ptr, addrSize);
+ rangeList.push_back({DW_RLE_start_end, begin, end});
+ break;
+ }
+
+ case DW_RLE_base_address: {
+ dw_addr_t base = data.GetMaxU64(offset_ptr, addrSize);
+ rangeList.push_back({DW_RLE_base_address, base, 0});
+ break;
+ }
+
+ case DW_RLE_offset_pair: {
+ dw_addr_t begin = data.GetULEB128(offset_ptr);
+ dw_addr_t end = data.GetULEB128(offset_ptr);
+ rangeList.push_back({DW_RLE_offset_pair, begin, end});
+ break;
+ }
+
+ case DW_RLE_base_addressx: {
+ dw_addr_t base = data.GetULEB128(offset_ptr);
+ rangeList.push_back({DW_RLE_base_addressx, base, 0});
+ break;
+ }
+
+ case DW_RLE_startx_endx: {
+ dw_addr_t start = data.GetULEB128(offset_ptr);
+ dw_addr_t end = data.GetULEB128(offset_ptr);
+ rangeList.push_back({DW_RLE_startx_endx, start, end});
+ break;
+ }
+
+ case DW_RLE_startx_length: {
+ dw_addr_t start = data.GetULEB128(offset_ptr);
+ dw_addr_t length = data.GetULEB128(offset_ptr);
+ rangeList.push_back({DW_RLE_startx_length, start, length});
+ break;
+ }
+
+ default:
+ lldbassert(0 && "unknown range list entry encoding");
+ error = true;
+ }
+ }
+
+ return false;
+}
+
+static uint64_t ReadAddressFromDebugAddrSection(const DWARFUnit *cu,
+ uint32_t index) {
+ uint32_t index_size = cu->GetAddressByteSize();
+ dw_offset_t addr_base = cu->GetAddrBase();
+ lldb::offset_t offset = addr_base + index * index_size;
+ return cu->GetSymbolFileDWARF()->get_debug_addr_data().GetMaxU64(&offset,
+ index_size);
+}
+
+bool DWARFDebugRngLists::FindRanges(const DWARFUnit *cu,
+ dw_offset_t debug_ranges_offset,
+ DWARFRangeList &range_list) const {
+ range_list.Clear();
+ dw_addr_t debug_ranges_address = cu->GetRangesBase() + debug_ranges_offset;
+ auto pos = m_range_map.find(debug_ranges_address);
+ if (pos != m_range_map.end()) {
+ dw_addr_t BaseAddr = cu->GetBaseAddress();
+ for (const RngListEntry &E : pos->second) {
+ switch (E.encoding) {
+ case DW_RLE_start_length:
+ range_list.Append(DWARFRangeList::Entry(E.value0, E.value1));
+ break;
+ case DW_RLE_base_address:
+ BaseAddr = E.value0;
+ break;
+ case DW_RLE_start_end:
+ range_list.Append(DWARFRangeList::Entry(E.value0, E.value1 - E.value0));
+ break;
+ case DW_RLE_offset_pair:
+ range_list.Append(
+ DWARFRangeList::Entry(BaseAddr + E.value0, E.value1 - E.value0));
+ break;
+ case DW_RLE_base_addressx: {
+ BaseAddr = ReadAddressFromDebugAddrSection(cu, E.value0);
+ break;
+ }
+ case DW_RLE_startx_endx: {
+ dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
+ dw_addr_t end = ReadAddressFromDebugAddrSection(cu, E.value1);
+ range_list.Append(DWARFRangeList::Entry(start, end - start));
+ break;
+ }
+ case DW_RLE_startx_length: {
+ dw_addr_t start = ReadAddressFromDebugAddrSection(cu, E.value0);
+ range_list.Append(DWARFRangeList::Entry(start, E.value1));
+ break;
+ }
+ default:
+ llvm_unreachable("unexpected encoding");
+ }
+ }
return true;
}
return false;
}
+
+void DWARFDebugRngLists::Extract(SymbolFileDWARF *dwarf2Data) {
+ const DWARFDataExtractor &data = dwarf2Data->get_debug_rnglists_data();
+ lldb::offset_t offset = 0;
+
+ uint64_t length = data.GetU32(&offset);
+ bool isDwarf64 = (length == 0xffffffff);
+ if (isDwarf64)
+ length = data.GetU64(&offset);
+ lldb::offset_t end = offset + length;
+
+ // Check version.
+ if (data.GetU16(&offset) < 5)
+ return;
+
+ uint8_t addrSize = data.GetU8(&offset);
+
+ // We do not support non-zero segment selector size.
+ if (data.GetU8(&offset) != 0) {
+ lldbassert(0 && "not implemented");
+ return;
+ }
+
+ uint32_t offsetsAmount = data.GetU32(&offset);
+ for (uint32_t i = 0; i < offsetsAmount; ++i)
+ Offsets.push_back(data.GetMaxU64(&offset, isDwarf64 ? 8 : 4));
+
+ lldb::offset_t listOffset = offset;
+ std::vector<RngListEntry> rangeList;
+ while (offset < end && ExtractRangeList(data, addrSize, &offset, rangeList)) {
+ m_range_map[listOffset] = rangeList;
+ listOffset = offset;
+ }
+}
+
+uint64_t DWARFDebugRngLists::GetOffset(size_t Index) const {
+ return Offsets[Index];
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
index f514359e00a4..5790f448ba85 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -15,17 +15,28 @@
#include <map>
-class DWARFDebugRanges {
+class DWARFDebugRangesBase {
+public:
+ virtual ~DWARFDebugRangesBase(){};
+
+ virtual void Extract(SymbolFileDWARF *dwarf2Data) = 0;
+ virtual bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
+ DWARFRangeList &range_list) const = 0;
+ virtual uint64_t GetOffset(size_t Index) const = 0;
+};
+
+class DWARFDebugRanges final : public DWARFDebugRangesBase {
public:
DWARFDebugRanges();
- ~DWARFDebugRanges();
- void Extract(SymbolFileDWARF *dwarf2Data);
+
+ void Extract(SymbolFileDWARF *dwarf2Data) override;
+ bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
+ DWARFRangeList &range_list) const override;
+ uint64_t GetOffset(size_t Index) const override;
+
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_addr_t debug_ranges_base,
- dw_offset_t debug_ranges_offset,
- DWARFRangeList &range_list) const;
protected:
bool Extract(SymbolFileDWARF *dwarf2Data, lldb::offset_t *offset_ptr,
@@ -37,4 +48,27 @@ protected:
range_map m_range_map;
};
+// DWARF v5 .debug_rnglists section.
+class DWARFDebugRngLists final : public DWARFDebugRangesBase {
+ struct RngListEntry {
+ uint8_t encoding;
+ uint64_t value0;
+ uint64_t value1;
+ };
+
+public:
+ void Extract(SymbolFileDWARF *dwarf2Data) override;
+ bool FindRanges(const DWARFUnit *cu, dw_offset_t debug_ranges_offset,
+ DWARFRangeList &range_list) const override;
+ uint64_t GetOffset(size_t Index) const override;
+
+protected:
+ bool ExtractRangeList(const lldb_private::DWARFDataExtractor &data,
+ uint8_t addrSize, lldb::offset_t *offset_ptr,
+ std::vector<RngListEntry> &list);
+
+ std::vector<uint64_t> Offsets;
+ std::map<dw_offset_t, std::vector<RngListEntry>> m_range_map;
+};
+
#endif // SymbolFileDWARF_DWARFDebugRanges_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
index 1f3c59768fdf..aff5ea64e9ce 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -10,13 +10,9 @@
#ifndef SymbolFileDWARF_DWARFDeclContext_h_
#define SymbolFileDWARF_DWARFDeclContext_h_
-// C Includes
-// C++ Includes
#include <string>
#include <vector>
-// Other libraries and framework includes
#include "lldb/Utility/ConstString.h"
-// Project includes
#include "DWARFDefines.h"
//----------------------------------------------------------------------
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
index 1d927ba3bca3..99becdbb2bc1 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
@@ -504,9 +504,9 @@ const char *DW_MACINFO_value_to_name(uint32_t val) {
return llvmstr.data();
}
-const char *DW_CFA_value_to_name(uint32_t val) {
+const char *DW_CFA_value_to_name(uint32_t val, llvm::Triple::ArchType Arch) {
static char invalid[100];
- llvm::StringRef llvmstr = llvm::dwarf::CallFrameString(val);
+ llvm::StringRef llvmstr = llvm::dwarf::CallFrameString(val, Arch);
if (llvmstr.empty()) {
snprintf(invalid, sizeof(invalid), "Unknown DW_CFA constant: 0x%x", val);
return invalid;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
index 926f83b3564a..0f5a885efb86 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -64,7 +64,7 @@ const char *DW_LNE_value_to_name(uint32_t val);
const char *DW_MACINFO_value_to_name(uint32_t val);
-const char *DW_CFA_value_to_name(uint32_t val);
+const char *DW_CFA_value_to_name(uint32_t val, llvm::Triple::ArchType Arch);
const char *DW_GNU_EH_PE_value_to_name(uint32_t val);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
index 4fde5748d3f3..5d2a8ffdb85b 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -154,6 +154,9 @@ DWARFFormValue::GetFixedFormSizesForAddressSize(uint8_t addr_size,
DWARFFormValue::DWARFFormValue() : m_cu(NULL), m_form(0), m_value() {}
+DWARFFormValue::DWARFFormValue(const DWARFUnit *cu)
+ : m_cu(cu), m_form(0), m_value() {}
+
DWARFFormValue::DWARFFormValue(const DWARFUnit *cu, dw_form_t form)
: m_cu(cu), m_form(form), m_value() {}
@@ -165,6 +168,9 @@ void DWARFFormValue::Clear() {
bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
lldb::offset_t *offset_ptr) {
+ if (m_form == DW_FORM_implicit_const)
+ return true;
+
bool indirect = false;
bool is_block = false;
m_value.data = NULL;
@@ -176,8 +182,12 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
switch (m_form) {
case DW_FORM_addr:
assert(m_cu);
- m_value.value.uval = data.GetMaxU64(
- offset_ptr, DWARFUnit::GetAddressByteSize(m_cu));
+ m_value.value.uval =
+ data.GetMaxU64(offset_ptr, DWARFUnit::GetAddressByteSize(m_cu));
+ break;
+ case DW_FORM_block1:
+ m_value.value.uval = data.GetU8(offset_ptr);
+ is_block = true;
break;
case DW_FORM_block2:
m_value.value.uval = data.GetU16(offset_ptr);
@@ -187,94 +197,82 @@ bool DWARFFormValue::ExtractValue(const DWARFDataExtractor &data,
m_value.value.uval = data.GetU32(offset_ptr);
is_block = true;
break;
- case DW_FORM_data2:
- m_value.value.uval = data.GetU16(offset_ptr);
- break;
- case DW_FORM_data4:
- m_value.value.uval = data.GetU32(offset_ptr);
- break;
- case DW_FORM_data8:
- m_value.value.uval = data.GetU64(offset_ptr);
- break;
- case DW_FORM_string:
- m_value.value.cstr = data.GetCStr(offset_ptr);
+ case DW_FORM_data16:
+ m_value.value.uval = 16;
+ is_block = true;
break;
case DW_FORM_exprloc:
case DW_FORM_block:
m_value.value.uval = data.GetULEB128(offset_ptr);
is_block = true;
break;
- case DW_FORM_block1:
- m_value.value.uval = data.GetU8(offset_ptr);
- is_block = true;
- break;
- case DW_FORM_data1:
- m_value.value.uval = data.GetU8(offset_ptr);
- break;
- case DW_FORM_flag:
- m_value.value.uval = data.GetU8(offset_ptr);
+ case DW_FORM_string:
+ m_value.value.cstr = data.GetCStr(offset_ptr);
break;
case DW_FORM_sdata:
m_value.value.sval = data.GetSLEB128(offset_ptr);
break;
case DW_FORM_strp:
+ case DW_FORM_line_strp:
+ case DW_FORM_sec_offset:
assert(m_cu);
m_value.value.uval =
data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
break;
- // case DW_FORM_APPLE_db_str:
- case DW_FORM_udata:
- m_value.value.uval = data.GetULEB128(offset_ptr);
- break;
- case DW_FORM_ref_addr:
- assert(m_cu);
- ref_addr_size = 4;
- if (m_cu->GetVersion() <= 2)
- ref_addr_size = m_cu->GetAddressByteSize();
- else
- ref_addr_size = m_cu->IsDWARF64() ? 8 : 4;
- m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
- break;
+ case DW_FORM_addrx1:
+ case DW_FORM_strx1:
case DW_FORM_ref1:
+ case DW_FORM_data1:
+ case DW_FORM_flag:
m_value.value.uval = data.GetU8(offset_ptr);
break;
+ case DW_FORM_addrx2:
+ case DW_FORM_strx2:
case DW_FORM_ref2:
+ case DW_FORM_data2:
m_value.value.uval = data.GetU16(offset_ptr);
break;
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ m_value.value.uval = data.GetMaxU64(offset_ptr, 3);
+ break;
+ case DW_FORM_addrx4:
+ case DW_FORM_strx4:
case DW_FORM_ref4:
+ case DW_FORM_data4:
m_value.value.uval = data.GetU32(offset_ptr);
break;
+ case DW_FORM_data8:
case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
m_value.value.uval = data.GetU64(offset_ptr);
break;
+ case DW_FORM_addrx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_strx:
+ case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
m_value.value.uval = data.GetULEB128(offset_ptr);
break;
+ case DW_FORM_ref_addr:
+ assert(m_cu);
+ if (m_cu->GetVersion() <= 2)
+ ref_addr_size = m_cu->GetAddressByteSize();
+ else
+ ref_addr_size = m_cu->IsDWARF64() ? 8 : 4;
+ m_value.value.uval = data.GetMaxU64(offset_ptr, ref_addr_size);
+ break;
case DW_FORM_indirect:
m_form = data.GetULEB128(offset_ptr);
indirect = true;
break;
-
- case DW_FORM_sec_offset:
- assert(m_cu);
- m_value.value.uval =
- data.GetMaxU64(offset_ptr, DWARFUnit::IsDWARF64(m_cu) ? 8 : 4);
- break;
case DW_FORM_flag_present:
m_value.value.uval = 1;
break;
- case DW_FORM_ref_sig8:
- m_value.value.uval = data.GetU64(offset_ptr);
- break;
- case DW_FORM_GNU_str_index:
- m_value.value.uval = data.GetULEB128(offset_ptr);
- break;
- case DW_FORM_GNU_addr_index:
- m_value.value.uval = data.GetULEB128(offset_ptr);
- break;
default:
return false;
- break;
}
} while (indirect);
@@ -346,49 +344,65 @@ bool DWARFFormValue::SkipValue(dw_form_t form,
// 0 bytes values (implied from DW_FORM)
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
return true;
- // 1 byte values
- case DW_FORM_data1:
- case DW_FORM_flag:
- case DW_FORM_ref1:
- *offset_ptr += 1;
- return true;
+ // 1 byte values
+ case DW_FORM_addrx1:
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ case DW_FORM_strx1:
+ *offset_ptr += 1;
+ return true;
- // 2 byte values
- case DW_FORM_data2:
- case DW_FORM_ref2:
- *offset_ptr += 2;
- return true;
+ // 2 byte values
+ case DW_FORM_addrx2:
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ case DW_FORM_strx2:
+ *offset_ptr += 2;
+ return true;
- // 32 bit for DWARF 32, 64 for DWARF 64
- case DW_FORM_sec_offset:
- case DW_FORM_strp:
- assert(cu);
- *offset_ptr += (cu->IsDWARF64() ? 8 : 4);
- return true;
+ // 3 byte values
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ *offset_ptr += 3;
+ return true;
- // 4 byte values
- case DW_FORM_data4:
- case DW_FORM_ref4:
- *offset_ptr += 4;
- return true;
+ // 32 bit for DWARF 32, 64 for DWARF 64
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp:
+ assert(cu);
+ *offset_ptr += (cu->IsDWARF64() ? 8 : 4);
+ return true;
- // 8 byte values
- case DW_FORM_data8:
- case DW_FORM_ref8:
- case DW_FORM_ref_sig8:
- *offset_ptr += 8;
- return true;
+ // 4 byte values
+ case DW_FORM_addrx4:
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ case DW_FORM_strx4:
+ *offset_ptr += 4;
+ return true;
- // signed or unsigned LEB 128 values
- case DW_FORM_sdata:
- case DW_FORM_udata:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_addr_index:
- case DW_FORM_GNU_str_index:
- debug_info_data.Skip_LEB128(offset_ptr);
- return true;
+ // 8 byte values
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ *offset_ptr += 8;
+ return true;
+
+ // signed or unsigned LEB 128 values
+ case DW_FORM_addrx:
+ case DW_FORM_rnglistx:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_strx:
+ debug_info_data.Skip_LEB128(offset_ptr);
+ return true;
case DW_FORM_indirect: {
dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
@@ -546,6 +560,26 @@ const char *DWARFFormValue::AsCString() const {
index_size);
return symbol_file->get_debug_str_data().PeekCStr(str_offset);
}
+
+ if (m_form == DW_FORM_strx || m_form == DW_FORM_strx1 ||
+ m_form == DW_FORM_strx2 || m_form == DW_FORM_strx3 ||
+ m_form == DW_FORM_strx4) {
+
+ // The same code as above.
+ if (!symbol_file)
+ return nullptr;
+
+ uint32_t indexSize = m_cu->IsDWARF64() ? 8 : 4;
+ lldb::offset_t offset =
+ m_cu->GetStrOffsetsBase() + m_value.value.uval * indexSize;
+ dw_offset_t strOffset =
+ symbol_file->get_debug_str_offsets_data().GetMaxU64(&offset, indexSize);
+ return symbol_file->get_debug_str_data().PeekCStr(strOffset);
+ }
+
+ if (m_form == DW_FORM_line_strp)
+ return symbol_file->get_debug_line_str_data().PeekCStr(m_value.value.uval);
+
return nullptr;
}
@@ -556,7 +590,9 @@ dw_addr_t DWARFFormValue::Address() const {
return Unsigned();
assert(m_cu);
- assert(m_form == DW_FORM_GNU_addr_index);
+ assert(m_form == DW_FORM_GNU_addr_index || m_form == DW_FORM_addrx ||
+ m_form == DW_FORM_addrx1 || m_form == DW_FORM_addrx2 ||
+ m_form == DW_FORM_addrx3 || m_form == DW_FORM_addrx4);
if (!symbol_file)
return 0;
@@ -568,7 +604,7 @@ dw_addr_t DWARFFormValue::Address() const {
}
uint64_t DWARFFormValue::Reference() const {
- uint64_t die_offset = m_value.value.uval;
+ uint64_t value = m_value.value.uval;
switch (m_form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
@@ -577,32 +613,36 @@ uint64_t DWARFFormValue::Reference() const {
case DW_FORM_ref_udata:
assert(m_cu); // CU must be valid for DW_FORM_ref forms that are compile
// unit relative or we will get this wrong
- die_offset += m_cu->GetOffset();
- break;
+ return value + m_cu->GetOffset();
+
+ case DW_FORM_ref_addr:
+ case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_ref_alt:
+ return value;
default:
- break;
+ return DW_INVALID_OFFSET;
}
-
- return die_offset;
}
uint64_t DWARFFormValue::Reference(dw_offset_t base_offset) const {
- uint64_t die_offset = m_value.value.uval;
+ uint64_t value = m_value.value.uval;
switch (m_form) {
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- die_offset += base_offset;
- break;
+ return value + base_offset;
+
+ case DW_FORM_ref_addr:
+ case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_ref_alt:
+ return value;
default:
- break;
+ return DW_INVALID_OFFSET;
}
-
- return die_offset;
}
const uint8_t *DWARFFormValue::BlockData() const { return m_value.data; }
@@ -729,6 +769,8 @@ int DWARFFormValue::Compare(const DWARFFormValue &a_value,
bool DWARFFormValue::FormIsSupported(dw_form_t form) {
switch (form) {
case DW_FORM_addr:
+ case DW_FORM_addrx:
+ case DW_FORM_rnglistx:
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_data2:
@@ -741,6 +783,11 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) {
case DW_FORM_flag:
case DW_FORM_sdata:
case DW_FORM_strp:
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
case DW_FORM_udata:
case DW_FORM_ref_addr:
case DW_FORM_ref1:
@@ -755,6 +802,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) {
case DW_FORM_ref_sig8:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_addr_index:
+ case DW_FORM_implicit_const:
return true;
default:
break;
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index ef1a693b37c9..0890f0c1bfc5 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -11,9 +11,10 @@
#define SymbolFileDWARF_DWARFFormValue_h_
#include "DWARFDataExtractor.h"
-#include <stddef.h> // for NULL
+#include <stddef.h>
class DWARFUnit;
+class SymbolFileDWARF;
class DWARFFormValue {
public:
@@ -55,12 +56,17 @@ public:
};
DWARFFormValue();
+ DWARFFormValue(const DWARFUnit *cu);
DWARFFormValue(const DWARFUnit *cu, dw_form_t form);
const DWARFUnit *GetCompileUnit() const { return m_cu; }
void SetCompileUnit(const DWARFUnit *cu) { m_cu = cu; }
dw_form_t Form() const { return m_form; }
+ dw_form_t& FormRef() { return m_form; }
void SetForm(dw_form_t form) { m_form = form; }
const ValueType &Value() const { return m_value; }
+ ValueType &ValueRef() { return m_value; }
+ void SetValue(const ValueType &val) { m_value = val; }
+
void Dump(lldb_private::Stream &s) const;
bool ExtractValue(const lldb_private::DWARFDataExtractor &data,
lldb::offset_t *offset_ptr);
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
index f44b2bb97b2b..7afc71bc24f0 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -191,13 +191,6 @@ void DWARFUnit::ExtractDIEsRWLocked() {
IsDWARF64());
while (offset < next_cu_offset &&
die.FastExtract(data, this, fixed_form_sizes, &offset)) {
- // if (log)
- // log->Printf("0x%8.8x: %*.*s%s%s",
- // die.GetOffset(),
- // depth * 2, depth * 2, "",
- // DW_TAG_value_to_name (die.Tag()),
- // die.HasChildren() ? " *" : "");
-
const bool null_die = die.IsNULL();
if (depth == 0) {
assert(m_die_array.empty() && "Compile unit DIE already added");
@@ -223,7 +216,7 @@ void DWARFUnit::ExtractDIEsRWLocked() {
// the list (saves up to 25% in C++ code), we need a way to let the
// DIE know that it actually doesn't have children.
if (!m_die_array.empty())
- m_die_array.back().SetEmptyChildren(true);
+ m_die_array.back().SetHasChildren(false);
}
} else {
die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]);
@@ -244,9 +237,6 @@ void DWARFUnit::ExtractDIEsRWLocked() {
if (depth > 0)
--depth;
- if (depth == 0)
- break; // We are done with this compile unit!
-
prev_die_had_children = false;
} else {
die_index_stack.back() = m_die_array.size() - 1;
@@ -258,10 +248,17 @@ void DWARFUnit::ExtractDIEsRWLocked() {
}
prev_die_had_children = die_has_children;
}
+
+ if (depth == 0)
+ break; // We are done with this compile unit!
}
if (!m_die_array.empty()) {
- lldbassert(!m_first_die || m_first_die == m_die_array.front());
+ if (m_first_die) {
+ // Only needed for the assertion.
+ m_first_die.SetHasChildren(m_die_array.front().HasChildren());
+ lldbassert(m_first_die == m_die_array.front());
+ }
m_first_die = m_die_array.front();
}
@@ -301,8 +298,46 @@ void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const {
}
}
+// This is used when a split dwarf is enabled.
+// A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute
+// that points to the first string offset of the CU contribution to the
+// .debug_str_offsets. At the same time, the corresponding split debug unit also
+// may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and
+// for that case, we should find the offset (skip the section header).
+static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) {
+ lldb::offset_t baseOffset = 0;
+
+ const DWARFDataExtractor &strOffsets =
+ dwo_cu->GetSymbolFileDWARF()->get_debug_str_offsets_data();
+ uint64_t length = strOffsets.GetU32(&baseOffset);
+ if (length == 0xffffffff)
+ length = strOffsets.GetU64(&baseOffset);
+
+ // Check version.
+ if (strOffsets.GetU16(&baseOffset) < 5)
+ return;
+
+ // Skip padding.
+ baseOffset += 2;
+
+ dwo_cu->SetStrOffsetsBase(baseOffset);
+}
+
// m_die_array_mutex must be already held as read/write.
void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
+ dw_addr_t addr_base = cu_die.GetAttributeValueAsUnsigned(
+ m_dwarf, this, DW_AT_addr_base, LLDB_INVALID_ADDRESS);
+ if (addr_base != LLDB_INVALID_ADDRESS)
+ SetAddrBase(addr_base);
+
+ dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
+ m_dwarf, this, DW_AT_rnglists_base, LLDB_INVALID_ADDRESS);
+ if (ranges_base != LLDB_INVALID_ADDRESS)
+ SetRangesBase(ranges_base);
+
+ SetStrOffsetsBase(cu_die.GetAttributeValueAsUnsigned(
+ m_dwarf, this, DW_AT_str_offsets_base, 0));
+
uint64_t base_addr = cu_die.GetAttributeValueAsAddress(
m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
if (base_addr == LLDB_INVALID_ADDRESS)
@@ -333,11 +368,25 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) {
m_dwo_symbol_file = std::move(dwo_symbol_file);
- dw_addr_t addr_base =
- cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0);
- dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned(
- m_dwarf, this, DW_AT_GNU_ranges_base, 0);
- dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset);
+ // Here for DWO CU we want to use the address base set in the skeleton unit
+ // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base
+ // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_*
+ // attributes which were applicable to the DWO units. The corresponding
+ // DW_AT_* attributes standardized in DWARF v5 are also applicable to the main
+ // unit in contrast.
+ if (addr_base == LLDB_INVALID_ADDRESS)
+ addr_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this,
+ DW_AT_GNU_addr_base, 0);
+ dwo_cu->SetAddrBase(addr_base);
+
+ if (ranges_base == LLDB_INVALID_ADDRESS)
+ ranges_base = cu_die.GetAttributeValueAsUnsigned(m_dwarf, this,
+ DW_AT_GNU_ranges_base, 0);
+ dwo_cu->SetRangesBase(ranges_base);
+
+ dwo_cu->SetBaseObjOffset(m_offset);
+
+ SetDwoStrOffsetsBase(dwo_cu);
}
DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
@@ -395,14 +444,20 @@ dw_offset_t DWARFUnit::GetAbbrevOffset() const {
return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
}
-void DWARFUnit::SetAddrBase(dw_addr_t addr_base,
- dw_addr_t ranges_base,
- dw_offset_t base_obj_offset) {
- m_addr_base = addr_base;
+void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; }
+
+void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) {
m_ranges_base = ranges_base;
+}
+
+void DWARFUnit::SetBaseObjOffset(dw_offset_t base_obj_offset) {
m_base_obj_offset = base_obj_offset;
}
+void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) {
+ m_str_offsets_base = str_offsets_base;
+}
+
// It may be called only with m_die_array_mutex held R/W.
void DWARFUnit::ClearDIEsRWLocked() {
m_die_array.clear();
@@ -586,9 +641,7 @@ void DWARFUnit::SetUserData(void *d) {
}
bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() {
- if (GetProducer() == eProducerLLVMGCC)
- return false;
- return true;
+ return GetProducer() != eProducerLLVMGCC;
}
bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
@@ -600,11 +653,8 @@ bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
bool DWARFUnit::Supports_unnamed_objc_bitfields() {
if (GetProducer() == eProducerClang) {
const uint32_t major_version = GetProducerVersionMajor();
- if (major_version > 425 ||
- (major_version == 425 && GetProducerVersionUpdate() >= 13))
- return true;
- else
- return false;
+ return major_version > 425 ||
+ (major_version == 425 && GetProducerVersionUpdate() >= 13);
}
return true; // Assume all other compilers didn't have incorrect ObjC bitfield
// info
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
index 3cc24d4202b8..178c894686ee 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
@@ -111,8 +111,11 @@ public:
dw_addr_t GetBaseAddress() const { return m_base_addr; }
dw_addr_t GetAddrBase() const { return m_addr_base; }
dw_addr_t GetRangesBase() const { return m_ranges_base; }
- void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base,
- dw_offset_t base_obj_offset);
+ dw_addr_t GetStrOffsetsBase() const { return m_str_offsets_base; }
+ void SetAddrBase(dw_addr_t addr_base);
+ void SetRangesBase(dw_addr_t ranges_base);
+ void SetBaseObjOffset(dw_offset_t base_obj_offset);
+ void SetStrOffsetsBase(dw_offset_t str_offsets_base);
void BuildAddressRangeTable(SymbolFileDWARF *dwarf,
DWARFDebugAranges *debug_aranges);
@@ -202,6 +205,8 @@ protected:
dw_offset_t m_length = 0;
uint16_t m_version = 0;
uint8_t m_addr_size = 0;
+ uint8_t m_unit_type = 0;
+ uint64_t m_dwo_id = 0;
DWARFProducer m_producer = eProducerInvalid;
uint32_t m_producer_version_major = 0;
uint32_t m_producer_version_minor = 0;
@@ -214,7 +219,7 @@ protected:
// If this is a dwo compile unit this is the offset of the base compile unit
// in the main object file
dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
-
+ dw_offset_t m_str_offsets_base = 0; // Value of DW_AT_str_offsets_base.
// Offset of the initial length field.
dw_offset_t m_offset;
diff --git a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
index 614ff470d161..c043272f8a3e 100644
--- a/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp
@@ -225,7 +225,8 @@ void DebugNamesDWARFIndex::GetFunctions(
const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
std::vector<DWARFDIE> &dies) {
- m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, dies);
+ std::vector<DWARFDIE> v;
+ m_fallback.GetFunctions(name, info, parent_decl_ctx, name_type_mask, v);
for (const DebugNames::Entry &entry :
m_debug_names_up->equal_range(name.GetStringRef())) {
@@ -235,8 +236,13 @@ void DebugNamesDWARFIndex::GetFunctions(
if (DIERef ref = ToDIERef(entry))
ProcessFunctionDIE(name.GetStringRef(), ref, info, parent_decl_ctx,
- name_type_mask, dies);
+ name_type_mask, v);
}
+
+ std::set<DWARFDebugInfoEntry *> seen;
+ for (DWARFDIE die : v)
+ if (seen.insert(die.GetDIE()).second)
+ dies.push_back(die);
}
void DebugNamesDWARFIndex::GetFunctions(const RegularExpression &regex,
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
index 36211a08557e..f83ba6663dfc 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.cpp
@@ -279,7 +279,9 @@ bool DWARFMappedHash::Header::Read(const lldb_private::DWARFDataExtractor &data,
switch (header_data.atoms[i].type) {
case eAtomTypeDIEOffset: // DIE offset, check form for encoding
hash_data.offset =
- (dw_offset_t)form_value.Reference(header_data.die_base_offset);
+ DWARFFormValue::IsDataForm(form_value.Form())
+ ? form_value.Unsigned()
+ : form_value.Reference(header_data.die_base_offset);
break;
case eAtomTypeTag: // DW_TAG value for the DIE
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
index 0293fbd7c495..038e9b8c2b08 100644
--- a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
@@ -10,10 +10,6 @@
#ifndef SymbolFileDWARF_LogChannelDWARF_h_
#define SymbolFileDWARF_LogChannelDWARF_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Log.h"
#define DWARF_LOG_DEBUG_INFO (1u << 1)
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index ac320ac52b08..2a0a89f0b25a 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -9,7 +9,6 @@
#include "SymbolFileDWARF.h"
-// Other libraries and framework includes
#include "llvm/Support/Casting.h"
#include "llvm/Support/Threading.h"
@@ -17,12 +16,12 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
@@ -111,17 +110,14 @@ using namespace lldb_private;
namespace {
-PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"comp-dir-symlink-paths", OptionValue::eTypeFileSpecList, true, 0, nullptr,
- nullptr,
+ {},
"If the DW_AT_comp_dir matches any of these paths the symbolic "
"links will be resolved at DWARF parse time."},
- {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr,
- nullptr,
+ {"ignore-file-indexes", OptionValue::eTypeBoolean, true, 0, nullptr, {},
"Ignore indexes present in the object files and always index DWARF "
- "manually."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr},
-};
+ "manually."}};
enum {
ePropertySymLinkPaths,
@@ -200,7 +196,7 @@ static FileSpec resolveCompDir(const char *path_from_dwarf) {
bool is_symlink = false;
// Always normalize our compile unit directory to get rid of redundant
// slashes and other path anomalies before we use it for path prepending
- FileSpec local_spec(local_path, false);
+ FileSpec local_spec(local_path);
const auto &file_specs = GetGlobalPluginProperties()->GetSymLinkPaths();
for (size_t i = 0; i < file_specs.GetSize() && !is_symlink; ++i)
is_symlink = FileSpec::Equal(file_specs.GetFileSpecAtIndex(i),
@@ -215,7 +211,7 @@ static FileSpec resolveCompDir(const char *path_from_dwarf) {
return local_spec;
FileSpec resolved_symlink;
- const auto error = FileSystem::Readlink(local_spec, resolved_symlink);
+ const auto error = FileSystem::Instance().Readlink(local_spec, resolved_symlink);
if (error.Success())
return resolved_symlink;
@@ -263,6 +259,9 @@ SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFile *obj_file) {
}
TypeList *SymbolFileDWARF::GetTypeList() {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile)
return debug_map_symfile->GetTypeList();
@@ -341,9 +340,10 @@ void SymbolFileDWARF::GetTypes(const DWARFDIE &die, dw_offset_t min_die_offset,
}
size_t SymbolFileDWARF::GetTypes(SymbolContextScope *sc_scope,
- uint32_t type_mask, TypeList &type_list)
+ TypeClass type_mask, TypeList &type_list)
{
+ ASSERT_MODULE_LOCK(this);
TypeSet type_set;
CompileUnit *comp_unit = NULL;
@@ -413,9 +413,9 @@ SymbolFileDWARF::SymbolFileDWARF(ObjectFile *objfile)
m_debug_map_module_wp(), m_debug_map_symfile(NULL), m_data_debug_abbrev(),
m_data_debug_aranges(), m_data_debug_frame(), m_data_debug_info(),
m_data_debug_line(), m_data_debug_macro(), m_data_debug_loc(),
- m_data_debug_ranges(), m_data_debug_str(), m_data_apple_names(),
- m_data_apple_types(), m_data_apple_namespaces(), m_abbr(), m_info(),
- m_line(), m_fetched_external_modules(false),
+ m_data_debug_ranges(), m_data_debug_rnglists(), m_data_debug_str(),
+ m_data_apple_names(), m_data_apple_types(), m_data_apple_namespaces(),
+ m_abbr(), m_info(), m_line(), m_fetched_external_modules(false),
m_supports_DW_AT_APPLE_objc_complete_type(eLazyBoolCalculate), m_ranges(),
m_unique_ast_type_map() {}
@@ -494,7 +494,7 @@ void SymbolFileDWARF::InitializeObject() {
}
bool SymbolFileDWARF::SupportedVersion(uint16_t version) {
- return version == 2 || version == 3 || version == 4;
+ return version >= 2 && version <= 5;
}
uint32_t SymbolFileDWARF::CalculateAbilities() {
@@ -645,19 +645,40 @@ const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_data() {
return GetCachedSectionData(eSectionTypeDWARFDebugLine, m_data_debug_line);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_line_str_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugLineStr, m_data_debug_line_str);
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_debug_macro_data() {
return GetCachedSectionData(eSectionTypeDWARFDebugMacro, m_data_debug_macro);
}
+const DWARFDataExtractor &SymbolFileDWARF::DebugLocData() {
+ const DWARFDataExtractor &debugLocData = get_debug_loc_data();
+ if (debugLocData.GetByteSize() > 0)
+ return debugLocData;
+ return get_debug_loclists_data();
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_debug_loc_data() {
return GetCachedSectionData(eSectionTypeDWARFDebugLoc, m_data_debug_loc);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_loclists_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugLocLists,
+ m_data_debug_loclists);
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_debug_ranges_data() {
return GetCachedSectionData(eSectionTypeDWARFDebugRanges,
m_data_debug_ranges);
}
+const DWARFDataExtractor &SymbolFileDWARF::get_debug_rnglists_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugRngLists,
+ m_data_debug_rnglists);
+}
+
const DWARFDataExtractor &SymbolFileDWARF::get_debug_str_data() {
return GetCachedSectionData(eSectionTypeDWARFDebugStr, m_data_debug_str);
}
@@ -747,21 +768,24 @@ SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit) {
return NULL;
}
-DWARFDebugRanges *SymbolFileDWARF::DebugRanges() {
+DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() {
if (m_ranges.get() == NULL) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "%s this = %p", LLVM_PRETTY_FUNCTION,
static_cast<void *>(this));
- if (get_debug_ranges_data().GetByteSize() > 0) {
+
+ if (get_debug_ranges_data().GetByteSize() > 0)
m_ranges.reset(new DWARFDebugRanges());
- if (m_ranges.get())
- m_ranges->Extract(this);
- }
+ else if (get_debug_rnglists_data().GetByteSize() > 0)
+ m_ranges.reset(new DWARFDebugRngLists());
+
+ if (m_ranges.get())
+ m_ranges->Extract(this);
}
return m_ranges.get();
}
-const DWARFDebugRanges *SymbolFileDWARF::DebugRanges() const {
+const DWARFDebugRangesBase *SymbolFileDWARF::DebugRanges() const {
return m_ranges.get();
}
@@ -786,7 +810,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu,
if (module_sp) {
const DWARFDIE cu_die = dwarf_cu->DIE();
if (cu_die) {
- FileSpec cu_file_spec{cu_die.GetName(), false};
+ FileSpec cu_file_spec(cu_die.GetName());
if (cu_file_spec) {
// If we have a full path to the compile unit, we don't need to
// resolve the file. This can be expensive e.g. when the source
@@ -801,8 +825,7 @@ lldb::CompUnitSP SymbolFileDWARF::ParseCompileUnit(DWARFUnit *dwarf_cu,
std::string remapped_file;
if (module_sp->RemapSourceFile(cu_file_spec.GetPath(),
remapped_file))
- cu_file_spec.SetFile(remapped_file, false,
- FileSpec::Style::native);
+ cu_file_spec.SetFile(remapped_file, FileSpec::Style::native);
}
LanguageType cu_language = DWARFUnit::LanguageTypeFromDWARF(
@@ -851,6 +874,7 @@ uint32_t SymbolFileDWARF::GetNumCompileUnits() {
}
CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
+ ASSERT_MODULE_LOCK(this);
CompUnitSP cu_sp;
DWARFDebugInfo *info = DebugInfo();
if (info) {
@@ -861,8 +885,9 @@ CompUnitSP SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx) {
return cu_sp;
}
-Function *SymbolFileDWARF::ParseCompileUnitFunction(const SymbolContext &sc,
- const DWARFDIE &die) {
+Function *SymbolFileDWARF::ParseFunction(CompileUnit &comp_unit,
+ const DWARFDIE &die) {
+ ASSERT_MODULE_LOCK(this);
if (die.IsValid()) {
TypeSystem *type_system =
GetTypeSystemForLanguage(die.GetCU()->GetLanguageType());
@@ -870,7 +895,7 @@ Function *SymbolFileDWARF::ParseCompileUnitFunction(const SymbolContext &sc,
if (type_system) {
DWARFASTParser *dwarf_ast = type_system->GetDWARFParser();
if (dwarf_ast)
- return dwarf_ast->ParseFunctionFromDWARF(sc, die);
+ return dwarf_ast->ParseFunctionFromDWARF(comp_unit, die);
}
}
return nullptr;
@@ -884,20 +909,19 @@ bool SymbolFileDWARF::FixupAddress(Address &addr) {
// This is a normal DWARF file, no address fixups need to happen
return true;
}
-lldb::LanguageType
-SymbolFileDWARF::ParseCompileUnitLanguage(const SymbolContext &sc) {
- assert(sc.comp_unit);
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+lldb::LanguageType SymbolFileDWARF::ParseLanguage(CompileUnit &comp_unit) {
+ ASSERT_MODULE_LOCK(this);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu)
return dwarf_cu->GetLanguageType();
else
return eLanguageTypeUnknown;
}
-size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
- assert(sc.comp_unit);
+size_t SymbolFileDWARF::ParseFunctions(CompileUnit &comp_unit) {
+ ASSERT_MODULE_LOCK(this);
size_t functions_added = 0;
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu) {
DWARFDIECollection function_dies;
const size_t num_functions =
@@ -905,8 +929,8 @@ size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
size_t func_idx;
for (func_idx = 0; func_idx < num_functions; ++func_idx) {
DWARFDIE die = function_dies.GetDIEAtIndex(func_idx);
- if (sc.comp_unit->FindFunctionByUID(die.GetID()).get() == NULL) {
- if (ParseCompileUnitFunction(sc, die))
+ if (comp_unit.FindFunctionByUID(die.GetID()).get() == NULL) {
+ if (ParseFunction(comp_unit, die))
++functions_added;
}
}
@@ -915,10 +939,10 @@ size_t SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc) {
return functions_added;
}
-bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
- const SymbolContext &sc, FileSpecList &support_files) {
- assert(sc.comp_unit);
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+bool SymbolFileDWARF::ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) {
+ ASSERT_MODULE_LOCK(this);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu) {
const DWARFBaseDIE cu_die = dwarf_cu->GetUnitDIEOnly();
@@ -930,19 +954,19 @@ bool SymbolFileDWARF::ParseCompileUnitSupportFiles(
if (stmt_list != DW_INVALID_OFFSET) {
// All file indexes in DWARF are one based and a file of index zero is
// supposed to be the compile unit itself.
- support_files.Append(*sc.comp_unit);
+ support_files.Append(comp_unit);
return DWARFDebugLine::ParseSupportFiles(
- sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir,
- stmt_list, support_files);
+ comp_unit.GetModule(), get_debug_line_data(), cu_comp_dir,
+ stmt_list, support_files, dwarf_cu);
}
}
}
return false;
}
-bool SymbolFileDWARF::ParseCompileUnitIsOptimized(
- const lldb_private::SymbolContext &sc) {
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+bool SymbolFileDWARF::ParseIsOptimized(CompileUnit &comp_unit) {
+ ASSERT_MODULE_LOCK(this);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu)
return dwarf_cu->GetIsOptimized();
return false;
@@ -951,6 +975,7 @@ bool SymbolFileDWARF::ParseCompileUnitIsOptimized(
bool SymbolFileDWARF::ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) {
+ ASSERT_MODULE_LOCK(this);
assert(sc.comp_unit);
DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
if (dwarf_cu) {
@@ -1027,12 +1052,12 @@ static void ParseDWARFLineTableCallback(dw_offset_t offset,
}
}
-bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
- assert(sc.comp_unit);
- if (sc.comp_unit->GetLineTable() != NULL)
+bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
+ ASSERT_MODULE_LOCK(this);
+ if (comp_unit.GetLineTable() != NULL)
return true;
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu) {
const DWARFBaseDIE dwarf_cu_die = dwarf_cu->GetUnitDIEOnly();
if (dwarf_cu_die) {
@@ -1040,7 +1065,7 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
dwarf_cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list,
DW_INVALID_OFFSET);
if (cu_line_offset != DW_INVALID_OFFSET) {
- std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
+ std::unique_ptr<LineTable> line_table_ap(new LineTable(&comp_unit));
if (line_table_ap.get()) {
ParseDWARFLineTableCallbackInfo info;
info.line_table = line_table_ap.get();
@@ -1053,9 +1078,7 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
* #0
* for MIPS. Use ArchSpec to clear the bit #0.
*/
- ArchSpec arch;
- GetObjectFile()->GetArchitecture(arch);
- switch (arch.GetMachine()) {
+ switch (GetObjectFile()->GetArchitecture().GetMachine()) {
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
@@ -1070,17 +1093,17 @@ bool SymbolFileDWARF::ParseCompileUnitLineTable(const SymbolContext &sc) {
lldb::offset_t offset = cu_line_offset;
DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset,
ParseDWARFLineTableCallback,
- &info);
+ &info, dwarf_cu);
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
if (debug_map_symfile) {
// We have an object file that has a line table with addresses that
// are not linked. We need to link the line table and convert the
// addresses that are relative to the .o file into addresses for
// the main executable.
- sc.comp_unit->SetLineTable(
+ comp_unit.SetLineTable(
debug_map_symfile->LinkOSOLineTable(this, line_table_ap.get()));
} else {
- sc.comp_unit->SetLineTable(line_table_ap.release());
+ comp_unit.SetLineTable(line_table_ap.release());
return true;
}
}
@@ -1112,10 +1135,10 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) {
return debug_macros_sp;
}
-bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
- assert(sc.comp_unit);
+bool SymbolFileDWARF::ParseDebugMacros(CompileUnit &comp_unit) {
+ ASSERT_MODULE_LOCK(this);
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu == nullptr)
return false;
@@ -1131,16 +1154,14 @@ bool SymbolFileDWARF::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
if (sect_offset == DW_INVALID_OFFSET)
return false;
- sc.comp_unit->SetDebugMacros(ParseDebugMacros(&sect_offset));
+ comp_unit.SetDebugMacros(ParseDebugMacros(&sect_offset));
return true;
}
-size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
- Block *parent_block,
- const DWARFDIE &orig_die,
- addr_t subprogram_low_pc,
- uint32_t depth) {
+size_t SymbolFileDWARF::ParseBlocksRecursive(
+ lldb_private::CompileUnit &comp_unit, Block *parent_block,
+ const DWARFDIE &orig_die, addr_t subprogram_low_pc, uint32_t depth) {
size_t blocks_added = 0;
DWARFDIE die = orig_die;
while (die) {
@@ -1219,13 +1240,13 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
std::unique_ptr<Declaration> decl_ap;
if (decl_file != 0 || decl_line != 0 || decl_column != 0)
decl_ap.reset(new Declaration(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
+ comp_unit.GetSupportFiles().GetFileSpecAtIndex(decl_file),
decl_line, decl_column));
std::unique_ptr<Declaration> call_ap;
if (call_file != 0 || call_line != 0 || call_column != 0)
call_ap.reset(new Declaration(
- sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file),
+ comp_unit.GetSupportFiles().GetFileSpecAtIndex(call_file),
call_line, call_column));
block->SetInlinedFunctionInfo(name, mangled_name, decl_ap.get(),
@@ -1235,8 +1256,9 @@ size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc,
++blocks_added;
if (die.HasChildren()) {
- blocks_added += ParseFunctionBlocks(sc, block, die.GetFirstChild(),
- subprogram_low_pc, depth + 1);
+ blocks_added +=
+ ParseBlocksRecursive(comp_unit, block, die.GetFirstChild(),
+ subprogram_low_pc, depth + 1);
}
}
} break;
@@ -1292,6 +1314,9 @@ void SymbolFileDWARF::ParseDeclsForContext(CompilerDeclContext decl_ctx) {
}
SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
// must make sure we use the correct DWARF file when resolving things. On
// MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
@@ -1308,6 +1333,9 @@ SymbolFileDWARF *SymbolFileDWARF::GetDWARFForUID(lldb::user_id_t uid) {
DWARFDIE
SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Anytime we get a "lldb::user_id_t" from an lldb_private::SymbolFile API we
// must make sure we use the correct DWARF file when resolving things. On
// MacOSX, when using SymbolFileDWARFDebugMap, we will use multiple
@@ -1322,6 +1350,9 @@ SymbolFileDWARF::GetDIEFromUID(lldb::user_id_t uid) {
}
CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Anytime we have a lldb::user_id_t, we must get the DIE by calling
// SymbolFileDWARF::GetDIEFromUID(). See comments inside the
// SymbolFileDWARF::GetDIEFromUID() for details.
@@ -1333,6 +1364,9 @@ CompilerDecl SymbolFileDWARF::GetDeclForUID(lldb::user_id_t type_uid) {
CompilerDeclContext
SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Anytime we have a lldb::user_id_t, we must get the DIE by calling
// SymbolFileDWARF::GetDIEFromUID(). See comments inside the
// SymbolFileDWARF::GetDIEFromUID() for details.
@@ -1344,6 +1378,9 @@ SymbolFileDWARF::GetDeclContextForUID(lldb::user_id_t type_uid) {
CompilerDeclContext
SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Anytime we have a lldb::user_id_t, we must get the DIE by calling
// SymbolFileDWARF::GetDIEFromUID(). See comments inside the
// SymbolFileDWARF::GetDIEFromUID() for details.
@@ -1354,6 +1391,9 @@ SymbolFileDWARF::GetDeclContextContainingUID(lldb::user_id_t type_uid) {
}
Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
+ // This method can be called without going through the symbol vendor so we
+ // need to lock the module.
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
// Anytime we have a lldb::user_id_t, we must get the DIE by calling
// SymbolFileDWARF::GetDIEFromUID(). See comments inside the
// SymbolFileDWARF::GetDIEFromUID() for details.
@@ -1364,6 +1404,17 @@ Type *SymbolFileDWARF::ResolveTypeUID(lldb::user_id_t type_uid) {
return nullptr;
}
+llvm::Optional<SymbolFile::ArrayInfo>
+SymbolFileDWARF::GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ DWARFDIE type_die = GetDIEFromUID(type_uid);
+ if (type_die)
+ return DWARFASTParser::ParseChildArrayInfo(type_die, exe_ctx);
+ else
+ return llvm::None;
+}
+
Type *SymbolFileDWARF::ResolveTypeUID(const DIERef &die_ref) {
return ResolveType(GetDIE(die_ref), true);
}
@@ -1429,8 +1480,7 @@ bool SymbolFileDWARF::HasForwardDeclForClangType(
}
bool SymbolFileDWARF::CompleteType(CompilerType &compiler_type) {
- std::lock_guard<std::recursive_mutex> guard(
- GetObjectFile()->GetModule()->GetMutex());
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
ClangASTContext *clang_type_system =
llvm::dyn_cast_or_null<ClangASTContext>(compiler_type.GetTypeSystem());
@@ -1525,7 +1575,7 @@ bool SymbolFileDWARF::GetFunction(const DWARFDIE &die, SymbolContext &sc) {
sc.function = sc.comp_unit->FindFunctionByUID(die.GetID()).get();
if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, die);
+ sc.function = ParseFunction(*sc.comp_unit, die);
if (sc.function) {
sc.module_sp = sc.function->CalculateSymbolContextModule();
@@ -1578,18 +1628,20 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
return dwo_symfile;
}
- FileSpec dwo_file(dwo_name, true);
+ FileSpec dwo_file(dwo_name);
+ FileSystem::Instance().Resolve(dwo_file);
if (dwo_file.IsRelative()) {
const char *comp_dir = cu_die.GetAttributeValueAsString(
this, &dwarf_cu, DW_AT_comp_dir, nullptr);
if (!comp_dir)
return nullptr;
- dwo_file.SetFile(comp_dir, true, FileSpec::Style::native);
+ dwo_file.SetFile(comp_dir, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dwo_file);
dwo_file.AppendPathComponent(dwo_name);
}
- if (!dwo_file.Exists())
+ if (!FileSystem::Instance().Exists(dwo_file))
return nullptr;
const lldb::offset_t file_offset = 0;
@@ -1597,7 +1649,8 @@ SymbolFileDWARF::GetDwoSymbolFileForCompileUnit(
lldb::offset_t dwo_file_data_offset = 0;
ObjectFileSP dwo_obj_file = ObjectFile::FindPlugin(
GetObjectFile()->GetModule(), &dwo_file, file_offset,
- dwo_file.GetByteSize(), dwo_file_data_sp, dwo_file_data_offset);
+ FileSystem::Instance().GetByteSize(dwo_file), dwo_file_data_sp,
+ dwo_file_data_offset);
if (dwo_obj_file == nullptr)
return nullptr;
@@ -1616,7 +1669,7 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
DWARFUnit *dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
const DWARFBaseDIE die = dwarf_cu->GetUnitDIEOnly();
- if (die && die.HasChildren() == false) {
+ if (die && !die.HasChildren()) {
const char *name = die.GetAttributeValueAsString(DW_AT_name, nullptr);
if (name) {
@@ -1628,14 +1681,15 @@ void SymbolFileDWARF::UpdateExternalModuleListIfNeeded() {
die.GetAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
if (dwo_path) {
ModuleSpec dwo_module_spec;
- dwo_module_spec.GetFileSpec().SetFile(dwo_path, false,
+ dwo_module_spec.GetFileSpec().SetFile(dwo_path,
FileSpec::Style::native);
if (dwo_module_spec.GetFileSpec().IsRelative()) {
const char *comp_dir =
die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr);
if (comp_dir) {
- dwo_module_spec.GetFileSpec().SetFile(comp_dir, true,
+ dwo_module_spec.GetFileSpec().SetFile(comp_dir,
FileSpec::Style::native);
+ FileSystem::Instance().Resolve(dwo_module_spec.GetFileSpec());
dwo_module_spec.GetFileSpec().AppendPathComponent(dwo_path);
}
}
@@ -1726,7 +1780,7 @@ SymbolFileDWARF::GlobalVariableMap &SymbolFileDWARF::GetGlobalAranges() {
}
uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
- uint32_t resolve_scope,
+ SymbolContextItem resolve_scope,
SymbolContext &sc) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat,
@@ -1784,7 +1838,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
sc.function =
sc.comp_unit->FindFunctionByUID(function_die.GetID()).get();
if (sc.function == NULL)
- sc.function = ParseCompileUnitFunction(sc, function_die);
+ sc.function = ParseFunction(*sc.comp_unit, function_die);
if (sc.function && (resolve_scope & eSymbolContextBlock))
block_die = function_die.LookupDeepestBlock(file_vm_addr);
@@ -1860,7 +1914,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const Address &so_addr,
uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line,
bool check_inlines,
- uint32_t resolve_scope,
+ SymbolContextItem resolve_scope,
SymbolContextList &sc_list) {
const uint32_t prev_size = sc_list.GetSize();
if (resolve_scope & eSymbolContextCompUnit) {
@@ -1925,7 +1979,7 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
.get();
if (sc.function == NULL)
sc.function =
- ParseCompileUnitFunction(sc, function_die);
+ ParseFunction(*sc.comp_unit, function_die);
if (sc.function &&
(resolve_scope & eSymbolContextBlock))
@@ -1975,11 +2029,17 @@ uint32_t SymbolFileDWARF::ResolveSymbolContext(const FileSpec &file_spec,
}
void SymbolFileDWARF::PreloadSymbols() {
- std::lock_guard<std::recursive_mutex> guard(
- GetObjectFile()->GetModule()->GetMutex());
+ std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
m_index->Preload();
}
+std::recursive_mutex &SymbolFileDWARF::GetModuleMutex() const {
+ lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
+ if (module_sp)
+ return module_sp->GetMutex();
+ return GetObjectFile()->GetModule()->GetMutex();
+}
+
bool SymbolFileDWARF::DeclContextMatchesThisSymbolFile(
const lldb_private::CompilerDeclContext *decl_ctx) {
if (decl_ctx == nullptr || !decl_ctx->IsValid()) {
@@ -2195,7 +2255,7 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
sc.block = function_block.FindBlockByID(inlined_die.GetID());
if (sc.block == NULL)
sc.block = function_block.FindBlockByID(inlined_die.GetOffset());
- if (sc.block == NULL || sc.block->GetStartAddress(addr) == false)
+ if (sc.block == NULL || !sc.block->GetStartAddress(addr))
addr.Clear();
} else {
sc.block = NULL;
@@ -2231,11 +2291,10 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx,
return false;
}
-uint32_t
-SymbolFileDWARF::FindFunctions(const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines,
- bool append, SymbolContextList &sc_list) {
+uint32_t SymbolFileDWARF::FindFunctions(
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ FunctionNameType name_type_mask, bool include_inlines, bool append,
+ SymbolContextList &sc_list) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat, "SymbolFileDWARF::FindFunctions (name = '%s')",
name.AsCString());
@@ -2378,9 +2437,8 @@ void SymbolFileDWARF::GetMangledNamesForFunction(
}
uint32_t SymbolFileDWARF::FindTypes(
- const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
- uint32_t max_matches,
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
// If we aren't appending the results to this list, then clear the list
@@ -2469,8 +2527,8 @@ uint32_t SymbolFileDWARF::FindTypes(
SymbolVendor *sym_vendor = external_module_sp->GetSymbolVendor();
if (sym_vendor) {
const uint32_t num_external_matches =
- sym_vendor->FindTypes(sc, name, parent_decl_ctx, append,
- max_matches, searched_symbol_files, types);
+ sym_vendor->FindTypes(name, parent_decl_ctx, append, max_matches,
+ searched_symbol_files, types);
if (num_external_matches)
return num_external_matches;
}
@@ -2506,7 +2564,7 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
if (die) {
std::vector<CompilerContext> die_context;
- die.GetDWOContext(die_context);
+ die.GetDeclContext(die_context);
if (die_context != context)
continue;
@@ -2528,7 +2586,7 @@ size_t SymbolFileDWARF::FindTypes(const std::vector<CompilerContext> &context,
}
CompilerDeclContext
-SymbolFileDWARF::FindNamespace(const SymbolContext &sc, const ConstString &name,
+SymbolFileDWARF::FindNamespace(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx) {
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
@@ -3065,39 +3123,36 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc,
return types_added;
}
-size_t SymbolFileDWARF::ParseFunctionBlocks(const SymbolContext &sc) {
- assert(sc.comp_unit && sc.function);
+size_t SymbolFileDWARF::ParseBlocksRecursive(Function &func) {
+ ASSERT_MODULE_LOCK(this);
+ CompileUnit *comp_unit = func.GetCompileUnit();
+ lldbassert(comp_unit);
+
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(comp_unit);
+ if (!dwarf_cu)
+ return 0;
+
size_t functions_added = 0;
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
- if (dwarf_cu) {
- const dw_offset_t function_die_offset = sc.function->GetID();
- DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset);
- if (function_die) {
- ParseFunctionBlocks(sc, &sc.function->GetBlock(false), function_die,
- LLDB_INVALID_ADDRESS, 0);
- }
+ const dw_offset_t function_die_offset = func.GetID();
+ DWARFDIE function_die = dwarf_cu->GetDIE(function_die_offset);
+ if (function_die) {
+ ParseBlocksRecursive(*comp_unit, &func.GetBlock(false), function_die,
+ LLDB_INVALID_ADDRESS, 0);
}
return functions_added;
}
-size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) {
- // At least a compile unit must be valid
- assert(sc.comp_unit);
+size_t SymbolFileDWARF::ParseTypes(CompileUnit &comp_unit) {
+ ASSERT_MODULE_LOCK(this);
size_t types_added = 0;
- DWARFUnit *dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+ DWARFUnit *dwarf_cu = GetDWARFCompileUnit(&comp_unit);
if (dwarf_cu) {
- if (sc.function) {
- dw_offset_t function_die_offset = sc.function->GetID();
- DWARFDIE func_die = dwarf_cu->GetDIE(function_die_offset);
- if (func_die && func_die.HasChildren()) {
- types_added = ParseTypes(sc, func_die.GetFirstChild(), true, true);
- }
- } else {
- DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
- if (dwarf_cu_die && dwarf_cu_die.HasChildren()) {
- types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
- }
+ DWARFDIE dwarf_cu_die = dwarf_cu->DIE();
+ if (dwarf_cu_die && dwarf_cu_die.HasChildren()) {
+ SymbolContext sc;
+ sc.comp_unit = &comp_unit;
+ types_added = ParseTypes(sc, dwarf_cu_die.GetFirstChild(), true, true);
}
}
@@ -3105,6 +3160,7 @@ size_t SymbolFileDWARF::ParseTypes(const SymbolContext &sc) {
}
size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) {
+ ASSERT_MODULE_LOCK(this);
if (sc.comp_unit != NULL) {
DWARFDebugInfo *info = DebugInfo();
if (info == NULL)
@@ -3298,7 +3354,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
uint32_t block_length = form_value.Unsigned();
location.CopyOpcodeData(module, data, block_offset, block_length);
} else {
- const DWARFDataExtractor &debug_loc_data = get_debug_loc_data();
+ const DWARFDataExtractor &debug_loc_data = DebugLocData();
const dw_offset_t debug_loc_offset = form_value.Unsigned();
size_t loc_list_length = DWARFExpression::LocationListSize(
@@ -3319,22 +3375,10 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
case DW_AT_start_scope: {
if (form_value.Form() == DW_FORM_sec_offset) {
DWARFRangeList dwarf_scope_ranges;
- const DWARFDebugRanges *debug_ranges = DebugRanges();
- debug_ranges->FindRanges(die.GetCU()->GetRangesBase(),
+ const DWARFDebugRangesBase *debug_ranges = DebugRanges();
+ debug_ranges->FindRanges(die.GetCU(),
form_value.Unsigned(),
dwarf_scope_ranges);
-
- // All DW_AT_start_scope are relative to the base address of the
- // compile unit. We add the compile unit base address to make
- // sure all the addresses are properly fixed up.
- for (size_t i = 0, count = dwarf_scope_ranges.GetSize();
- i < count; ++i) {
- const DWARFRangeList::Entry &range =
- dwarf_scope_ranges.GetEntryRef(i);
- scope_ranges.Append(range.GetRangeBase() +
- die.GetCU()->GetBaseAddress(),
- range.GetByteSize());
- }
} else {
// TODO: Handle the case when DW_AT_start_scope have form
// constant. The
@@ -3436,6 +3480,11 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
is_static_lifetime = true;
}
SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
+ if (debug_map_symfile)
+ // Set the module of the expression to the linked module
+ // instead of the oject file so the relocated address can be
+ // found there.
+ location.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
if (is_static_lifetime) {
if (is_external)
@@ -3736,6 +3785,60 @@ size_t SymbolFileDWARF::ParseVariables(const SymbolContext &sc,
return vars_added;
}
+/// Collect call graph edges present in a function DIE.
+static std::vector<lldb_private::CallEdge>
+CollectCallEdges(DWARFDIE function_die) {
+ // Check if the function has a supported call site-related attribute.
+ // TODO: In the future it may be worthwhile to support call_all_source_calls.
+ uint64_t has_call_edges =
+ function_die.GetAttributeValueAsUnsigned(DW_AT_call_all_calls, 0);
+ if (!has_call_edges)
+ return {};
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ LLDB_LOG(log, "CollectCallEdges: Found call site info in {0}",
+ function_die.GetPubname());
+
+ // Scan the DIE for TAG_call_site entries.
+ // TODO: A recursive scan of all blocks in the subprogram is needed in order
+ // to be DWARF5-compliant. This may need to be done lazily to be performant.
+ // For now, assume that all entries are nested directly under the subprogram
+ // (this is the kind of DWARF LLVM produces) and parse them eagerly.
+ std::vector<CallEdge> call_edges;
+ for (DWARFDIE child = function_die.GetFirstChild(); child.IsValid();
+ child = child.GetSibling()) {
+ if (child.Tag() != DW_TAG_call_site)
+ continue;
+
+ // Extract DW_AT_call_origin (the call target's DIE).
+ DWARFDIE call_origin = child.GetReferencedDIE(DW_AT_call_origin);
+ if (!call_origin.IsValid()) {
+ LLDB_LOG(log, "CollectCallEdges: Invalid call origin in {0}",
+ function_die.GetPubname());
+ continue;
+ }
+
+ // Extract DW_AT_call_return_pc (the PC the call returns to) if it's
+ // available. It should only ever be unavailable for tail call edges, in
+ // which case use LLDB_INVALID_ADDRESS.
+ addr_t return_pc = child.GetAttributeValueAsAddress(DW_AT_call_return_pc,
+ LLDB_INVALID_ADDRESS);
+
+ LLDB_LOG(log, "CollectCallEdges: Found call origin: {0} (retn-PC: {1:x})",
+ call_origin.GetPubname(), return_pc);
+ call_edges.emplace_back(call_origin.GetMangledName(), return_pc);
+ }
+ return call_edges;
+}
+
+std::vector<lldb_private::CallEdge>
+SymbolFileDWARF::ParseCallEdgesInFunction(UserID func_id) {
+ DWARFDIE func_die = GetDIEFromUID(func_id.GetID());
+ if (func_die.IsValid())
+ return CollectCallEdges(func_die);
+ return {};
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -3745,6 +3848,14 @@ uint32_t SymbolFileDWARF::GetPluginVersion() { return 1; }
void SymbolFileDWARF::Dump(lldb_private::Stream &s) { m_index->Dump(s); }
+void SymbolFileDWARF::DumpClangAST(Stream &s) {
+ TypeSystem *ts = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus);
+ ClangASTContext *clang = llvm::dyn_cast_or_null<ClangASTContext>(ts);
+ if (!clang)
+ return;
+ clang->Dump(s);
+}
+
SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired()) {
lldb::ModuleSP module_sp(m_debug_map_module_wp.lock());
@@ -3760,6 +3871,8 @@ SymbolFileDWARFDebugMap *SymbolFileDWARF::GetDebugMapSymfile() {
DWARFExpression::LocationListFormat
SymbolFileDWARF::GetLocationListFormat() const {
+ if (m_data_debug_loclists.m_data.GetByteSize() > 0)
+ return DWARFExpression::LocLists;
return DWARFExpression::RegularLocationList;
}
@@ -3768,9 +3881,9 @@ SymbolFileDWARFDwp *SymbolFileDWARF::GetDwpSymbolFile() {
ModuleSpec module_spec;
module_spec.GetFileSpec() = m_obj_file->GetFileSpec();
module_spec.GetSymbolFileSpec() =
- FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp", false);
+ FileSpec(m_obj_file->GetFileSpec().GetPath() + ".dwp");
FileSpec dwp_filespec = Symbols::LocateExecutableSymbolFile(module_spec);
- if (dwp_filespec.Exists()) {
+ if (FileSystem::Instance().Exists(dwp_filespec)) {
m_dwp_symfile = SymbolFileDWARFDwp::Create(GetObjectFile()->GetModule(),
dwp_filespec);
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index a5f2ac8f3e7d..d351289f8b51 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -10,8 +10,6 @@
#ifndef SymbolFileDWARF_SymbolFileDWARF_h_
#define SymbolFileDWARF_SymbolFileDWARF_h_
-// C Includes
-// C++ Includes
#include <list>
#include <map>
#include <mutex>
@@ -19,7 +17,6 @@
#include <unordered_map>
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/Threading.h"
@@ -35,7 +32,6 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/lldb-private.h"
-// Project includes
#include "DWARFDataExtractor.h"
#include "DWARFDefines.h"
#include "DWARFIndex.h"
@@ -53,7 +49,7 @@ class DWARFDebugAranges;
class DWARFDebugInfo;
class DWARFDebugInfoEntry;
class DWARFDebugLine;
-class DWARFDebugRanges;
+class DWARFDebugRangesBase;
class DWARFDeclContext;
class DWARFDIECollection;
class DWARFFormValue;
@@ -73,9 +69,6 @@ public:
friend class DWARFUnit;
friend class DWARFDIE;
friend class DWARFASTParserClang;
- friend class DWARFASTParserGo;
- friend class DWARFASTParserJava;
- friend class DWARFASTParserOCaml;
//------------------------------------------------------------------
// Static Functions
@@ -114,36 +107,34 @@ public:
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
lldb::LanguageType
- ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override;
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
- size_t
- ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override;
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
- bool
- ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override;
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
- bool
- ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override;
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- bool ParseCompileUnitSupportFiles(
- const lldb_private::SymbolContext &sc,
- lldb_private::FileSpecList &support_files) override;
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ lldb_private::FileSpecList &support_files) override;
- bool
- ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) override;
+ bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override;
+
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
bool ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) override;
- size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override;
-
- size_t ParseTypes(const lldb_private::SymbolContext &sc) override;
+ size_t ParseBlocksRecursive(lldb_private::Function &func) override;
size_t
ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
bool CompleteType(lldb_private::CompilerType &compiler_type) override;
@@ -168,12 +159,13 @@ public:
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;
uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
uint32_t
ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines, uint32_t resolve_scope,
+ bool check_inlines,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContextList &sc_list) override;
uint32_t
@@ -189,8 +181,8 @@ public:
uint32_t
FindFunctions(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines, bool append,
- lldb_private::SymbolContextList &sc_list) override;
+ lldb::FunctionNameType name_type_mask, bool include_inlines,
+ bool append, lldb_private::SymbolContextList &sc_list) override;
uint32_t FindFunctions(const lldb_private::RegularExpression &regex,
bool include_inlines, bool append,
@@ -201,8 +193,7 @@ public:
std::vector<lldb_private::ConstString> &mangled_names) override;
uint32_t
- FindTypes(const lldb_private::SymbolContext &sc,
- const lldb_private::ConstString &name,
+ FindTypes(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
@@ -214,19 +205,20 @@ public:
lldb_private::TypeList *GetTypeList() override;
size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override;
lldb_private::TypeSystem *
GetTypeSystemForLanguage(lldb::LanguageType language) override;
lldb_private::CompilerDeclContext FindNamespace(
- const lldb_private::SymbolContext &sc,
const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
void PreloadSymbols() override;
+ std::recursive_mutex &GetModuleMutex() const override;
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -234,17 +226,20 @@ public:
uint32_t GetPluginVersion() override;
- const lldb_private::DWARFDataExtractor &get_debug_abbrev_data();
- const lldb_private::DWARFDataExtractor &get_debug_addr_data();
+ virtual const lldb_private::DWARFDataExtractor &get_debug_abbrev_data();
+ virtual const lldb_private::DWARFDataExtractor &get_debug_addr_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();
+ virtual const lldb_private::DWARFDataExtractor &get_debug_info_data();
const lldb_private::DWARFDataExtractor &get_debug_line_data();
+ const lldb_private::DWARFDataExtractor &get_debug_line_str_data();
const lldb_private::DWARFDataExtractor &get_debug_macro_data();
const lldb_private::DWARFDataExtractor &get_debug_loc_data();
+ const lldb_private::DWARFDataExtractor &get_debug_loclists_data();
const lldb_private::DWARFDataExtractor &get_debug_ranges_data();
- const lldb_private::DWARFDataExtractor &get_debug_str_data();
- const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
+ const lldb_private::DWARFDataExtractor &get_debug_rnglists_data();
+ virtual const lldb_private::DWARFDataExtractor &get_debug_str_data();
+ virtual const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data();
const lldb_private::DWARFDataExtractor &get_debug_types_data();
const lldb_private::DWARFDataExtractor &get_apple_names_data();
const lldb_private::DWARFDataExtractor &get_apple_types_data();
@@ -260,9 +255,11 @@ public:
const DWARFDebugInfo *DebugInfo() const;
- DWARFDebugRanges *DebugRanges();
+ DWARFDebugRangesBase *DebugRanges();
- const DWARFDebugRanges *DebugRanges() const;
+ const DWARFDebugRangesBase *DebugRanges() const;
+
+ const lldb_private::DWARFDataExtractor &DebugLocData();
static bool SupportedVersion(uint16_t version);
@@ -316,8 +313,13 @@ public:
DIEInDeclContext(const lldb_private::CompilerDeclContext *parent_decl_ctx,
const DWARFDIE &die);
+ std::vector<lldb_private::CallEdge>
+ ParseCallEdgesInFunction(UserID func_id) override;
+
void Dump(lldb_private::Stream &s) override;
+ void DumpClangAST(lldb_private::Stream &s) override;
+
protected:
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
DIEToTypePtr;
@@ -352,14 +354,13 @@ protected:
bool GetFunction(const DWARFDIE &die, lldb_private::SymbolContext &sc);
- lldb_private::Function *
- ParseCompileUnitFunction(const lldb_private::SymbolContext &sc,
- const DWARFDIE &die);
+ lldb_private::Function *ParseFunction(lldb_private::CompileUnit &comp_unit,
+ const DWARFDIE &die);
- size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc,
- lldb_private::Block *parent_block,
- const DWARFDIE &die,
- lldb::addr_t subprogram_low_pc, uint32_t depth);
+ size_t ParseBlocksRecursive(lldb_private::CompileUnit &comp_unit,
+ lldb_private::Block *parent_block,
+ const DWARFDIE &die,
+ lldb::addr_t subprogram_low_pc, uint32_t depth);
size_t ParseTypes(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
bool parse_siblings, bool parse_children);
@@ -466,9 +467,12 @@ protected:
DWARFDataSegment m_data_debug_frame;
DWARFDataSegment m_data_debug_info;
DWARFDataSegment m_data_debug_line;
+ DWARFDataSegment m_data_debug_line_str;
DWARFDataSegment m_data_debug_macro;
DWARFDataSegment m_data_debug_loc;
+ DWARFDataSegment m_data_debug_loclists;
DWARFDataSegment m_data_debug_ranges;
+ DWARFDataSegment m_data_debug_rnglists;
DWARFDataSegment m_data_debug_str;
DWARFDataSegment m_data_debug_str_offsets;
DWARFDataSegment m_data_debug_types;
@@ -498,7 +502,7 @@ protected:
typedef std::shared_ptr<std::set<DIERef>> DIERefSetSP;
typedef std::unordered_map<std::string, DIERefSetSP> NameToOffsetMap;
NameToOffsetMap m_function_scope_qualified_name_map;
- std::unique_ptr<DWARFDebugRanges> m_ranges;
+ std::unique_ptr<DWARFDebugRangesBase> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
DIEToTypePtr m_die_to_type;
DIEToVariableSP m_die_to_variable_sp;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 39c70d146524..2c1e6416a935 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "SymbolFileDWARFDebugMap.h"
#include "DWARFDebugAranges.h"
@@ -90,11 +86,10 @@ SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(
const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
for (uint32_t idx = comp_unit_info->first_symbol_index +
2; // Skip the N_SO and N_OSO
- idx < oso_end_idx;
- ++idx) {
+ idx < oso_end_idx; ++idx) {
Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
if (exe_symbol) {
- if (exe_symbol->IsDebug() == false)
+ if (!exe_symbol->IsDebug())
continue;
switch (exe_symbol->GetType()) {
@@ -184,7 +179,7 @@ public:
GetSymbolVendor(bool can_create = true,
lldb_private::Stream *feedback_strm = NULL) override {
// Scope for locker
- if (m_symfile_ap.get() || can_create == false)
+ if (m_symfile_ap.get() || !can_create)
return m_symfile_ap.get();
ModuleSP exe_module_sp(m_exe_module_wp.lock());
@@ -351,7 +346,7 @@ void SymbolFileDWARFDebugMap::InitOSO() {
so_symbol->GetType() == eSymbolTypeSourceFile &&
oso_symbol->GetType() == eSymbolTypeObjectFile) {
m_compile_unit_infos[i].so_file.SetFile(
- so_symbol->GetName().AsCString(), false, FileSpec::Style::native);
+ so_symbol->GetName().AsCString(), FileSpec::Style::native);
m_compile_unit_infos[i].oso_path = oso_symbol->GetName();
m_compile_unit_infos[i].oso_mod_time =
llvm::sys::toTimePoint(oso_symbol->GetIntegerValue(0));
@@ -421,10 +416,13 @@ Module *SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo(
m_oso_map[{comp_unit_info->oso_path, comp_unit_info->oso_mod_time}] =
comp_unit_info->oso_sp;
const char *oso_path = comp_unit_info->oso_path.GetCString();
- FileSpec oso_file(oso_path, false);
+ FileSpec oso_file(oso_path);
ConstString oso_object;
- if (oso_file.Exists()) {
- auto oso_mod_time = FileSystem::GetModificationTime(oso_file);
+ if (FileSystem::Instance().Exists(oso_file)) {
+ // The modification time returned by the FS can have a higher precision
+ // than the one from the CU.
+ auto oso_mod_time = std::chrono::time_point_cast<std::chrono::seconds>(
+ FileSystem::Instance().GetModificationTime(oso_file));
if (oso_mod_time != comp_unit_info->oso_mod_time) {
obj_file->GetModule()->ReportError(
"debug map object file '%s' has changed (actual time is "
@@ -490,7 +488,12 @@ ObjectFile *SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex(uint32_t oso_idx) {
SymbolFileDWARF *
SymbolFileDWARFDebugMap::GetSymbolFile(const SymbolContext &sc) {
- CompileUnitInfo *comp_unit_info = GetCompUnitInfo(sc);
+ return GetSymbolFile(*sc.comp_unit);
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFile(const CompileUnit &comp_unit) {
+ CompileUnitInfo *comp_unit_info = GetCompUnitInfo(comp_unit);
if (comp_unit_info)
return GetSymbolFileByCompUnitInfo(comp_unit_info);
return NULL;
@@ -518,7 +521,8 @@ uint32_t SymbolFileDWARFDebugMap::GetCompUnitInfoIndex(
SymbolFileDWARF *
SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex(uint32_t oso_idx) {
- if (oso_idx < m_compile_unit_infos.size())
+ unsigned size = m_compile_unit_infos.size();
+ if (oso_idx < size)
return GetSymbolFileByCompUnitInfo(&m_compile_unit_infos[oso_idx]);
return NULL;
}
@@ -597,9 +601,14 @@ CompUnitSP SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx) {
SymbolFileDWARFDebugMap::CompileUnitInfo *
SymbolFileDWARFDebugMap::GetCompUnitInfo(const SymbolContext &sc) {
+ return GetCompUnitInfo(*sc.comp_unit);
+}
+
+SymbolFileDWARFDebugMap::CompileUnitInfo *
+SymbolFileDWARFDebugMap::GetCompUnitInfo(const CompileUnit &comp_unit) {
const uint32_t cu_count = GetNumCompileUnits();
for (uint32_t i = 0; i < cu_count; ++i) {
- if (sc.comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
+ if (comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
return &m_compile_unit_infos[i];
}
return NULL;
@@ -617,50 +626,46 @@ size_t SymbolFileDWARFDebugMap::GetCompUnitInfosForModule(
}
lldb::LanguageType
-SymbolFileDWARFDebugMap::ParseCompileUnitLanguage(const SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+SymbolFileDWARFDebugMap::ParseLanguage(CompileUnit &comp_unit) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseCompileUnitLanguage(sc);
+ return oso_dwarf->ParseLanguage(comp_unit);
return eLanguageTypeUnknown;
}
-size_t
-SymbolFileDWARFDebugMap::ParseCompileUnitFunctions(const SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+size_t SymbolFileDWARFDebugMap::ParseFunctions(CompileUnit &comp_unit) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseCompileUnitFunctions(sc);
+ return oso_dwarf->ParseFunctions(comp_unit);
return 0;
}
-bool SymbolFileDWARFDebugMap::ParseCompileUnitLineTable(
- const SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+bool SymbolFileDWARFDebugMap::ParseLineTable(CompileUnit &comp_unit) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseCompileUnitLineTable(sc);
+ return oso_dwarf->ParseLineTable(comp_unit);
return false;
}
-bool SymbolFileDWARFDebugMap::ParseCompileUnitDebugMacros(
- const SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+bool SymbolFileDWARFDebugMap::ParseDebugMacros(CompileUnit &comp_unit) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseCompileUnitDebugMacros(sc);
+ return oso_dwarf->ParseDebugMacros(comp_unit);
return false;
}
-bool SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles(
- const SymbolContext &sc, FileSpecList &support_files) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+bool SymbolFileDWARFDebugMap::ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseCompileUnitSupportFiles(sc, support_files);
+ return oso_dwarf->ParseSupportFiles(comp_unit, support_files);
return false;
}
-bool SymbolFileDWARFDebugMap::ParseCompileUnitIsOptimized(
- const lldb_private::SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+bool SymbolFileDWARFDebugMap::ParseIsOptimized(CompileUnit &comp_unit) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseCompileUnitIsOptimized(sc);
+ return oso_dwarf->ParseIsOptimized(comp_unit);
return false;
}
@@ -672,17 +677,21 @@ bool SymbolFileDWARFDebugMap::ParseImportedModules(
return false;
}
-size_t SymbolFileDWARFDebugMap::ParseFunctionBlocks(const SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+size_t SymbolFileDWARFDebugMap::ParseBlocksRecursive(Function &func) {
+ CompileUnit *comp_unit = func.GetCompileUnit();
+ if (!comp_unit)
+ return 0;
+
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(*comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseFunctionBlocks(sc);
+ return oso_dwarf->ParseBlocksRecursive(func);
return 0;
}
-size_t SymbolFileDWARFDebugMap::ParseTypes(const SymbolContext &sc) {
- SymbolFileDWARF *oso_dwarf = GetSymbolFile(sc);
+size_t SymbolFileDWARFDebugMap::ParseTypes(CompileUnit &comp_unit) {
+ SymbolFileDWARF *oso_dwarf = GetSymbolFile(comp_unit);
if (oso_dwarf)
- return oso_dwarf->ParseTypes(sc);
+ return oso_dwarf->ParseTypes(comp_unit);
return 0;
}
@@ -702,6 +711,16 @@ Type *SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid) {
return NULL;
}
+llvm::Optional<SymbolFile::ArrayInfo>
+SymbolFileDWARFDebugMap::GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
+ const uint64_t oso_idx = GetOSOIndexFromUserID(type_uid);
+ SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
+ if (oso_dwarf)
+ return oso_dwarf->GetDynamicArrayInfoForUID(type_uid, exe_ctx);
+ return llvm::None;
+}
+
bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) {
bool success = false;
if (compiler_type) {
@@ -717,8 +736,10 @@ bool SymbolFileDWARFDebugMap::CompleteType(CompilerType &compiler_type) {
return success;
}
-uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
- const Address &exe_so_addr, uint32_t resolve_scope, SymbolContext &sc) {
+uint32_t
+SymbolFileDWARFDebugMap::ResolveSymbolContext(const Address &exe_so_addr,
+ SymbolContextItem resolve_scope,
+ SymbolContext &sc) {
uint32_t resolved_flags = 0;
Symtab *symtab = m_obj_file->GetSymtab();
if (symtab) {
@@ -760,7 +781,7 @@ uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
uint32_t SymbolFileDWARFDebugMap::ResolveSymbolContext(
const FileSpec &file_spec, uint32_t line, bool check_inlines,
- uint32_t resolve_scope, SymbolContextList &sc_list) {
+ SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
const uint32_t initial = sc_list.GetSize();
const uint32_t cu_count = GetNumCompileUnits();
@@ -792,8 +813,7 @@ uint32_t SymbolFileDWARFDebugMap::PrivateFindGlobalVariables(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
const std::vector<uint32_t>
&indexes, // Indexes into the symbol table that match "name"
- uint32_t max_matches,
- VariableList &variables) {
+ uint32_t max_matches, VariableList &variables) {
const uint32_t original_size = variables.GetSize();
const size_t match_count = indexes.size();
for (size_t i = 0; i < match_count; ++i) {
@@ -977,7 +997,7 @@ static void RemoveFunctionsWithModuleNotEqualTo(const ModuleSP &module_sp,
uint32_t SymbolFileDWARFDebugMap::FindFunctions(
const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines, bool append,
+ FunctionNameType name_type_mask, bool include_inlines, bool append,
SymbolContextList &sc_list) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat,
@@ -1032,7 +1052,7 @@ uint32_t SymbolFileDWARFDebugMap::FindFunctions(const RegularExpression &regex,
}
size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ lldb::TypeClass type_mask,
TypeList &type_list) {
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
Timer scoped_timer(func_cat,
@@ -1060,6 +1080,15 @@ size_t SymbolFileDWARFDebugMap::GetTypes(SymbolContextScope *sc_scope,
return type_list.GetSize() - initial_size;
}
+std::vector<lldb_private::CallEdge>
+SymbolFileDWARFDebugMap::ParseCallEdgesInFunction(UserID func_id) {
+ uint32_t oso_idx = GetOSOIndexFromUserID(func_id.GetID());
+ SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
+ if (oso_dwarf)
+ return oso_dwarf->ParseCallEdgesInFunction(func_id);
+ return {};
+}
+
TypeSP SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext(
const DWARFDeclContext &die_decl_ctx) {
TypeSP type_sp;
@@ -1136,7 +1165,7 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
// Only search all .o files for the definition if we don't need the
// implementation because otherwise, with a valid debug map we should have
// the ObjC class symbol and the code above should have found it.
- if (must_be_implementation == false) {
+ if (!must_be_implementation) {
TypeSP type_sp;
ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
@@ -1151,32 +1180,20 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE(
}
uint32_t SymbolFileDWARFDebugMap::FindTypes(
- const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
- uint32_t max_matches,
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
if (!append)
types.Clear();
const uint32_t initial_types_size = types.GetSize();
- SymbolFileDWARF *oso_dwarf;
- if (sc.comp_unit) {
- oso_dwarf = GetSymbolFile(sc);
- if (oso_dwarf)
- return oso_dwarf->FindTypes(sc, name, parent_decl_ctx, append,
- max_matches, searched_symbol_files, types);
- } else {
- ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- oso_dwarf->FindTypes(sc, name, parent_decl_ctx, append, max_matches,
- searched_symbol_files, types);
- if (types.GetSize() >= max_matches)
- return true;
- else
- return false;
- });
- }
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ oso_dwarf->FindTypes(name, parent_decl_ctx, append, max_matches,
+ searched_symbol_files, types);
+ return types.GetSize() >= max_matches;
+ });
return types.GetSize() - initial_types_size;
}
@@ -1195,27 +1212,26 @@ uint32_t SymbolFileDWARFDebugMap::FindTypes(
//}
CompilerDeclContext SymbolFileDWARFDebugMap::FindNamespace(
- const lldb_private::SymbolContext &sc,
const lldb_private::ConstString &name,
const CompilerDeclContext *parent_decl_ctx) {
CompilerDeclContext matching_namespace;
- SymbolFileDWARF *oso_dwarf;
- if (sc.comp_unit) {
- oso_dwarf = GetSymbolFile(sc);
- if (oso_dwarf)
- matching_namespace = oso_dwarf->FindNamespace(sc, name, parent_decl_ctx);
- } else {
- ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
- matching_namespace = oso_dwarf->FindNamespace(sc, name, parent_decl_ctx);
+ ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+ matching_namespace = oso_dwarf->FindNamespace(name, parent_decl_ctx);
- return (bool)matching_namespace;
- });
- }
+ return (bool)matching_namespace;
+ });
return matching_namespace;
}
+void SymbolFileDWARFDebugMap::DumpClangAST(Stream &s) {
+ ForEachSymbolFile([&s](SymbolFileDWARF *oso_dwarf) -> bool {
+ oso_dwarf->DumpClangAST(s);
+ return true;
+ });
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index 550f74a203ea..176eadeeca71 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -56,27 +56,33 @@ public:
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
lldb::LanguageType
- ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override;
- size_t
- ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override;
- bool
- ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override;
- bool
- ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override;
- bool ParseCompileUnitSupportFiles(
- const lldb_private::SymbolContext &sc,
- lldb_private::FileSpecList &support_files) override;
- bool
- ParseCompileUnitIsOptimized(const lldb_private::SymbolContext &sc) override;
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
+
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ lldb_private::FileSpecList &support_files) override;
+
+ bool ParseIsOptimized(lldb_private::CompileUnit &comp_unit) override;
+
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
+
bool ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) override;
- size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override;
- size_t ParseTypes(const lldb_private::SymbolContext &sc) override;
+ size_t ParseBlocksRecursive(lldb_private::Function &func) override;
size_t
ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
+
lldb_private::CompilerDeclContext
GetDeclContextForUID(lldb::user_id_t uid) override;
lldb_private::CompilerDeclContext
@@ -86,11 +92,12 @@ public:
bool CompleteType(lldb_private::CompilerType &compiler_type) override;
uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
uint32_t
ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines, uint32_t resolve_scope,
+ bool check_inlines,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContextList &sc_list) override;
uint32_t
FindGlobalVariables(const lldb_private::ConstString &name,
@@ -103,25 +110,27 @@ public:
uint32_t
FindFunctions(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines, bool append,
- lldb_private::SymbolContextList &sc_list) override;
+ lldb::FunctionNameType name_type_mask, bool include_inlines,
+ bool append, lldb_private::SymbolContextList &sc_list) override;
uint32_t FindFunctions(const lldb_private::RegularExpression &regex,
bool include_inlines, bool append,
lldb_private::SymbolContextList &sc_list) override;
uint32_t
- FindTypes(const lldb_private::SymbolContext &sc,
- const lldb_private::ConstString &name,
+ FindTypes(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
lldb_private::TypeMap &types) override;
lldb_private::CompilerDeclContext FindNamespace(
- const lldb_private::SymbolContext &sc,
const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override;
+ std::vector<lldb_private::CallEdge>
+ ParseCallEdgesInFunction(lldb_private::UserID func_id) override;
+
+ void DumpClangAST(lldb_private::Stream &s) override;
//------------------------------------------------------------------
// PluginInterface protocol
@@ -189,6 +198,7 @@ protected:
bool GetFileSpecForSO(uint32_t oso_idx, lldb_private::FileSpec &file_spec);
CompileUnitInfo *GetCompUnitInfo(const lldb_private::SymbolContext &sc);
+ CompileUnitInfo *GetCompUnitInfo(const lldb_private::CompileUnit &comp_unit);
size_t GetCompUnitInfosForModule(const lldb_private::Module *oso_module,
std::vector<CompileUnitInfo *> &cu_infos);
@@ -206,6 +216,7 @@ protected:
uint32_t GetCompUnitInfoIndex(const CompileUnitInfo *comp_unit_info);
SymbolFileDWARF *GetSymbolFile(const lldb_private::SymbolContext &sc);
+ SymbolFileDWARF *GetSymbolFile(const lldb_private::CompileUnit &comp_unit);
SymbolFileDWARF *GetSymbolFileByCompUnitInfo(CompileUnitInfo *comp_unit_info);
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index 15fe362fa117..7881448535b8 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -61,14 +61,6 @@ SymbolFileDWARFDwo::ParseCompileUnit(DWARFUnit *dwarf_cu,
}
DWARFUnit *SymbolFileDWARFDwo::GetCompileUnit() {
- // A clang module is found via a skeleton CU, but is not a proper DWO.
- // Clang modules have a .debug_info section instead of the *_dwo variant.
- if (auto *section_list = m_obj_file->GetSectionList(false))
- if (auto section_sp =
- section_list->FindSectionByType(eSectionTypeDWARFDebugInfo, true))
- if (!section_sp->GetName().GetStringRef().endswith("dwo"))
- return nullptr;
-
// Only dwo files with 1 compile unit is supported
if (GetNumCompileUnits() == 1)
return DebugInfo()->GetCompileUnitAtIndex(0);
@@ -126,6 +118,37 @@ DWARFUnit *SymbolFileDWARFDwo::GetBaseCompileUnit() {
return m_base_dwarf_cu;
}
+const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_abbrev_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugAbbrevDwo,
+ m_data_debug_abbrev);
+}
+
+const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_addr_data() {
+ // For single file split dwarf case (when we have .dwo sections in a .o),
+ // we do not want to use the .debug_addr section from .o file,
+ // but want to get one from the final executable.
+ // For regular split debug case, .dwo file does not contain the
+ // .debug_addr, so we would always fall back to such lookup anyways.
+ llvm::call_once(m_data_debug_addr.m_flag, [this] {
+ SymbolFileDWARF::LoadSectionData(eSectionTypeDWARFDebugAddr,
+ std::ref(m_data_debug_addr.m_data));
+ });
+ return m_data_debug_addr.m_data;
+}
+
+const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_info_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugInfoDwo, m_data_debug_info);
+}
+
+const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_str_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugStrDwo, m_data_debug_str);
+}
+
+const DWARFDataExtractor &SymbolFileDWARFDwo::get_debug_str_offsets_data() {
+ return GetCachedSectionData(eSectionTypeDWARFDebugStrOffsetsDwo,
+ m_data_debug_str_offsets);
+}
+
SymbolFileDWARF *SymbolFileDWARFDwo::GetBaseSymbolFile() {
return m_base_dwarf_cu->GetSymbolFileDWARF();
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index 483a19512a36..b9ed37547aca 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -10,10 +10,6 @@
#ifndef SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
#define SymbolFileDWARFDwo_SymbolFileDWARFDwo_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "SymbolFileDWARF.h"
class SymbolFileDWARFDwo : public SymbolFileDWARF {
@@ -50,6 +46,12 @@ public:
DWARFUnit *GetBaseCompileUnit() override;
+ const lldb_private::DWARFDataExtractor &get_debug_abbrev_data() override;
+ const lldb_private::DWARFDataExtractor &get_debug_addr_data() override;
+ const lldb_private::DWARFDataExtractor &get_debug_info_data() override;
+ const lldb_private::DWARFDataExtractor &get_debug_str_data() override;
+ const lldb_private::DWARFDataExtractor &get_debug_str_offsets_data() override;
+
protected:
void LoadSectionData(lldb::SectionType sect_type,
lldb_private::DWARFDataExtractor &data) override;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
index b1b505b5899f..905ba0a5c7b8 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwoDwp.h
@@ -10,10 +10,6 @@
#ifndef SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_
#define SymbolFileDWARFDwoDwp_SymbolFileDWARFDwoDwp_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "SymbolFileDWARFDwo.h"
#include "SymbolFileDWARFDwp.h"
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
index ae10e7179e33..73226dfc130f 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.cpp
@@ -9,10 +9,6 @@
#include "SymbolFileDWARFDwp.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -30,7 +26,7 @@ lldbSectTypeToLlvmSectionKind(lldb::SectionType type) {
case lldb::eSectionTypeDWARFDebugLine:
return llvm::DW_SECT_LINE;
case lldb::eSectionTypeDWARFDebugLoc:
- return llvm::DW_SECT_LOC;
+ return llvm::DW_SECT_LOC;
case lldb::eSectionTypeDWARFDebugStrOffsets:
return llvm::DW_SECT_STR_OFFSETS;
// case lldb::eSectionTypeDWARFDebugMacinfo:
@@ -50,7 +46,8 @@ SymbolFileDWARFDwp::Create(lldb::ModuleSP module_sp,
lldb::DataBufferSP file_data_sp;
lldb::offset_t file_data_offset = 0;
lldb::ObjectFileSP obj_file = lldb_private::ObjectFile::FindPlugin(
- module_sp, &file_spec, file_offset, file_spec.GetByteSize(), file_data_sp,
+ module_sp, &file_spec, file_offset,
+ lldb_private::FileSystem::Instance().GetByteSize(file_spec), file_data_sp,
file_data_offset);
if (obj_file == nullptr)
return nullptr;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
index 470d1c5b1c48..87f4d9402335 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwp.h
@@ -10,14 +10,10 @@
#ifndef SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_
#define SymbolFileDWARFDwp_SymbolFileDWARFDwp_h_
-// C Includes
-// C++ Includes
#include <memory>
-// Other libraries and framework includes
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
-// Project includes
#include "lldb/Core/Module.h"
#include "DWARFDataExtractor.h"
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
index 8273d975e57d..dd912aecf0d8 100644
--- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -9,10 +9,6 @@
#include "UniqueDWARFASTType.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/Declaration.h"
bool UniqueDWARFASTTypeList::Find(const DWARFDIE &die,
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
index 5d51044cbe1a..1e6b164e9457 100644
--- a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -10,14 +10,10 @@
#ifndef lldb_UniqueDWARFASTType_h_
#define lldb_UniqueDWARFASTType_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/ADT/DenseMap.h"
-// Project includes
#include "DWARFDIE.h"
#include "lldb/Symbol/Declaration.h"
diff --git a/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt b/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
new file mode 100644
index 000000000000..da2d7fe8108a
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN
+ CompileUnitIndex.cpp
+ DWARFLocationExpression.cpp
+ PdbAstBuilder.cpp
+ PdbIndex.cpp
+ PdbSymUid.cpp
+ PdbUtil.cpp
+ SymbolFileNativePDB.cpp
+ UdtRecordCompleter.cpp
+
+ LINK_LIBS
+ clangAST
+ clangLex
+ lldbCore
+ lldbSymbol
+ lldbUtility
+ LINK_COMPONENTS
+ DebugInfoCodeView
+ DebugInfoPDB
+ Support
+ )
diff --git a/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
new file mode 100644
index 000000000000..67ea05767fde
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
@@ -0,0 +1,217 @@
+//===-- CompileUnitIndex.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompileUnitIndex.h"
+
+#include "PdbIndex.h"
+#include "PdbUtil.h"
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Support/Path.h"
+
+#include "lldb/Utility/LLDBAssert.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static bool IsMainFile(llvm::StringRef main, llvm::StringRef other) {
+ if (main == other)
+ return true;
+
+ // If the files refer to the local file system, we can just ask the file
+ // system if they're equivalent. But if the source isn't present on disk
+ // then we still want to try.
+ if (llvm::sys::fs::equivalent(main, other))
+ return true;
+
+ llvm::SmallString<64> normalized(other);
+ llvm::sys::path::native(normalized);
+ return main.equals_lower(normalized);
+}
+
+static void ParseCompile3(const CVSymbol &sym, CompilandIndexItem &cci) {
+ cci.m_compile_opts.emplace();
+ llvm::cantFail(
+ SymbolDeserializer::deserializeAs<Compile3Sym>(sym, *cci.m_compile_opts));
+}
+
+static void ParseObjname(const CVSymbol &sym, CompilandIndexItem &cci) {
+ cci.m_obj_name.emplace();
+ llvm::cantFail(
+ SymbolDeserializer::deserializeAs<ObjNameSym>(sym, *cci.m_obj_name));
+}
+
+static void ParseBuildInfo(PdbIndex &index, const CVSymbol &sym,
+ CompilandIndexItem &cci) {
+ BuildInfoSym bis(SymbolRecordKind::BuildInfoSym);
+ llvm::cantFail(SymbolDeserializer::deserializeAs<BuildInfoSym>(sym, bis));
+
+ // S_BUILDINFO just points to an LF_BUILDINFO in the IPI stream. Let's do
+ // a little extra work to pull out the LF_BUILDINFO.
+ LazyRandomTypeCollection &types = index.ipi().typeCollection();
+ llvm::Optional<CVType> cvt = types.tryGetType(bis.BuildId);
+
+ if (!cvt || cvt->kind() != LF_BUILDINFO)
+ return;
+
+ BuildInfoRecord bir;
+ llvm::cantFail(TypeDeserializer::deserializeAs<BuildInfoRecord>(*cvt, bir));
+ cci.m_build_info.assign(bir.ArgIndices.begin(), bir.ArgIndices.end());
+}
+
+static void ParseExtendedInfo(PdbIndex &index, CompilandIndexItem &item) {
+ const CVSymbolArray &syms = item.m_debug_stream.getSymbolArray();
+
+ // This is a private function, it shouldn't be called if the information
+ // has already been parsed.
+ lldbassert(!item.m_obj_name);
+ lldbassert(!item.m_compile_opts);
+ lldbassert(item.m_build_info.empty());
+
+ // We're looking for 3 things. S_COMPILE3, S_OBJNAME, and S_BUILDINFO.
+ int found = 0;
+ for (const CVSymbol &sym : syms) {
+ switch (sym.kind()) {
+ case S_COMPILE3:
+ ParseCompile3(sym, item);
+ break;
+ case S_OBJNAME:
+ ParseObjname(sym, item);
+ break;
+ case S_BUILDINFO:
+ ParseBuildInfo(index, sym, item);
+ break;
+ default:
+ continue;
+ }
+ if (++found >= 3)
+ break;
+ }
+}
+
+CompilandIndexItem::CompilandIndexItem(
+ PdbCompilandId id, llvm::pdb::ModuleDebugStreamRef debug_stream,
+ llvm::pdb::DbiModuleDescriptor descriptor)
+ : m_id(id), m_debug_stream(std::move(debug_stream)),
+ m_module_descriptor(std::move(descriptor)) {}
+
+CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) {
+ auto result = m_comp_units.try_emplace(modi, nullptr);
+ if (!result.second)
+ return *result.first->second;
+
+ // Find the module list and load its debug information stream and cache it
+ // since we need to use it for almost all interesting operations.
+ const DbiModuleList &modules = m_index.dbi().modules();
+ llvm::pdb::DbiModuleDescriptor descriptor = modules.getModuleDescriptor(modi);
+ uint16_t stream = descriptor.getModuleStreamIndex();
+ std::unique_ptr<llvm::msf::MappedBlockStream> stream_data =
+ m_index.pdb().createIndexedStream(stream);
+ llvm::pdb::ModuleDebugStreamRef debug_stream(descriptor,
+ std::move(stream_data));
+ cantFail(debug_stream.reload());
+
+ std::unique_ptr<CompilandIndexItem> &cci = result.first->second;
+
+ cci = llvm::make_unique<CompilandIndexItem>(
+ PdbCompilandId{modi}, std::move(debug_stream), std::move(descriptor));
+ ParseExtendedInfo(m_index, *cci);
+
+ cci->m_strings.initialize(debug_stream.getSubsectionsArray());
+ PDBStringTable &strings = cantFail(m_index.pdb().getStringTable());
+ cci->m_strings.setStrings(strings.getStringTable());
+
+ // We want the main source file to always comes first. Note that we can't
+ // just push_back the main file onto the front because `GetMainSourceFile`
+ // computes it in such a way that it doesn't own the resulting memory. So we
+ // have to iterate the module file list comparing each one to the main file
+ // name until we find it, and we can cache that one since the memory is backed
+ // by a contiguous chunk inside the mapped PDB.
+ llvm::SmallString<64> main_file = GetMainSourceFile(*cci);
+ std::string s = main_file.str();
+ llvm::sys::path::native(main_file);
+
+ uint32_t file_count = modules.getSourceFileCount(modi);
+ cci->m_file_list.reserve(file_count);
+ bool found_main_file = false;
+ for (llvm::StringRef file : modules.source_files(modi)) {
+ if (!found_main_file && IsMainFile(main_file, file)) {
+ cci->m_file_list.insert(cci->m_file_list.begin(), file);
+ found_main_file = true;
+ continue;
+ }
+ cci->m_file_list.push_back(file);
+ }
+
+ return *cci;
+}
+
+const CompilandIndexItem *CompileUnitIndex::GetCompiland(uint16_t modi) const {
+ auto iter = m_comp_units.find(modi);
+ if (iter == m_comp_units.end())
+ return nullptr;
+ return iter->second.get();
+}
+
+CompilandIndexItem *CompileUnitIndex::GetCompiland(uint16_t modi) {
+ auto iter = m_comp_units.find(modi);
+ if (iter == m_comp_units.end())
+ return nullptr;
+ return iter->second.get();
+}
+
+llvm::SmallString<64>
+CompileUnitIndex::GetMainSourceFile(const CompilandIndexItem &item) const {
+ // LF_BUILDINFO contains a list of arg indices which point to LF_STRING_ID
+ // records in the IPI stream. The order of the arg indices is as follows:
+ // [0] - working directory where compiler was invoked.
+ // [1] - absolute path to compiler binary
+ // [2] - source file name
+ // [3] - path to compiler generated PDB (the /Zi PDB, although this entry gets
+ // added even when using /Z7)
+ // [4] - full command line invocation.
+ //
+ // We need to form the path [0]\[2] to generate the full path to the main
+ // file.source
+ if (item.m_build_info.size() < 3)
+ return {""};
+
+ LazyRandomTypeCollection &types = m_index.ipi().typeCollection();
+
+ StringIdRecord working_dir;
+ StringIdRecord file_name;
+ CVType dir_cvt = types.getType(item.m_build_info[0]);
+ CVType file_cvt = types.getType(item.m_build_info[2]);
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<StringIdRecord>(dir_cvt, working_dir));
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<StringIdRecord>(file_cvt, file_name));
+
+ llvm::sys::path::Style style = working_dir.String.startswith("/")
+ ? llvm::sys::path::Style::posix
+ : llvm::sys::path::Style::windows;
+ if (llvm::sys::path::is_absolute(file_name.String, style))
+ return file_name.String;
+
+ llvm::SmallString<64> absolute_path = working_dir.String;
+ llvm::sys::path::append(absolute_path, file_name.String);
+ return absolute_path;
+}
diff --git a/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h
new file mode 100644
index 000000000000..c965870da44b
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h
@@ -0,0 +1,95 @@
+//===-- CompileUnitIndex.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_PLUGINS_SYMBOLFILENATIVEPDB_COMPILEUNITINDEX_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_COMPILEUNITINDEX_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "PdbSymUid.h"
+
+#include <map>
+#include <memory>
+
+namespace lldb_private {
+
+namespace npdb {
+class PdbIndex;
+
+/// Represents a single compile unit. This class is useful for collecting the
+/// important accessors and information about a compile unit from disparate
+/// parts of the PDB into a single place, simplifying acess to compile unit
+/// information for the callers.
+struct CompilandIndexItem {
+ CompilandIndexItem(PdbCompilandId m_id,
+ llvm::pdb::ModuleDebugStreamRef debug_stream,
+ llvm::pdb::DbiModuleDescriptor descriptor);
+
+ // index of this compile unit.
+ PdbCompilandId m_id;
+
+ // debug stream.
+ llvm::pdb::ModuleDebugStreamRef m_debug_stream;
+
+ // dbi module descriptor.
+ llvm::pdb::DbiModuleDescriptor m_module_descriptor;
+
+ llvm::codeview::StringsAndChecksumsRef m_strings;
+
+ // List of files which contribute to this compiland.
+ std::vector<llvm::StringRef> m_file_list;
+
+ // Maps virtual address to global symbol id, which can then be used to
+ // locate the exact compile unit and offset of the symbol. Note that this
+ // is intentionally an ordered map so that we can find all symbols up to a
+ // given starting address.
+ std::map<lldb::addr_t, PdbSymUid> m_symbols_by_va;
+
+ // S_COMPILE3 sym describing compilation settings for the module.
+ llvm::Optional<llvm::codeview::Compile3Sym> m_compile_opts;
+
+ // S_OBJNAME sym describing object name.
+ llvm::Optional<llvm::codeview::ObjNameSym> m_obj_name;
+
+ // LF_BUILDINFO sym describing source file name, working directory,
+ // command line, etc. This usually contains exactly 5 items which
+ // are references to other strings.
+ llvm::SmallVector<llvm::codeview::TypeIndex, 5> m_build_info;
+};
+
+/// Indexes information about all compile units. This is really just a map of
+/// global compile unit index to |CompilandIndexItem| structures.
+class CompileUnitIndex {
+ PdbIndex &m_index;
+ llvm::DenseMap<uint16_t, std::unique_ptr<CompilandIndexItem>> m_comp_units;
+
+public:
+ explicit CompileUnitIndex(PdbIndex &index) : m_index(index) {}
+
+ CompilandIndexItem &GetOrCreateCompiland(uint16_t modi);
+
+ const CompilandIndexItem *GetCompiland(uint16_t modi) const;
+
+ CompilandIndexItem *GetCompiland(uint16_t modi);
+
+ llvm::SmallString<64> GetMainSourceFile(const CompilandIndexItem &item) const;
+};
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
new file mode 100644
index 000000000000..7b62530e4680
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
@@ -0,0 +1,673 @@
+//===-- DWARFLocationExpression.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLocationExpression.h"
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamBuffer.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/DataBufferHeap.h"
+
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Support/Endian.h"
+
+#include "PdbUtil.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static const uint32_t g_code_view_to_lldb_registers_x86[] = {
+ LLDB_INVALID_REGNUM, // NONE
+ lldb_al_i386, // AL
+ lldb_cl_i386, // CL
+ lldb_dl_i386, // DL
+ lldb_bl_i386, // BL
+ lldb_ah_i386, // AH
+ lldb_ch_i386, // CH
+ lldb_dh_i386, // DH
+ lldb_bh_i386, // BH
+ lldb_ax_i386, // AX
+ lldb_cx_i386, // CX
+ lldb_dx_i386, // DX
+ lldb_bx_i386, // BX
+ lldb_sp_i386, // SP
+ lldb_bp_i386, // BP
+ lldb_si_i386, // SI
+ lldb_di_i386, // DI
+ lldb_eax_i386, // EAX
+ lldb_ecx_i386, // ECX
+ lldb_edx_i386, // EDX
+ lldb_ebx_i386, // EBX
+ lldb_esp_i386, // ESP
+ lldb_ebp_i386, // EBP
+ lldb_esi_i386, // ESI
+ lldb_edi_i386, // EDI
+ lldb_es_i386, // ES
+ lldb_cs_i386, // CS
+ lldb_ss_i386, // SS
+ lldb_ds_i386, // DS
+ lldb_fs_i386, // FS
+ lldb_gs_i386, // GS
+ LLDB_INVALID_REGNUM, // IP
+ LLDB_INVALID_REGNUM, // FLAGS
+ lldb_eip_i386, // EIP
+ lldb_eflags_i386, // EFLAGS
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // TEMP
+ LLDB_INVALID_REGNUM, // TEMPH
+ LLDB_INVALID_REGNUM, // QUOTE
+ LLDB_INVALID_REGNUM, // PCDR3
+ LLDB_INVALID_REGNUM, // PCDR4
+ LLDB_INVALID_REGNUM, // PCDR5
+ LLDB_INVALID_REGNUM, // PCDR6
+ LLDB_INVALID_REGNUM, // PCDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CR0
+ LLDB_INVALID_REGNUM, // CR1
+ LLDB_INVALID_REGNUM, // CR2
+ LLDB_INVALID_REGNUM, // CR3
+ LLDB_INVALID_REGNUM, // CR4
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_dr0_i386, // DR0
+ lldb_dr1_i386, // DR1
+ lldb_dr2_i386, // DR2
+ lldb_dr3_i386, // DR3
+ lldb_dr4_i386, // DR4
+ lldb_dr5_i386, // DR5
+ lldb_dr6_i386, // DR6
+ lldb_dr7_i386, // DR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // GDTR
+ LLDB_INVALID_REGNUM, // GDTL
+ LLDB_INVALID_REGNUM, // IDTR
+ LLDB_INVALID_REGNUM, // IDTL
+ LLDB_INVALID_REGNUM, // LDTR
+ LLDB_INVALID_REGNUM, // TR
+ LLDB_INVALID_REGNUM, // PSEUDO1
+ LLDB_INVALID_REGNUM, // PSEUDO2
+ LLDB_INVALID_REGNUM, // PSEUDO3
+ LLDB_INVALID_REGNUM, // PSEUDO4
+ LLDB_INVALID_REGNUM, // PSEUDO5
+ LLDB_INVALID_REGNUM, // PSEUDO6
+ LLDB_INVALID_REGNUM, // PSEUDO7
+ LLDB_INVALID_REGNUM, // PSEUDO8
+ LLDB_INVALID_REGNUM, // PSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_i386, // ST0
+ lldb_st1_i386, // ST1
+ lldb_st2_i386, // ST2
+ lldb_st3_i386, // ST3
+ lldb_st4_i386, // ST4
+ lldb_st5_i386, // ST5
+ lldb_st6_i386, // ST6
+ lldb_st7_i386, // ST7
+ LLDB_INVALID_REGNUM, // CTRL
+ LLDB_INVALID_REGNUM, // STAT
+ LLDB_INVALID_REGNUM, // TAG
+ LLDB_INVALID_REGNUM, // FPIP
+ LLDB_INVALID_REGNUM, // FPCS
+ LLDB_INVALID_REGNUM, // FPDO
+ LLDB_INVALID_REGNUM, // FPDS
+ LLDB_INVALID_REGNUM, // ISEM
+ LLDB_INVALID_REGNUM, // FPEIP
+ LLDB_INVALID_REGNUM, // FPEDO
+ lldb_mm0_i386, // MM0
+ lldb_mm1_i386, // MM1
+ lldb_mm2_i386, // MM2
+ lldb_mm3_i386, // MM3
+ lldb_mm4_i386, // MM4
+ lldb_mm5_i386, // MM5
+ lldb_mm6_i386, // MM6
+ lldb_mm7_i386, // MM7
+ lldb_xmm0_i386, // XMM0
+ lldb_xmm1_i386, // XMM1
+ lldb_xmm2_i386, // XMM2
+ lldb_xmm3_i386, // XMM3
+ lldb_xmm4_i386, // XMM4
+ lldb_xmm5_i386, // XMM5
+ lldb_xmm6_i386, // XMM6
+ lldb_xmm7_i386 // XMM7
+};
+
+static const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
+ LLDB_INVALID_REGNUM, // NONE
+ lldb_al_x86_64, // AL
+ lldb_cl_x86_64, // CL
+ lldb_dl_x86_64, // DL
+ lldb_bl_x86_64, // BL
+ lldb_ah_x86_64, // AH
+ lldb_ch_x86_64, // CH
+ lldb_dh_x86_64, // DH
+ lldb_bh_x86_64, // BH
+ lldb_ax_x86_64, // AX
+ lldb_cx_x86_64, // CX
+ lldb_dx_x86_64, // DX
+ lldb_bx_x86_64, // BX
+ lldb_sp_x86_64, // SP
+ lldb_bp_x86_64, // BP
+ lldb_si_x86_64, // SI
+ lldb_di_x86_64, // DI
+ lldb_eax_x86_64, // EAX
+ lldb_ecx_x86_64, // ECX
+ lldb_edx_x86_64, // EDX
+ lldb_ebx_x86_64, // EBX
+ lldb_esp_x86_64, // ESP
+ lldb_ebp_x86_64, // EBP
+ lldb_esi_x86_64, // ESI
+ lldb_edi_x86_64, // EDI
+ lldb_es_x86_64, // ES
+ lldb_cs_x86_64, // CS
+ lldb_ss_x86_64, // SS
+ lldb_ds_x86_64, // DS
+ lldb_fs_x86_64, // FS
+ lldb_gs_x86_64, // GS
+ LLDB_INVALID_REGNUM, // IP
+ LLDB_INVALID_REGNUM, // FLAGS
+ LLDB_INVALID_REGNUM, // EIP
+ LLDB_INVALID_REGNUM, // EFLAGS
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // TEMP
+ LLDB_INVALID_REGNUM, // TEMPH
+ LLDB_INVALID_REGNUM, // QUOTE
+ LLDB_INVALID_REGNUM, // PCDR3
+ LLDB_INVALID_REGNUM, // PCDR4
+ LLDB_INVALID_REGNUM, // PCDR5
+ LLDB_INVALID_REGNUM, // PCDR6
+ LLDB_INVALID_REGNUM, // PCDR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // CR0
+ LLDB_INVALID_REGNUM, // CR1
+ LLDB_INVALID_REGNUM, // CR2
+ LLDB_INVALID_REGNUM, // CR3
+ LLDB_INVALID_REGNUM, // CR4
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_dr0_x86_64, // DR0
+ lldb_dr1_x86_64, // DR1
+ lldb_dr2_x86_64, // DR2
+ lldb_dr3_x86_64, // DR3
+ lldb_dr4_x86_64, // DR4
+ lldb_dr5_x86_64, // DR5
+ lldb_dr6_x86_64, // DR6
+ lldb_dr7_x86_64, // DR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // GDTR
+ LLDB_INVALID_REGNUM, // GDTL
+ LLDB_INVALID_REGNUM, // IDTR
+ LLDB_INVALID_REGNUM, // IDTL
+ LLDB_INVALID_REGNUM, // LDTR
+ LLDB_INVALID_REGNUM, // TR
+ LLDB_INVALID_REGNUM, // PSEUDO1
+ LLDB_INVALID_REGNUM, // PSEUDO2
+ LLDB_INVALID_REGNUM, // PSEUDO3
+ LLDB_INVALID_REGNUM, // PSEUDO4
+ LLDB_INVALID_REGNUM, // PSEUDO5
+ LLDB_INVALID_REGNUM, // PSEUDO6
+ LLDB_INVALID_REGNUM, // PSEUDO7
+ LLDB_INVALID_REGNUM, // PSEUDO8
+ LLDB_INVALID_REGNUM, // PSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_x86_64, // ST0
+ lldb_st1_x86_64, // ST1
+ lldb_st2_x86_64, // ST2
+ lldb_st3_x86_64, // ST3
+ lldb_st4_x86_64, // ST4
+ lldb_st5_x86_64, // ST5
+ lldb_st6_x86_64, // ST6
+ lldb_st7_x86_64, // ST7
+ LLDB_INVALID_REGNUM, // CTRL
+ LLDB_INVALID_REGNUM, // STAT
+ LLDB_INVALID_REGNUM, // TAG
+ LLDB_INVALID_REGNUM, // FPIP
+ LLDB_INVALID_REGNUM, // FPCS
+ LLDB_INVALID_REGNUM, // FPDO
+ LLDB_INVALID_REGNUM, // FPDS
+ LLDB_INVALID_REGNUM, // ISEM
+ LLDB_INVALID_REGNUM, // FPEIP
+ LLDB_INVALID_REGNUM, // FPEDO
+ lldb_mm0_x86_64, // MM0
+ lldb_mm1_x86_64, // MM1
+ lldb_mm2_x86_64, // MM2
+ lldb_mm3_x86_64, // MM3
+ lldb_mm4_x86_64, // MM4
+ lldb_mm5_x86_64, // MM5
+ lldb_mm6_x86_64, // MM6
+ lldb_mm7_x86_64, // MM7
+ lldb_xmm0_x86_64, // XMM0
+ lldb_xmm1_x86_64, // XMM1
+ lldb_xmm2_x86_64, // XMM2
+ lldb_xmm3_x86_64, // XMM3
+ lldb_xmm4_x86_64, // XMM4
+ lldb_xmm5_x86_64, // XMM5
+ lldb_xmm6_x86_64, // XMM6
+ lldb_xmm7_x86_64, // XMM7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ lldb_mxcsr_x86_64, // MXCSR
+ LLDB_INVALID_REGNUM, // EDXEAX
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // EMM0L
+ LLDB_INVALID_REGNUM, // EMM1L
+ LLDB_INVALID_REGNUM, // EMM2L
+ LLDB_INVALID_REGNUM, // EMM3L
+ LLDB_INVALID_REGNUM, // EMM4L
+ LLDB_INVALID_REGNUM, // EMM5L
+ LLDB_INVALID_REGNUM, // EMM6L
+ LLDB_INVALID_REGNUM, // EMM7L
+ LLDB_INVALID_REGNUM, // EMM0H
+ LLDB_INVALID_REGNUM, // EMM1H
+ LLDB_INVALID_REGNUM, // EMM2H
+ LLDB_INVALID_REGNUM, // EMM3H
+ LLDB_INVALID_REGNUM, // EMM4H
+ LLDB_INVALID_REGNUM, // EMM5H
+ LLDB_INVALID_REGNUM, // EMM6H
+ LLDB_INVALID_REGNUM, // EMM7H
+ LLDB_INVALID_REGNUM, // MM00
+ LLDB_INVALID_REGNUM, // MM01
+ LLDB_INVALID_REGNUM, // MM10
+ LLDB_INVALID_REGNUM, // MM11
+ LLDB_INVALID_REGNUM, // MM20
+ LLDB_INVALID_REGNUM, // MM21
+ LLDB_INVALID_REGNUM, // MM30
+ LLDB_INVALID_REGNUM, // MM31
+ LLDB_INVALID_REGNUM, // MM40
+ LLDB_INVALID_REGNUM, // MM41
+ LLDB_INVALID_REGNUM, // MM50
+ LLDB_INVALID_REGNUM, // MM51
+ LLDB_INVALID_REGNUM, // MM60
+ LLDB_INVALID_REGNUM, // MM61
+ LLDB_INVALID_REGNUM, // MM70
+ LLDB_INVALID_REGNUM, // MM71
+ lldb_xmm8_x86_64, // XMM8
+ lldb_xmm9_x86_64, // XMM9
+ lldb_xmm10_x86_64, // XMM10
+ lldb_xmm11_x86_64, // XMM11
+ lldb_xmm12_x86_64, // XMM12
+ lldb_xmm13_x86_64, // XMM13
+ lldb_xmm14_x86_64, // XMM14
+ lldb_xmm15_x86_64, // XMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ lldb_sil_x86_64, // SIL
+ lldb_dil_x86_64, // DIL
+ lldb_bpl_x86_64, // BPL
+ lldb_spl_x86_64, // SPL
+ lldb_rax_x86_64, // RAX
+ lldb_rbx_x86_64, // RBX
+ lldb_rcx_x86_64, // RCX
+ lldb_rdx_x86_64, // RDX
+ lldb_rsi_x86_64, // RSI
+ lldb_rdi_x86_64, // RDI
+ lldb_rbp_x86_64, // RBP
+ lldb_rsp_x86_64, // RSP
+ lldb_r8_x86_64, // R8
+ lldb_r9_x86_64, // R9
+ lldb_r10_x86_64, // R10
+ lldb_r11_x86_64, // R11
+ lldb_r12_x86_64, // R12
+ lldb_r13_x86_64, // R13
+ lldb_r14_x86_64, // R14
+ lldb_r15_x86_64, // R15
+ lldb_r8l_x86_64, // R8B
+ lldb_r9l_x86_64, // R9B
+ lldb_r10l_x86_64, // R10B
+ lldb_r11l_x86_64, // R11B
+ lldb_r12l_x86_64, // R12B
+ lldb_r13l_x86_64, // R13B
+ lldb_r14l_x86_64, // R14B
+ lldb_r15l_x86_64, // R15B
+ lldb_r8w_x86_64, // R8W
+ lldb_r9w_x86_64, // R9W
+ lldb_r10w_x86_64, // R10W
+ lldb_r11w_x86_64, // R11W
+ lldb_r12w_x86_64, // R12W
+ lldb_r13w_x86_64, // R13W
+ lldb_r14w_x86_64, // R14W
+ lldb_r15w_x86_64, // R15W
+ lldb_r8d_x86_64, // R8D
+ lldb_r9d_x86_64, // R9D
+ lldb_r10d_x86_64, // R10D
+ lldb_r11d_x86_64, // R11D
+ lldb_r12d_x86_64, // R12D
+ lldb_r13d_x86_64, // R13D
+ lldb_r14d_x86_64, // R14D
+ lldb_r15d_x86_64, // R15D
+ lldb_ymm0_x86_64, // AMD64_YMM0
+ lldb_ymm1_x86_64, // AMD64_YMM1
+ lldb_ymm2_x86_64, // AMD64_YMM2
+ lldb_ymm3_x86_64, // AMD64_YMM3
+ lldb_ymm4_x86_64, // AMD64_YMM4
+ lldb_ymm5_x86_64, // AMD64_YMM5
+ lldb_ymm6_x86_64, // AMD64_YMM6
+ lldb_ymm7_x86_64, // AMD64_YMM7
+ lldb_ymm8_x86_64, // AMD64_YMM8
+ lldb_ymm9_x86_64, // AMD64_YMM9
+ lldb_ymm10_x86_64, // AMD64_YMM10
+ lldb_ymm11_x86_64, // AMD64_YMM11
+ lldb_ymm12_x86_64, // AMD64_YMM12
+ lldb_ymm13_x86_64, // AMD64_YMM13
+ lldb_ymm14_x86_64, // AMD64_YMM14
+ lldb_ymm15_x86_64, // AMD64_YMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_bnd0_x86_64, // BND0
+ lldb_bnd1_x86_64, // BND1
+ lldb_bnd2_x86_64 // BND2
+};
+
+uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
+ llvm::codeview::RegisterId register_id) {
+ switch (arch_type) {
+ case llvm::Triple::x86:
+ if (static_cast<uint16_t>(register_id) <
+ sizeof(g_code_view_to_lldb_registers_x86) /
+ sizeof(g_code_view_to_lldb_registers_x86[0]))
+ return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>(
+ register_id)];
+
+ switch (register_id) {
+ case llvm::codeview::RegisterId::MXCSR:
+ return lldb_mxcsr_i386;
+ case llvm::codeview::RegisterId::BND0:
+ return lldb_bnd0_i386;
+ case llvm::codeview::RegisterId::BND1:
+ return lldb_bnd1_i386;
+ case llvm::codeview::RegisterId::BND2:
+ return lldb_bnd2_i386;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+ case llvm::Triple::x86_64:
+ if (static_cast<uint16_t>(register_id) <
+ sizeof(g_code_view_to_lldb_registers_x86_64) /
+ sizeof(g_code_view_to_lldb_registers_x86_64[0]))
+ return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>(
+ register_id)];
+
+ return LLDB_INVALID_REGNUM;
+ default:
+ return LLDB_INVALID_REGNUM;
+ }
+}
+
+uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
+ if (register_id == llvm::codeview::RegisterId::VFRAME)
+ return LLDB_REGNUM_GENERIC_FP;
+
+ return LLDB_INVALID_REGNUM;
+}
+
+static uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
+ llvm::codeview::RegisterId register_id,
+ RegisterKind &register_kind) {
+ register_kind = eRegisterKindLLDB;
+ uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
+ if (reg_num != LLDB_INVALID_REGNUM)
+ return reg_num;
+
+ register_kind = eRegisterKindGeneric;
+ return GetGenericRegisterNumber(register_id);
+}
+
+static bool IsSimpleTypeSignedInteger(SimpleTypeKind kind) {
+ switch (kind) {
+ case SimpleTypeKind::Int128:
+ case SimpleTypeKind::Int64:
+ case SimpleTypeKind::Int64Quad:
+ case SimpleTypeKind::Int32:
+ case SimpleTypeKind::Int32Long:
+ case SimpleTypeKind::Int16:
+ case SimpleTypeKind::Int16Short:
+ case SimpleTypeKind::Float128:
+ case SimpleTypeKind::Float80:
+ case SimpleTypeKind::Float64:
+ case SimpleTypeKind::Float32:
+ case SimpleTypeKind::Float16:
+ case SimpleTypeKind::NarrowCharacter:
+ case SimpleTypeKind::SignedCharacter:
+ case SimpleTypeKind::SByte:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static std::pair<size_t, bool> GetIntegralTypeInfo(TypeIndex ti,
+ TpiStream &tpi) {
+ if (ti.isSimple()) {
+ SimpleTypeKind stk = ti.getSimpleKind();
+ return {GetTypeSizeForSimpleKind(stk), IsSimpleTypeSignedInteger(stk)};
+ }
+
+ CVType cvt = tpi.getType(ti);
+ switch (cvt.kind()) {
+ case LF_MODIFIER: {
+ ModifierRecord mfr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(cvt, mfr));
+ return GetIntegralTypeInfo(mfr.ModifiedType, tpi);
+ }
+ case LF_POINTER: {
+ PointerRecord pr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<PointerRecord>(cvt, pr));
+ return GetIntegralTypeInfo(pr.ReferentType, tpi);
+ }
+ case LF_ENUM: {
+ EnumRecord er;
+ llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
+ return GetIntegralTypeInfo(er.UnderlyingType, tpi);
+ }
+ default:
+ assert(false && "Type is not integral!");
+ return {0, false};
+ }
+}
+
+template <typename StreamWriter>
+static DWARFExpression MakeLocationExpressionInternal(lldb::ModuleSP module,
+ StreamWriter &&writer) {
+ const ArchSpec &architecture = module->GetArchitecture();
+ ByteOrder byte_order = architecture.GetByteOrder();
+ uint32_t address_size = architecture.GetAddressByteSize();
+ uint32_t byte_size = architecture.GetDataByteSize();
+ if (byte_order == eByteOrderInvalid || address_size == 0)
+ return DWARFExpression(nullptr);
+
+ RegisterKind register_kind = eRegisterKindDWARF;
+ StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
+
+ if (!writer(stream, register_kind))
+ return DWARFExpression(nullptr);
+
+ DataBufferSP buffer =
+ std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
+ DataExtractor extractor(buffer, byte_order, address_size, byte_size);
+ DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
+ result.SetRegisterKind(register_kind);
+
+ return result;
+}
+
+static DWARFExpression MakeRegisterBasedLocationExpressionInternal(
+ llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset,
+ lldb::ModuleSP module) {
+ return MakeLocationExpressionInternal(
+ module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
+ uint32_t reg_num = GetRegisterNumber(
+ module->GetArchitecture().GetMachine(), reg, register_kind);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ return false;
+
+ if (reg_num > 31) {
+ llvm::dwarf::LocationAtom base = relative_offset
+ ? llvm::dwarf::DW_OP_bregx
+ : llvm::dwarf::DW_OP_regx;
+ stream.PutHex8(base);
+ stream.PutULEB128(reg_num);
+ } else {
+ llvm::dwarf::LocationAtom base = relative_offset
+ ? llvm::dwarf::DW_OP_breg0
+ : llvm::dwarf::DW_OP_reg0;
+ stream.PutHex8(base + reg_num);
+ }
+
+ if (relative_offset)
+ stream.PutSLEB128(*relative_offset);
+
+ return true;
+ });
+}
+
+DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpression(
+ llvm::codeview::RegisterId reg, lldb::ModuleSP module) {
+ return MakeRegisterBasedLocationExpressionInternal(reg, llvm::None, module);
+}
+
+DWARFExpression lldb_private::npdb::MakeRegRelLocationExpression(
+ llvm::codeview::RegisterId reg, int32_t offset, lldb::ModuleSP module) {
+ return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);
+}
+
+DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(
+ uint16_t section, uint32_t offset, ModuleSP module) {
+ assert(section > 0);
+ assert(module);
+
+ return MakeLocationExpressionInternal(
+ module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
+ stream.PutHex8(llvm::dwarf::DW_OP_addr);
+
+ SectionList *section_list = module->GetSectionList();
+ assert(section_list);
+
+ // Section indices in PDB are 1-based, but in DWARF they are 0-based, so
+ // we need to subtract 1.
+ uint32_t section_idx = section - 1;
+ if (section_idx >= section_list->GetSize())
+ return false;
+
+ auto section_ptr = section_list->GetSectionAtIndex(section_idx);
+ if (!section_ptr)
+ return false;
+
+ stream.PutMaxHex64(section_ptr->GetFileAddress() + offset,
+ stream.GetAddressByteSize(), stream.GetByteOrder());
+
+ return true;
+ });
+}
+
+DWARFExpression lldb_private::npdb::MakeConstantLocationExpression(
+ TypeIndex underlying_ti, TpiStream &tpi, const llvm::APSInt &constant,
+ ModuleSP module) {
+ const ArchSpec &architecture = module->GetArchitecture();
+ uint32_t address_size = architecture.GetAddressByteSize();
+
+ size_t size = 0;
+ bool is_signed = false;
+ std::tie(size, is_signed) = GetIntegralTypeInfo(underlying_ti, tpi);
+
+ union {
+ llvm::support::little64_t I;
+ llvm::support::ulittle64_t U;
+ } Value;
+
+ std::shared_ptr<DataBufferHeap> buffer = std::make_shared<DataBufferHeap>();
+ buffer->SetByteSize(size);
+
+ llvm::ArrayRef<uint8_t> bytes;
+ if (is_signed) {
+ Value.I = constant.getSExtValue();
+ } else {
+ Value.U = constant.getZExtValue();
+ }
+
+ bytes = llvm::makeArrayRef(reinterpret_cast<const uint8_t *>(&Value), 8)
+ .take_front(size);
+ buffer->CopyData(bytes.data(), size);
+ DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
+ DWARFExpression result(nullptr, extractor, nullptr, 0, size);
+ return result;
+}
diff --git a/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
new file mode 100644
index 000000000000..670e95ee8e3c
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
@@ -0,0 +1,42 @@
+//===-- DWARFLocationExpression.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_PLUGINS_SYMBOLFILE_NATIVEPDB_DWARFLOCATIONEXPRESSION_H
+#define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_DWARFLOCATIONEXPRESSION_H
+
+#include "lldb/lldb-forward.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+
+namespace llvm {
+class APSInt;
+namespace codeview {
+class TypeIndex;
+}
+namespace pdb {
+class TpiStream;
+}
+} // namespace llvm
+namespace lldb_private {
+namespace npdb {
+DWARFExpression
+MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg,
+ lldb::ModuleSP module);
+
+DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg,
+ int32_t offset,
+ lldb::ModuleSP module);
+DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset,
+ lldb::ModuleSP module);
+DWARFExpression MakeConstantLocationExpression(
+ llvm::codeview::TypeIndex underlying_ti, llvm::pdb::TpiStream &tpi,
+ const llvm::APSInt &constant, lldb::ModuleSP module);
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
new file mode 100644
index 000000000000..8917fd092385
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -0,0 +1,1348 @@
+#include "PdbAstBuilder.h"
+
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Demangle/MicrosoftDemangle.h"
+
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangUtil.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include "PdbUtil.h"
+#include "UdtRecordCompleter.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static llvm::Optional<PdbCompilandSymId> FindSymbolScope(PdbIndex &index,
+ PdbCompilandSymId id) {
+ CVSymbol sym = index.ReadSymbolRecord(id);
+ if (symbolOpensScope(sym.kind())) {
+ // If this exact symbol opens a scope, we can just directly access its
+ // parent.
+ id.offset = getScopeParentOffset(sym);
+ // Global symbols have parent offset of 0. Return llvm::None to indicate
+ // this.
+ if (id.offset == 0)
+ return llvm::None;
+ return id;
+ }
+
+ // Otherwise we need to start at the beginning and iterate forward until we
+ // reach (or pass) this particular symbol
+ CompilandIndexItem &cii = index.compilands().GetOrCreateCompiland(id.modi);
+ const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+
+ auto begin = syms.begin();
+ auto end = syms.at(id.offset);
+ std::vector<PdbCompilandSymId> scope_stack;
+
+ while (begin != end) {
+ if (id.offset == begin.offset()) {
+ // We have a match! Return the top of the stack
+ if (scope_stack.empty())
+ return llvm::None;
+ return scope_stack.back();
+ }
+ if (begin.offset() > id.offset) {
+ // We passed it. We couldn't even find this symbol record.
+ lldbassert(false && "Invalid compiland symbol id!");
+ return llvm::None;
+ }
+
+ // We haven't found the symbol yet. Check if we need to open or close the
+ // scope stack.
+ if (symbolOpensScope(begin->kind())) {
+ // We can use the end offset of the scope to determine whether or not
+ // we can just outright skip this entire scope.
+ uint32_t scope_end = getScopeEndOffset(*begin);
+ if (scope_end < id.modi) {
+ begin = syms.at(scope_end);
+ } else {
+ // The symbol we're looking for is somewhere in this scope.
+ scope_stack.emplace_back(id.modi, begin.offset());
+ }
+ } else if (symbolEndsScope(begin->kind())) {
+ scope_stack.pop_back();
+ }
+ ++begin;
+ }
+
+ return llvm::None;
+}
+
+static clang::TagTypeKind TranslateUdtKind(const TagRecord &cr) {
+ switch (cr.Kind) {
+ case TypeRecordKind::Class:
+ return clang::TTK_Class;
+ case TypeRecordKind::Struct:
+ return clang::TTK_Struct;
+ case TypeRecordKind::Union:
+ return clang::TTK_Union;
+ case TypeRecordKind::Interface:
+ return clang::TTK_Interface;
+ case TypeRecordKind::Enum:
+ return clang::TTK_Enum;
+ default:
+ lldbassert(false && "Invalid tag record kind!");
+ return clang::TTK_Struct;
+ }
+}
+
+static bool IsCVarArgsFunction(llvm::ArrayRef<TypeIndex> args) {
+ if (args.empty())
+ return false;
+ return args.back() == TypeIndex::None();
+}
+
+static bool
+AnyScopesHaveTemplateParams(llvm::ArrayRef<llvm::ms_demangle::Node *> scopes) {
+ for (llvm::ms_demangle::Node *n : scopes) {
+ auto *idn = static_cast<llvm::ms_demangle::IdentifierNode *>(n);
+ if (idn->TemplateParams)
+ return true;
+ }
+ return false;
+}
+
+static ClangASTContext &GetClangASTContext(ObjectFile &obj) {
+ TypeSystem *ts =
+ obj.GetModule()->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ lldbassert(ts);
+ return static_cast<ClangASTContext &>(*ts);
+}
+
+static llvm::Optional<clang::CallingConv>
+TranslateCallingConvention(llvm::codeview::CallingConvention conv) {
+ using CC = llvm::codeview::CallingConvention;
+ switch (conv) {
+
+ case CC::NearC:
+ case CC::FarC:
+ return clang::CallingConv::CC_C;
+ case CC::NearPascal:
+ case CC::FarPascal:
+ return clang::CallingConv::CC_X86Pascal;
+ case CC::NearFast:
+ case CC::FarFast:
+ return clang::CallingConv::CC_X86FastCall;
+ case CC::NearStdCall:
+ case CC::FarStdCall:
+ return clang::CallingConv::CC_X86StdCall;
+ case CC::ThisCall:
+ return clang::CallingConv::CC_X86ThisCall;
+ case CC::NearVector:
+ return clang::CallingConv::CC_X86VectorCall;
+ default:
+ return llvm::None;
+ }
+}
+
+static llvm::Optional<CVTagRecord>
+GetNestedTagDefinition(const NestedTypeRecord &Record,
+ const CVTagRecord &parent, TpiStream &tpi) {
+ // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it
+ // is also used to indicate the primary definition of a nested class. That is
+ // to say, if you have:
+ // struct A {
+ // struct B {};
+ // using C = B;
+ // };
+ // Then in the debug info, this will appear as:
+ // LF_STRUCTURE `A::B` [type index = N]
+ // LF_STRUCTURE `A`
+ // LF_NESTTYPE [name = `B`, index = N]
+ // LF_NESTTYPE [name = `C`, index = N]
+ // In order to accurately reconstruct the decl context hierarchy, we need to
+ // know which ones are actual definitions and which ones are just aliases.
+
+ // If it's a simple type, then this is something like `using foo = int`.
+ if (Record.Type.isSimple())
+ return llvm::None;
+
+ CVType cvt = tpi.getType(Record.Type);
+
+ if (!IsTagRecord(cvt))
+ return llvm::None;
+
+ // If it's an inner definition, then treat whatever name we have here as a
+ // single component of a mangled name. So we can inject it into the parent's
+ // mangled name to see if it matches.
+ CVTagRecord child = CVTagRecord::create(cvt);
+ std::string qname = parent.asTag().getUniqueName();
+ if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4)
+ return llvm::None;
+
+ // qname[3] is the tag type identifier (struct, class, union, etc). Since the
+ // inner tag type is not necessarily the same as the outer tag type, re-write
+ // it to match the inner tag type.
+ qname[3] = child.asTag().getUniqueName()[3];
+ std::string piece;
+ if (qname[3] == 'W')
+ piece = "4";
+ piece += Record.Name;
+ piece.push_back('@');
+ qname.insert(4, std::move(piece));
+ if (qname != child.asTag().UniqueName)
+ return llvm::None;
+
+ return std::move(child);
+}
+
+PdbAstBuilder::PdbAstBuilder(ObjectFile &obj, PdbIndex &index)
+ : m_index(index), m_clang(GetClangASTContext(obj)) {
+ BuildParentMap();
+}
+
+clang::DeclContext &PdbAstBuilder::GetTranslationUnitDecl() {
+ return *m_clang.GetTranslationUnitDecl();
+}
+
+std::pair<clang::DeclContext *, std::string>
+PdbAstBuilder::CreateDeclInfoForType(const TagRecord &record, TypeIndex ti) {
+ // FIXME: Move this to GetDeclContextContainingUID.
+ if (!record.hasUniqueName())
+ return CreateDeclInfoForUndecoratedName(record.Name);
+
+ llvm::ms_demangle::Demangler demangler;
+ StringView sv(record.UniqueName.begin(), record.UniqueName.size());
+ llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
+ if (demangler.Error)
+ return {m_clang.GetTranslationUnitDecl(), record.UniqueName};
+
+ llvm::ms_demangle::IdentifierNode *idn =
+ ttn->QualifiedName->getUnqualifiedIdentifier();
+ std::string uname = idn->toString(llvm::ms_demangle::OF_NoTagSpecifier);
+
+ llvm::ms_demangle::NodeArrayNode *name_components =
+ ttn->QualifiedName->Components;
+ llvm::ArrayRef<llvm::ms_demangle::Node *> scopes(name_components->Nodes,
+ name_components->Count - 1);
+
+ clang::DeclContext *context = m_clang.GetTranslationUnitDecl();
+
+ // If this type doesn't have a parent type in the debug info, then the best we
+ // can do is to say that it's either a series of namespaces (if the scope is
+ // non-empty), or the translation unit (if the scope is empty).
+ auto parent_iter = m_parent_types.find(ti);
+ if (parent_iter == m_parent_types.end()) {
+ if (scopes.empty())
+ return {context, uname};
+
+ // If there is no parent in the debug info, but some of the scopes have
+ // template params, then this is a case of bad debug info. See, for
+ // example, llvm.org/pr39607. We don't want to create an ambiguity between
+ // a NamespaceDecl and a CXXRecordDecl, so instead we create a class at
+ // global scope with the fully qualified name.
+ if (AnyScopesHaveTemplateParams(scopes))
+ return {context, record.Name};
+
+ for (llvm::ms_demangle::Node *scope : scopes) {
+ auto *nii = static_cast<llvm::ms_demangle::NamedIdentifierNode *>(scope);
+ std::string str = nii->toString();
+ context = m_clang.GetUniqueNamespaceDeclaration(str.c_str(), context);
+ }
+ return {context, uname};
+ }
+
+ // Otherwise, all we need to do is get the parent type of this type and
+ // recurse into our lazy type creation / AST reconstruction logic to get an
+ // LLDB TypeSP for the parent. This will cause the AST to automatically get
+ // the right DeclContext created for any parent.
+ clang::QualType parent_qt = GetOrCreateType(parent_iter->second);
+
+ context = clang::TagDecl::castToDeclContext(parent_qt->getAsTagDecl());
+ return {context, uname};
+}
+
+void PdbAstBuilder::BuildParentMap() {
+ LazyRandomTypeCollection &types = m_index.tpi().typeCollection();
+
+ llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full;
+ llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward;
+
+ struct RecordIndices {
+ TypeIndex forward;
+ TypeIndex full;
+ };
+
+ llvm::StringMap<RecordIndices> record_indices;
+
+ for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+ CVType type = types.getType(*ti);
+ if (!IsTagRecord(type))
+ continue;
+
+ CVTagRecord tag = CVTagRecord::create(type);
+
+ RecordIndices &indices = record_indices[tag.asTag().getUniqueName()];
+ if (tag.asTag().isForwardRef())
+ indices.forward = *ti;
+ else
+ indices.full = *ti;
+
+ if (indices.full != TypeIndex::None() &&
+ indices.forward != TypeIndex::None()) {
+ forward_to_full[indices.forward] = indices.full;
+ full_to_forward[indices.full] = indices.forward;
+ }
+
+ // We're looking for LF_NESTTYPE records in the field list, so ignore
+ // forward references (no field list), and anything without a nested class
+ // (since there won't be any LF_NESTTYPE records).
+ if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass())
+ continue;
+
+ struct ProcessTpiStream : public TypeVisitorCallbacks {
+ ProcessTpiStream(PdbIndex &index, TypeIndex parent,
+ const CVTagRecord &parent_cvt,
+ llvm::DenseMap<TypeIndex, TypeIndex> &parents)
+ : index(index), parents(parents), parent(parent),
+ parent_cvt(parent_cvt) {}
+
+ PdbIndex &index;
+ llvm::DenseMap<TypeIndex, TypeIndex> &parents;
+
+ unsigned unnamed_type_index = 1;
+ TypeIndex parent;
+ const CVTagRecord &parent_cvt;
+
+ llvm::Error visitKnownMember(CVMemberRecord &CVR,
+ NestedTypeRecord &Record) override {
+ std::string unnamed_type_name;
+ if (Record.Name.empty()) {
+ unnamed_type_name =
+ llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str();
+ Record.Name = unnamed_type_name;
+ ++unnamed_type_index;
+ }
+ llvm::Optional<CVTagRecord> tag =
+ GetNestedTagDefinition(Record, parent_cvt, index.tpi());
+ if (!tag)
+ return llvm::ErrorSuccess();
+
+ parents[Record.Type] = parent;
+ return llvm::ErrorSuccess();
+ }
+ };
+
+ CVType field_list = m_index.tpi().getType(tag.asTag().FieldList);
+ ProcessTpiStream process(m_index, *ti, tag, m_parent_types);
+ llvm::Error error = visitMemberRecordStream(field_list.data(), process);
+ if (error)
+ llvm::consumeError(std::move(error));
+ }
+
+ // Now that we know the forward -> full mapping of all type indices, we can
+ // re-write all the indices. At the end of this process, we want a mapping
+ // consisting of fwd -> full and full -> full for all child -> parent indices.
+ // We can re-write the values in place, but for the keys, we must save them
+ // off so that we don't modify the map in place while also iterating it.
+ std::vector<TypeIndex> full_keys;
+ std::vector<TypeIndex> fwd_keys;
+ for (auto &entry : m_parent_types) {
+ TypeIndex key = entry.first;
+ TypeIndex value = entry.second;
+
+ auto iter = forward_to_full.find(value);
+ if (iter != forward_to_full.end())
+ entry.second = iter->second;
+
+ iter = forward_to_full.find(key);
+ if (iter != forward_to_full.end())
+ fwd_keys.push_back(key);
+ else
+ full_keys.push_back(key);
+ }
+ for (TypeIndex fwd : fwd_keys) {
+ TypeIndex full = forward_to_full[fwd];
+ m_parent_types[full] = m_parent_types[fwd];
+ }
+ for (TypeIndex full : full_keys) {
+ TypeIndex fwd = full_to_forward[full];
+ m_parent_types[fwd] = m_parent_types[full];
+ }
+
+ // Now that
+}
+
+static bool isLocalVariableType(SymbolKind K) {
+ switch (K) {
+ case S_REGISTER:
+ case S_REGREL32:
+ case S_LOCAL:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static std::string
+RenderScopeList(llvm::ArrayRef<llvm::ms_demangle::Node *> nodes) {
+ lldbassert(!nodes.empty());
+
+ std::string result = nodes.front()->toString();
+ nodes = nodes.drop_front();
+ while (!nodes.empty()) {
+ result += "::";
+ result += nodes.front()->toString(llvm::ms_demangle::OF_NoTagSpecifier);
+ nodes = nodes.drop_front();
+ }
+ return result;
+}
+
+static llvm::Optional<PublicSym32> FindPublicSym(const SegmentOffset &addr,
+ SymbolStream &syms,
+ PublicsStream &publics) {
+ llvm::FixedStreamArray<ulittle32_t> addr_map = publics.getAddressMap();
+ auto iter = std::lower_bound(
+ addr_map.begin(), addr_map.end(), addr,
+ [&](const ulittle32_t &x, const SegmentOffset &y) {
+ CVSymbol s1 = syms.readRecord(x);
+ lldbassert(s1.kind() == S_PUB32);
+ PublicSym32 p1;
+ llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(s1, p1));
+ if (p1.Segment < y.segment)
+ return true;
+ return p1.Offset < y.offset;
+ });
+ if (iter == addr_map.end())
+ return llvm::None;
+ CVSymbol sym = syms.readRecord(*iter);
+ lldbassert(sym.kind() == S_PUB32);
+ PublicSym32 p;
+ llvm::cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(sym, p));
+ if (p.Segment == addr.segment && p.Offset == addr.offset)
+ return p;
+ return llvm::None;
+}
+
+clang::Decl *PdbAstBuilder::GetOrCreateSymbolForId(PdbCompilandSymId id) {
+ CVSymbol cvs = m_index.ReadSymbolRecord(id);
+
+ if (isLocalVariableType(cvs.kind())) {
+ clang::DeclContext *scope = GetParentDeclContext(id);
+ clang::Decl *scope_decl = clang::Decl::castFromDeclContext(scope);
+ PdbCompilandSymId scope_id(id.modi, m_decl_to_status[scope_decl].uid);
+ return GetOrCreateVariableDecl(scope_id, id);
+ }
+
+ switch (cvs.kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ return GetOrCreateFunctionDecl(id);
+ case S_GDATA32:
+ case S_LDATA32:
+ case S_GTHREAD32:
+ case S_CONSTANT:
+ // global variable
+ return nullptr;
+ case S_BLOCK32:
+ return GetOrCreateBlockDecl(id);
+ default:
+ return nullptr;
+ }
+}
+
+clang::Decl *PdbAstBuilder::GetOrCreateDeclForUid(PdbSymUid uid) {
+ if (clang::Decl *result = TryGetDecl(uid))
+ return result;
+
+ clang::Decl *result = nullptr;
+ switch (uid.kind()) {
+ case PdbSymUidKind::CompilandSym:
+ result = GetOrCreateSymbolForId(uid.asCompilandSym());
+ break;
+ case PdbSymUidKind::Type: {
+ clang::QualType qt = GetOrCreateType(uid.asTypeSym());
+ if (auto *tag = qt->getAsTagDecl()) {
+ result = tag;
+ break;
+ }
+ return nullptr;
+ }
+ default:
+ return nullptr;
+ }
+ m_uid_to_decl[toOpaqueUid(uid)] = result;
+ return result;
+}
+
+clang::DeclContext *PdbAstBuilder::GetOrCreateDeclContextForUid(PdbSymUid uid) {
+ if (uid.kind() == PdbSymUidKind::CompilandSym) {
+ if (uid.asCompilandSym().offset == 0)
+ return &GetTranslationUnitDecl();
+ }
+
+ clang::Decl *decl = GetOrCreateDeclForUid(uid);
+ if (!decl)
+ return nullptr;
+
+ return clang::Decl::castToDeclContext(decl);
+}
+
+std::pair<clang::DeclContext *, std::string>
+PdbAstBuilder::CreateDeclInfoForUndecoratedName(llvm::StringRef name) {
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+ clang::DeclContext *context = &GetTranslationUnitDecl();
+
+ llvm::StringRef uname = specs.back().GetBaseName();
+ specs = specs.drop_back();
+ if (specs.empty())
+ return {context, name};
+
+ llvm::StringRef scope_name = specs.back().GetFullName();
+
+ // It might be a class name, try that first.
+ std::vector<TypeIndex> types = m_index.tpi().findRecordsByName(scope_name);
+ while (!types.empty()) {
+ clang::QualType qt = GetOrCreateType(types.back());
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ if (tag)
+ return {clang::TagDecl::castToDeclContext(tag), uname};
+ types.pop_back();
+ }
+
+ // If that fails, treat it as a series of namespaces.
+ for (const MSVCUndecoratedNameSpecifier &spec : specs) {
+ std::string ns_name = spec.GetBaseName().str();
+ context = m_clang.GetUniqueNamespaceDeclaration(ns_name.c_str(), context);
+ }
+ return {context, uname};
+}
+
+clang::DeclContext *
+PdbAstBuilder::GetParentDeclContextForSymbol(const CVSymbol &sym) {
+ if (!SymbolHasAddress(sym))
+ return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+ SegmentOffset addr = GetSegmentAndOffset(sym);
+ llvm::Optional<PublicSym32> pub =
+ FindPublicSym(addr, m_index.symrecords(), m_index.publics());
+ if (!pub)
+ return CreateDeclInfoForUndecoratedName(getSymbolName(sym)).first;
+
+ llvm::ms_demangle::Demangler demangler;
+ StringView name{pub->Name.begin(), pub->Name.size()};
+ llvm::ms_demangle::SymbolNode *node = demangler.parse(name);
+ if (!node)
+ return &GetTranslationUnitDecl();
+ llvm::ArrayRef<llvm::ms_demangle::Node *> name_components{
+ node->Name->Components->Nodes, node->Name->Components->Count - 1};
+
+ if (!name_components.empty()) {
+ // Render the current list of scope nodes as a fully qualified name, and
+ // look it up in the debug info as a type name. If we find something,
+ // this is a type (which may itself be prefixed by a namespace). If we
+ // don't, this is a list of namespaces.
+ std::string qname = RenderScopeList(name_components);
+ std::vector<TypeIndex> matches = m_index.tpi().findRecordsByName(qname);
+ while (!matches.empty()) {
+ clang::QualType qt = GetOrCreateType(matches.back());
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ if (tag)
+ return clang::TagDecl::castToDeclContext(tag);
+ matches.pop_back();
+ }
+ }
+
+ // It's not a type. It must be a series of namespaces.
+ clang::DeclContext *context = &GetTranslationUnitDecl();
+ while (!name_components.empty()) {
+ std::string ns = name_components.front()->toString();
+ context = m_clang.GetUniqueNamespaceDeclaration(ns.c_str(), context);
+ name_components = name_components.drop_front();
+ }
+ return context;
+}
+
+clang::DeclContext *PdbAstBuilder::GetParentDeclContext(PdbSymUid uid) {
+ // We must do this *without* calling GetOrCreate on the current uid, as
+ // that would be an infinite recursion.
+ switch (uid.kind()) {
+ case PdbSymUidKind::CompilandSym: {
+ llvm::Optional<PdbCompilandSymId> scope =
+ FindSymbolScope(m_index, uid.asCompilandSym());
+ if (scope)
+ return GetOrCreateDeclContextForUid(*scope);
+
+ CVSymbol sym = m_index.ReadSymbolRecord(uid.asCompilandSym());
+ return GetParentDeclContextForSymbol(sym);
+ }
+ case PdbSymUidKind::Type: {
+ // It could be a namespace, class, or global. We don't support nested
+ // functions yet. Anyway, we just need to consult the parent type map.
+ PdbTypeSymId type_id = uid.asTypeSym();
+ auto iter = m_parent_types.find(type_id.index);
+ if (iter == m_parent_types.end())
+ return &GetTranslationUnitDecl();
+ return GetOrCreateDeclContextForUid(PdbTypeSymId(iter->second));
+ }
+ case PdbSymUidKind::FieldListMember:
+ // In this case the parent DeclContext is the one for the class that this
+ // member is inside of.
+ break;
+ case PdbSymUidKind::GlobalSym: {
+ // If this refers to a compiland symbol, just recurse in with that symbol.
+ // The only other possibilities are S_CONSTANT and S_UDT, in which case we
+ // need to parse the undecorated name to figure out the scope, then look
+ // that up in the TPI stream. If it's found, it's a type, othewrise it's
+ // a series of namespaces.
+ // FIXME: do this.
+ CVSymbol global = m_index.ReadSymbolRecord(uid.asGlobalSym());
+ switch (global.kind()) {
+ case SymbolKind::S_GDATA32:
+ case SymbolKind::S_LDATA32:
+ return GetParentDeclContextForSymbol(global);
+ case SymbolKind::S_PROCREF:
+ case SymbolKind::S_LPROCREF: {
+ ProcRefSym ref{global.kind()};
+ llvm::cantFail(
+ SymbolDeserializer::deserializeAs<ProcRefSym>(global, ref));
+ PdbCompilandSymId cu_sym_id{ref.modi(), ref.SymOffset};
+ return GetParentDeclContext(cu_sym_id);
+ }
+ case SymbolKind::S_CONSTANT:
+ case SymbolKind::S_UDT:
+ return CreateDeclInfoForUndecoratedName(getSymbolName(global)).first;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return &GetTranslationUnitDecl();
+}
+
+bool PdbAstBuilder::CompleteType(clang::QualType qt) {
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ if (!tag)
+ return false;
+
+ return CompleteTagDecl(*tag);
+}
+
+bool PdbAstBuilder::CompleteTagDecl(clang::TagDecl &tag) {
+ // If this is not in our map, it's an error.
+ auto status_iter = m_decl_to_status.find(&tag);
+ lldbassert(status_iter != m_decl_to_status.end());
+
+ // If it's already complete, just return.
+ DeclStatus &status = status_iter->second;
+ if (status.resolved)
+ return true;
+
+ PdbTypeSymId type_id = PdbSymUid(status.uid).asTypeSym();
+
+ lldbassert(IsTagRecord(type_id, m_index.tpi()));
+
+ clang::QualType tag_qt = m_clang.getASTContext()->getTypeDeclType(&tag);
+ ClangASTContext::SetHasExternalStorage(tag_qt.getAsOpaquePtr(), false);
+
+ TypeIndex tag_ti = type_id.index;
+ CVType cvt = m_index.tpi().getType(tag_ti);
+ if (cvt.kind() == LF_MODIFIER)
+ tag_ti = LookThroughModifierRecord(cvt);
+
+ PdbTypeSymId best_ti = GetBestPossibleDecl(tag_ti, m_index.tpi());
+ cvt = m_index.tpi().getType(best_ti.index);
+ lldbassert(IsTagRecord(cvt));
+
+ if (IsForwardRefUdt(cvt)) {
+ // If we can't find a full decl for this forward ref anywhere in the debug
+ // info, then we have no way to complete it.
+ return false;
+ }
+
+ TypeIndex field_list_ti = GetFieldListIndex(cvt);
+ CVType field_list_cvt = m_index.tpi().getType(field_list_ti);
+ if (field_list_cvt.kind() != LF_FIELDLIST)
+ return false;
+
+ // Visit all members of this class, then perform any finalization necessary
+ // to complete the class.
+ CompilerType ct = ToCompilerType(tag_qt);
+ UdtRecordCompleter completer(best_ti, ct, tag, *this, m_index.tpi());
+ auto error =
+ llvm::codeview::visitMemberRecordStream(field_list_cvt.data(), completer);
+ completer.complete();
+
+ status.resolved = true;
+ if (!error)
+ return true;
+
+ llvm::consumeError(std::move(error));
+ return false;
+}
+
+clang::QualType PdbAstBuilder::CreateSimpleType(TypeIndex ti) {
+ if (ti == TypeIndex::NullptrT())
+ return GetBasicType(lldb::eBasicTypeNullPtr);
+
+ if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
+ clang::QualType direct_type = GetOrCreateType(ti.makeDirect());
+ return m_clang.getASTContext()->getPointerType(direct_type);
+ }
+
+ if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
+ return {};
+
+ lldb::BasicType bt = GetCompilerTypeForSimpleKind(ti.getSimpleKind());
+ if (bt == lldb::eBasicTypeInvalid)
+ return {};
+
+ return GetBasicType(bt);
+}
+
+clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) {
+ clang::QualType pointee_type = GetOrCreateType(pointer.ReferentType);
+
+ // This can happen for pointers to LF_VTSHAPE records, which we shouldn't
+ // create in the AST.
+ if (pointee_type.isNull())
+ return {};
+
+ if (pointer.isPointerToMember()) {
+ MemberPointerInfo mpi = pointer.getMemberInfo();
+ clang::QualType class_type = GetOrCreateType(mpi.ContainingType);
+
+ return m_clang.getASTContext()->getMemberPointerType(
+ pointee_type, class_type.getTypePtr());
+ }
+
+ clang::QualType pointer_type;
+ if (pointer.getMode() == PointerMode::LValueReference)
+ pointer_type =
+ m_clang.getASTContext()->getLValueReferenceType(pointee_type);
+ else if (pointer.getMode() == PointerMode::RValueReference)
+ pointer_type =
+ m_clang.getASTContext()->getRValueReferenceType(pointee_type);
+ else
+ pointer_type = m_clang.getASTContext()->getPointerType(pointee_type);
+
+ if ((pointer.getOptions() & PointerOptions::Const) != PointerOptions::None)
+ pointer_type.addConst();
+
+ if ((pointer.getOptions() & PointerOptions::Volatile) != PointerOptions::None)
+ pointer_type.addVolatile();
+
+ if ((pointer.getOptions() & PointerOptions::Restrict) != PointerOptions::None)
+ pointer_type.addRestrict();
+
+ return pointer_type;
+}
+
+clang::QualType
+PdbAstBuilder::CreateModifierType(const ModifierRecord &modifier) {
+ clang::QualType unmodified_type = GetOrCreateType(modifier.ModifiedType);
+ if (unmodified_type.isNull())
+ return {};
+
+ if ((modifier.Modifiers & ModifierOptions::Const) != ModifierOptions::None)
+ unmodified_type.addConst();
+ if ((modifier.Modifiers & ModifierOptions::Volatile) != ModifierOptions::None)
+ unmodified_type.addVolatile();
+
+ return unmodified_type;
+}
+
+clang::QualType PdbAstBuilder::CreateRecordType(PdbTypeSymId id,
+ const TagRecord &record) {
+ clang::DeclContext *context = nullptr;
+ std::string uname;
+ std::tie(context, uname) = CreateDeclInfoForType(record, id.index);
+ clang::TagTypeKind ttk = TranslateUdtKind(record);
+ lldb::AccessType access =
+ (ttk == clang::TTK_Class) ? lldb::eAccessPrivate : lldb::eAccessPublic;
+
+ ClangASTMetadata metadata;
+ metadata.SetUserID(toOpaqueUid(id));
+ metadata.SetIsDynamicCXXType(false);
+
+ CompilerType ct =
+ m_clang.CreateRecordType(context, access, uname.c_str(), ttk,
+ lldb::eLanguageTypeC_plus_plus, &metadata);
+
+ lldbassert(ct.IsValid());
+
+ ClangASTContext::StartTagDeclarationDefinition(ct);
+
+ // Even if it's possible, don't complete it at this point. Just mark it
+ // forward resolved, and if/when LLDB needs the full definition, it can
+ // ask us.
+ clang::QualType result =
+ clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
+
+ ClangASTContext::SetHasExternalStorage(result.getAsOpaquePtr(), true);
+ return result;
+}
+
+clang::Decl *PdbAstBuilder::TryGetDecl(PdbSymUid uid) const {
+ auto iter = m_uid_to_decl.find(toOpaqueUid(uid));
+ if (iter != m_uid_to_decl.end())
+ return iter->second;
+ return nullptr;
+}
+
+clang::NamespaceDecl *
+PdbAstBuilder::GetOrCreateNamespaceDecl(llvm::StringRef name,
+ clang::DeclContext &context) {
+ return m_clang.GetUniqueNamespaceDeclaration(name.str().c_str(), &context);
+}
+
+clang::BlockDecl *
+PdbAstBuilder::GetOrCreateBlockDecl(PdbCompilandSymId block_id) {
+ if (clang::Decl *decl = TryGetDecl(block_id))
+ return llvm::dyn_cast<clang::BlockDecl>(decl);
+
+ clang::DeclContext *scope = GetParentDeclContext(block_id);
+
+ clang::BlockDecl *block_decl = m_clang.CreateBlockDeclaration(scope);
+ m_uid_to_decl.insert({toOpaqueUid(block_id), block_decl});
+
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(block_id);
+ m_decl_to_status.insert({block_decl, status});
+
+ return block_decl;
+}
+
+clang::VarDecl *PdbAstBuilder::CreateVariableDecl(PdbSymUid uid, CVSymbol sym,
+ clang::DeclContext &scope) {
+ VariableInfo var_info = GetVariableNameInfo(sym);
+ clang::QualType qt = GetOrCreateType(var_info.type);
+
+ clang::VarDecl *var_decl = m_clang.CreateVariableDeclaration(
+ &scope, var_info.name.str().c_str(), qt);
+
+ m_uid_to_decl[toOpaqueUid(uid)] = var_decl;
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(uid);
+ m_decl_to_status.insert({var_decl, status});
+ return var_decl;
+}
+
+clang::VarDecl *
+PdbAstBuilder::GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
+ PdbCompilandSymId var_id) {
+ if (clang::Decl *decl = TryGetDecl(var_id))
+ return llvm::dyn_cast<clang::VarDecl>(decl);
+
+ clang::DeclContext *scope = GetOrCreateDeclContextForUid(scope_id);
+
+ CVSymbol sym = m_index.ReadSymbolRecord(var_id);
+ return CreateVariableDecl(PdbSymUid(var_id), sym, *scope);
+}
+
+clang::VarDecl *PdbAstBuilder::GetOrCreateVariableDecl(PdbGlobalSymId var_id) {
+ if (clang::Decl *decl = TryGetDecl(var_id))
+ return llvm::dyn_cast<clang::VarDecl>(decl);
+
+ CVSymbol sym = m_index.ReadSymbolRecord(var_id);
+ return CreateVariableDecl(PdbSymUid(var_id), sym, GetTranslationUnitDecl());
+}
+
+clang::TypedefNameDecl *
+PdbAstBuilder::GetOrCreateTypedefDecl(PdbGlobalSymId id) {
+ if (clang::Decl *decl = TryGetDecl(id))
+ return llvm::dyn_cast<clang::TypedefNameDecl>(decl);
+
+ CVSymbol sym = m_index.ReadSymbolRecord(id);
+ lldbassert(sym.kind() == S_UDT);
+ UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+
+ clang::DeclContext *scope = GetParentDeclContext(id);
+
+ PdbTypeSymId real_type_id{udt.Type, false};
+ clang::QualType qt = GetOrCreateType(real_type_id);
+
+ std::string uname = DropNameScope(udt.Name);
+
+ CompilerType ct = m_clang.CreateTypedefType(ToCompilerType(qt), uname.c_str(),
+ ToCompilerDeclContext(*scope));
+ clang::TypedefNameDecl *tnd = m_clang.GetAsTypedefDecl(ct);
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(id);
+ m_decl_to_status.insert({tnd, status});
+ return tnd;
+}
+
+clang::QualType PdbAstBuilder::GetBasicType(lldb::BasicType type) {
+ CompilerType ct = m_clang.GetBasicType(type);
+ return clang::QualType::getFromOpaquePtr(ct.GetOpaqueQualType());
+}
+
+clang::QualType PdbAstBuilder::CreateType(PdbTypeSymId type) {
+ if (type.index.isSimple())
+ return CreateSimpleType(type.index);
+
+ CVType cvt = m_index.tpi().getType(type.index);
+
+ if (cvt.kind() == LF_MODIFIER) {
+ ModifierRecord modifier;
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
+ return CreateModifierType(modifier);
+ }
+
+ if (cvt.kind() == LF_POINTER) {
+ PointerRecord pointer;
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
+ return CreatePointerType(pointer);
+ }
+
+ if (IsTagRecord(cvt)) {
+ CVTagRecord tag = CVTagRecord::create(cvt);
+ if (tag.kind() == CVTagRecord::Union)
+ return CreateRecordType(type.index, tag.asUnion());
+ if (tag.kind() == CVTagRecord::Enum)
+ return CreateEnumType(type.index, tag.asEnum());
+ return CreateRecordType(type.index, tag.asClass());
+ }
+
+ if (cvt.kind() == LF_ARRAY) {
+ ArrayRecord ar;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
+ return CreateArrayType(ar);
+ }
+
+ if (cvt.kind() == LF_PROCEDURE) {
+ ProcedureRecord pr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
+ return CreateProcedureType(pr);
+ }
+
+ return {};
+}
+
+clang::QualType PdbAstBuilder::GetOrCreateType(PdbTypeSymId type) {
+ lldb::user_id_t uid = toOpaqueUid(type);
+ auto iter = m_uid_to_type.find(uid);
+ if (iter != m_uid_to_type.end())
+ return iter->second;
+
+ PdbTypeSymId best_type = GetBestPossibleDecl(type, m_index.tpi());
+
+ clang::QualType qt;
+ if (best_type.index != type.index) {
+ // This is a forward decl. Call GetOrCreate on the full decl, then map the
+ // forward decl id to the full decl QualType.
+ clang::QualType qt = GetOrCreateType(best_type);
+ m_uid_to_type[toOpaqueUid(type)] = qt;
+ return qt;
+ }
+
+ // This is either a full decl, or a forward decl with no matching full decl
+ // in the debug info.
+ qt = CreateType(type);
+ m_uid_to_type[toOpaqueUid(type)] = qt;
+ if (IsTagRecord(type, m_index.tpi())) {
+ clang::TagDecl *tag = qt->getAsTagDecl();
+ lldbassert(m_decl_to_status.count(tag) == 0);
+
+ DeclStatus &status = m_decl_to_status[tag];
+ status.uid = uid;
+ status.resolved = false;
+ }
+ return qt;
+}
+
+clang::FunctionDecl *
+PdbAstBuilder::GetOrCreateFunctionDecl(PdbCompilandSymId func_id) {
+ if (clang::Decl *decl = TryGetDecl(func_id))
+ return llvm::dyn_cast<clang::FunctionDecl>(decl);
+
+ clang::DeclContext *parent = GetParentDeclContext(PdbSymUid(func_id));
+ std::string context_name;
+ if (clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(parent)) {
+ context_name = ns->getQualifiedNameAsString();
+ } else if (clang::TagDecl *tag = llvm::dyn_cast<clang::TagDecl>(parent)) {
+ context_name = tag->getQualifiedNameAsString();
+ }
+
+ CVSymbol cvs = m_index.ReadSymbolRecord(func_id);
+ ProcSym proc(static_cast<SymbolRecordKind>(cvs.kind()));
+ llvm::cantFail(SymbolDeserializer::deserializeAs<ProcSym>(cvs, proc));
+
+ PdbTypeSymId type_id(proc.FunctionType);
+ clang::QualType qt = GetOrCreateType(type_id);
+ if (qt.isNull())
+ return nullptr;
+
+ clang::StorageClass storage = clang::SC_None;
+ if (proc.Kind == SymbolRecordKind::ProcSym)
+ storage = clang::SC_Static;
+
+ const clang::FunctionProtoType *func_type =
+ llvm::dyn_cast<clang::FunctionProtoType>(qt);
+
+ CompilerType func_ct = ToCompilerType(qt);
+
+ llvm::StringRef proc_name = proc.Name;
+ proc_name.consume_front(context_name);
+ proc_name.consume_front("::");
+
+ clang::FunctionDecl *function_decl = m_clang.CreateFunctionDeclaration(
+ parent, proc_name.str().c_str(), func_ct, storage, false);
+
+ lldbassert(m_uid_to_decl.count(toOpaqueUid(func_id)) == 0);
+ m_uid_to_decl[toOpaqueUid(func_id)] = function_decl;
+ DeclStatus status;
+ status.resolved = true;
+ status.uid = toOpaqueUid(func_id);
+ m_decl_to_status.insert({function_decl, status});
+
+ CreateFunctionParameters(func_id, *function_decl, func_type->getNumParams());
+
+ return function_decl;
+}
+
+void PdbAstBuilder::CreateFunctionParameters(PdbCompilandSymId func_id,
+ clang::FunctionDecl &function_decl,
+ uint32_t param_count) {
+ CompilandIndexItem *cii = m_index.compilands().GetCompiland(func_id.modi);
+ CVSymbolArray scope =
+ cii->m_debug_stream.getSymbolArrayForScope(func_id.offset);
+
+ auto begin = scope.begin();
+ auto end = scope.end();
+ std::vector<clang::ParmVarDecl *> params;
+ while (begin != end && param_count > 0) {
+ uint32_t record_offset = begin.offset();
+ CVSymbol sym = *begin++;
+
+ TypeIndex param_type;
+ llvm::StringRef param_name;
+ switch (sym.kind()) {
+ case S_REGREL32: {
+ RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+ param_type = reg.Type;
+ param_name = reg.Name;
+ break;
+ }
+ case S_REGISTER: {
+ RegisterSym reg(SymbolRecordKind::RegisterSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+ param_type = reg.Index;
+ param_name = reg.Name;
+ break;
+ }
+ case S_LOCAL: {
+ LocalSym local(SymbolRecordKind::LocalSym);
+ cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+ if ((local.Flags & LocalSymFlags::IsParameter) == LocalSymFlags::None)
+ continue;
+ param_type = local.Type;
+ param_name = local.Name;
+ break;
+ }
+ case S_BLOCK32:
+ // All parameters should come before the first block. If that isn't the
+ // case, then perhaps this is bad debug info that doesn't contain
+ // information about all parameters.
+ return;
+ default:
+ continue;
+ }
+
+ PdbCompilandSymId param_uid(func_id.modi, record_offset);
+ clang::QualType qt = GetOrCreateType(param_type);
+
+ CompilerType param_type_ct(&m_clang, qt.getAsOpaquePtr());
+ clang::ParmVarDecl *param = m_clang.CreateParameterDeclaration(
+ &function_decl, param_name.str().c_str(), param_type_ct,
+ clang::SC_None);
+ lldbassert(m_uid_to_decl.count(toOpaqueUid(param_uid)) == 0);
+
+ m_uid_to_decl[toOpaqueUid(param_uid)] = param;
+ params.push_back(param);
+ --param_count;
+ }
+
+ if (!params.empty())
+ m_clang.SetFunctionParameters(&function_decl, params.data(), params.size());
+}
+
+clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id,
+ const EnumRecord &er) {
+ clang::DeclContext *decl_context = nullptr;
+ std::string uname;
+ std::tie(decl_context, uname) = CreateDeclInfoForType(er, id.index);
+ clang::QualType underlying_type = GetOrCreateType(er.UnderlyingType);
+
+ Declaration declaration;
+ CompilerType enum_ct = m_clang.CreateEnumerationType(
+ uname.c_str(), decl_context, declaration, ToCompilerType(underlying_type),
+ er.isScoped());
+
+ ClangASTContext::StartTagDeclarationDefinition(enum_ct);
+ ClangASTContext::SetHasExternalStorage(enum_ct.GetOpaqueQualType(), true);
+
+ return clang::QualType::getFromOpaquePtr(enum_ct.GetOpaqueQualType());
+}
+
+clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) {
+ clang::QualType element_type = GetOrCreateType(ar.ElementType);
+
+ uint64_t element_count =
+ ar.Size / GetSizeOfType({ar.ElementType}, m_index.tpi());
+
+ CompilerType array_ct = m_clang.CreateArrayType(ToCompilerType(element_type),
+ element_count, false);
+ return clang::QualType::getFromOpaquePtr(array_ct.GetOpaqueQualType());
+}
+
+clang::QualType
+PdbAstBuilder::CreateProcedureType(const ProcedureRecord &proc) {
+ TpiStream &stream = m_index.tpi();
+ CVType args_cvt = stream.getType(proc.ArgumentList);
+ ArgListRecord args;
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<ArgListRecord>(args_cvt, args));
+
+ llvm::ArrayRef<TypeIndex> arg_indices = llvm::makeArrayRef(args.ArgIndices);
+ bool is_variadic = IsCVarArgsFunction(arg_indices);
+ if (is_variadic)
+ arg_indices = arg_indices.drop_back();
+
+ std::vector<CompilerType> arg_types;
+ arg_types.reserve(arg_indices.size());
+
+ for (TypeIndex arg_index : arg_indices) {
+ clang::QualType arg_type = GetOrCreateType(arg_index);
+ arg_types.push_back(ToCompilerType(arg_type));
+ }
+
+ clang::QualType return_type = GetOrCreateType(proc.ReturnType);
+
+ llvm::Optional<clang::CallingConv> cc =
+ TranslateCallingConvention(proc.CallConv);
+ if (!cc)
+ return {};
+
+ CompilerType return_ct = ToCompilerType(return_type);
+ CompilerType func_sig_ast_type = m_clang.CreateFunctionType(
+ return_ct, arg_types.data(), arg_types.size(), is_variadic, 0, *cc);
+
+ return clang::QualType::getFromOpaquePtr(
+ func_sig_ast_type.GetOpaqueQualType());
+}
+
+static bool isTagDecl(clang::DeclContext &context) {
+ return !!llvm::dyn_cast<clang::TagDecl>(&context);
+}
+
+static bool isFunctionDecl(clang::DeclContext &context) {
+ return !!llvm::dyn_cast<clang::FunctionDecl>(&context);
+}
+
+static bool isBlockDecl(clang::DeclContext &context) {
+ return !!llvm::dyn_cast<clang::BlockDecl>(&context);
+}
+
+void PdbAstBuilder::ParseAllNamespacesPlusChildrenOf(
+ llvm::Optional<llvm::StringRef> parent) {
+ TypeIndex ti{m_index.tpi().TypeIndexBegin()};
+ for (const CVType &cvt : m_index.tpi().typeArray()) {
+ PdbTypeSymId tid{ti};
+ ++ti;
+
+ if (!IsTagRecord(cvt))
+ continue;
+
+ CVTagRecord tag = CVTagRecord::create(cvt);
+
+ if (!parent.hasValue()) {
+ clang::QualType qt = GetOrCreateType(tid);
+ CompleteType(qt);
+ continue;
+ }
+
+ // Call CreateDeclInfoForType unconditionally so that the namespace info
+ // gets created. But only call CreateRecordType if the namespace name
+ // matches.
+ clang::DeclContext *context = nullptr;
+ std::string uname;
+ std::tie(context, uname) = CreateDeclInfoForType(tag.asTag(), tid.index);
+ if (!context->isNamespace())
+ continue;
+
+ clang::NamespaceDecl *ns = llvm::dyn_cast<clang::NamespaceDecl>(context);
+ std::string actual_ns = ns->getQualifiedNameAsString();
+ if (llvm::StringRef(actual_ns).startswith(*parent)) {
+ clang::QualType qt = GetOrCreateType(tid);
+ CompleteType(qt);
+ continue;
+ }
+ }
+
+ uint32_t module_count = m_index.dbi().modules().getModuleCount();
+ for (uint16_t modi = 0; modi < module_count; ++modi) {
+ CompilandIndexItem &cii = m_index.compilands().GetOrCreateCompiland(modi);
+ const CVSymbolArray &symbols = cii.m_debug_stream.getSymbolArray();
+ auto iter = symbols.begin();
+ while (iter != symbols.end()) {
+ PdbCompilandSymId sym_id{modi, iter.offset()};
+
+ switch (iter->kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ GetOrCreateFunctionDecl(sym_id);
+ iter = symbols.at(getScopeEndOffset(*iter));
+ break;
+ case S_GDATA32:
+ case S_GTHREAD32:
+ case S_LDATA32:
+ case S_LTHREAD32:
+ GetOrCreateVariableDecl(PdbCompilandSymId(modi, 0), sym_id);
+ ++iter;
+ break;
+ default:
+ ++iter;
+ continue;
+ }
+ }
+ }
+}
+
+static CVSymbolArray skipFunctionParameters(clang::Decl &decl,
+ const CVSymbolArray &symbols) {
+ clang::FunctionDecl *func_decl = llvm::dyn_cast<clang::FunctionDecl>(&decl);
+ if (!func_decl)
+ return symbols;
+ unsigned int params = func_decl->getNumParams();
+ if (params == 0)
+ return symbols;
+
+ CVSymbolArray result = symbols;
+
+ while (!result.empty()) {
+ if (params == 0)
+ return result;
+
+ CVSymbol sym = *result.begin();
+ result.drop_front();
+
+ if (!isLocalVariableType(sym.kind()))
+ continue;
+
+ --params;
+ }
+ return result;
+}
+
+void PdbAstBuilder::ParseBlockChildren(PdbCompilandSymId block_id) {
+ CVSymbol sym = m_index.ReadSymbolRecord(block_id);
+ lldbassert(sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32 ||
+ sym.kind() == S_BLOCK32);
+ CompilandIndexItem &cii =
+ m_index.compilands().GetOrCreateCompiland(block_id.modi);
+ CVSymbolArray symbols =
+ cii.m_debug_stream.getSymbolArrayForScope(block_id.offset);
+
+ // Function parameters should already have been created when the function was
+ // parsed.
+ if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32)
+ symbols =
+ skipFunctionParameters(*m_uid_to_decl[toOpaqueUid(block_id)], symbols);
+
+ auto begin = symbols.begin();
+ while (begin != symbols.end()) {
+ PdbCompilandSymId child_sym_id(block_id.modi, begin.offset());
+ GetOrCreateSymbolForId(child_sym_id);
+ if (begin->kind() == S_BLOCK32) {
+ ParseBlockChildren(child_sym_id);
+ begin = symbols.at(getScopeEndOffset(*begin));
+ }
+ ++begin;
+ }
+}
+
+void PdbAstBuilder::ParseDeclsForSimpleContext(clang::DeclContext &context) {
+
+ clang::Decl *decl = clang::Decl::castFromDeclContext(&context);
+ lldbassert(decl);
+
+ auto iter = m_decl_to_status.find(decl);
+ lldbassert(iter != m_decl_to_status.end());
+
+ if (auto *tag = llvm::dyn_cast<clang::TagDecl>(&context)) {
+ CompleteTagDecl(*tag);
+ return;
+ }
+
+ if (isFunctionDecl(context) || isBlockDecl(context)) {
+ PdbCompilandSymId block_id = PdbSymUid(iter->second.uid).asCompilandSym();
+ ParseBlockChildren(block_id);
+ }
+}
+
+void PdbAstBuilder::ParseDeclsForContext(clang::DeclContext &context) {
+ // Namespaces aren't explicitly represented in the debug info, and the only
+ // way to parse them is to parse all type info, demangling every single type
+ // and trying to reconstruct the DeclContext hierarchy this way. Since this
+ // is an expensive operation, we have to special case it so that we do other
+ // work (such as parsing the items that appear within the namespaces) at the
+ // same time.
+ if (context.isTranslationUnit()) {
+ ParseAllNamespacesPlusChildrenOf(llvm::None);
+ return;
+ }
+
+ if (context.isNamespace()) {
+ clang::NamespaceDecl &ns = *llvm::dyn_cast<clang::NamespaceDecl>(&context);
+ std::string qname = ns.getQualifiedNameAsString();
+ ParseAllNamespacesPlusChildrenOf(llvm::StringRef{qname});
+ return;
+ }
+
+ if (isTagDecl(context) || isFunctionDecl(context) || isBlockDecl(context)) {
+ ParseDeclsForSimpleContext(context);
+ return;
+ }
+}
+
+CompilerDecl PdbAstBuilder::ToCompilerDecl(clang::Decl &decl) {
+ return {&m_clang, &decl};
+}
+
+CompilerType PdbAstBuilder::ToCompilerType(clang::QualType qt) {
+ return {&m_clang, qt.getAsOpaquePtr()};
+}
+
+CompilerDeclContext
+PdbAstBuilder::ToCompilerDeclContext(clang::DeclContext &context) {
+ return {&m_clang, &context};
+}
+
+clang::DeclContext *
+PdbAstBuilder::FromCompilerDeclContext(CompilerDeclContext context) {
+ return static_cast<clang::DeclContext *>(context.GetOpaqueDeclContext());
+}
+
+void PdbAstBuilder::Dump(Stream &stream) { m_clang.Dump(stream); }
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
new file mode 100644
index 000000000000..e3c0346f935e
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.h
@@ -0,0 +1,144 @@
+//===-- PdbAstBuilder.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_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBASTBUILDER_H
+#define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_PDBASTBUILDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/Symbol/ClangASTImporter.h"
+
+#include "PdbIndex.h"
+#include "PdbSymUid.h"
+
+namespace clang {
+class TagDecl;
+class DeclContext;
+class Decl;
+class QualType;
+class FunctionDecl;
+class NamespaceDecl;
+} // namespace clang
+
+namespace llvm {
+namespace codeview {
+class ProcSym;
+}
+} // namespace llvm
+
+namespace lldb_private {
+class ClangASTImporter;
+class ObjectFile;
+
+namespace npdb {
+class PdbIndex;
+struct VariableInfo;
+
+struct DeclStatus {
+ DeclStatus() = default;
+ DeclStatus(lldb::user_id_t uid, bool resolved)
+ : uid(uid), resolved(resolved) {}
+ lldb::user_id_t uid = 0;
+ bool resolved = false;
+};
+
+class PdbAstBuilder {
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ PdbAstBuilder(ObjectFile &obj, PdbIndex &index);
+
+ clang::DeclContext &GetTranslationUnitDecl();
+
+ clang::Decl *GetOrCreateDeclForUid(PdbSymUid uid);
+ clang::DeclContext *GetOrCreateDeclContextForUid(PdbSymUid uid);
+ clang::DeclContext *GetParentDeclContext(PdbSymUid uid);
+
+ clang::NamespaceDecl *GetOrCreateNamespaceDecl(llvm::StringRef name,
+ clang::DeclContext &context);
+ clang::FunctionDecl *GetOrCreateFunctionDecl(PdbCompilandSymId func_id);
+ clang::BlockDecl *GetOrCreateBlockDecl(PdbCompilandSymId block_id);
+ clang::VarDecl *GetOrCreateVariableDecl(PdbCompilandSymId scope_id,
+ PdbCompilandSymId var_id);
+ clang::VarDecl *GetOrCreateVariableDecl(PdbGlobalSymId var_id);
+ clang::TypedefNameDecl *GetOrCreateTypedefDecl(PdbGlobalSymId id);
+ void ParseDeclsForContext(clang::DeclContext &context);
+
+ clang::QualType GetBasicType(lldb::BasicType type);
+ clang::QualType GetOrCreateType(PdbTypeSymId type);
+
+ bool CompleteTagDecl(clang::TagDecl &tag);
+ bool CompleteType(clang::QualType qt);
+
+ CompilerDecl ToCompilerDecl(clang::Decl &decl);
+ CompilerType ToCompilerType(clang::QualType qt);
+ CompilerDeclContext ToCompilerDeclContext(clang::DeclContext &context);
+ clang::DeclContext *FromCompilerDeclContext(CompilerDeclContext context);
+
+ ClangASTContext &clang() { return m_clang; }
+ ClangASTImporter &importer() { return m_importer; }
+
+ void Dump(Stream &stream);
+
+private:
+ clang::Decl *TryGetDecl(PdbSymUid uid) const;
+
+ using TypeIndex = llvm::codeview::TypeIndex;
+
+ clang::QualType
+ CreatePointerType(const llvm::codeview::PointerRecord &pointer);
+ clang::QualType
+ CreateModifierType(const llvm::codeview::ModifierRecord &modifier);
+ clang::QualType CreateArrayType(const llvm::codeview::ArrayRecord &array);
+ clang::QualType CreateRecordType(PdbTypeSymId id,
+ const llvm::codeview::TagRecord &record);
+ clang::QualType CreateEnumType(PdbTypeSymId id,
+ const llvm::codeview::EnumRecord &record);
+ clang::QualType
+ CreateProcedureType(const llvm::codeview::ProcedureRecord &proc);
+ clang::QualType CreateType(PdbTypeSymId type);
+
+ void CreateFunctionParameters(PdbCompilandSymId func_id,
+ clang::FunctionDecl &function_decl,
+ uint32_t param_count);
+ clang::Decl *GetOrCreateSymbolForId(PdbCompilandSymId id);
+ clang::VarDecl *CreateVariableDecl(PdbSymUid uid,
+ llvm::codeview::CVSymbol sym,
+ clang::DeclContext &scope);
+ clang::DeclContext *
+ GetParentDeclContextForSymbol(const llvm::codeview::CVSymbol &sym);
+
+ void ParseAllNamespacesPlusChildrenOf(llvm::Optional<llvm::StringRef> parent);
+ void ParseDeclsForSimpleContext(clang::DeclContext &context);
+ void ParseBlockChildren(PdbCompilandSymId block_id);
+
+ void BuildParentMap();
+ std::pair<clang::DeclContext *, std::string>
+ CreateDeclInfoForType(const llvm::codeview::TagRecord &record, TypeIndex ti);
+ std::pair<clang::DeclContext *, std::string>
+ CreateDeclInfoForUndecoratedName(llvm::StringRef uname);
+ clang::QualType CreateSimpleType(TypeIndex ti);
+
+ PdbIndex &m_index;
+ ClangASTContext &m_clang;
+
+ ClangASTImporter m_importer;
+
+ llvm::DenseMap<TypeIndex, TypeIndex> m_parent_types;
+ llvm::DenseMap<clang::Decl *, DeclStatus> m_decl_to_status;
+ llvm::DenseMap<lldb::user_id_t, clang::Decl *> m_uid_to_decl;
+ llvm::DenseMap<lldb::user_id_t, clang::QualType> m_uid_to_type;
+};
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp b/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
new file mode 100644
index 000000000000..9f5dab6c2e84
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
@@ -0,0 +1,200 @@
+//===-- PdbIndex.cpp --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbIndex.h"
+#include "PdbUtil.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Error.h"
+
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/lldb-defines.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+PdbIndex::PdbIndex() : m_cus(*this), m_va_to_modi(m_allocator) {}
+
+#define ASSIGN_PTR_OR_RETURN(result_ptr, expr) \
+ { \
+ auto expected_result = expr; \
+ if (!expected_result) \
+ return expected_result.takeError(); \
+ result_ptr = &expected_result.get(); \
+ }
+
+llvm::Expected<std::unique_ptr<PdbIndex>>
+PdbIndex::create(std::unique_ptr<llvm::pdb::PDBFile> file) {
+ lldbassert(file);
+
+ std::unique_ptr<PdbIndex> result(new PdbIndex());
+ ASSIGN_PTR_OR_RETURN(result->m_dbi, file->getPDBDbiStream());
+ ASSIGN_PTR_OR_RETURN(result->m_tpi, file->getPDBTpiStream());
+ ASSIGN_PTR_OR_RETURN(result->m_ipi, file->getPDBIpiStream());
+ ASSIGN_PTR_OR_RETURN(result->m_info, file->getPDBInfoStream());
+ ASSIGN_PTR_OR_RETURN(result->m_publics, file->getPDBPublicsStream());
+ ASSIGN_PTR_OR_RETURN(result->m_globals, file->getPDBGlobalsStream());
+ ASSIGN_PTR_OR_RETURN(result->m_symrecords, file->getPDBSymbolStream());
+
+ result->m_tpi->buildHashMap();
+
+ result->m_file = std::move(file);
+
+ return std::move(result);
+}
+
+lldb::addr_t PdbIndex::MakeVirtualAddress(uint16_t segment,
+ uint32_t offset) const {
+ // Segment indices are 1-based.
+ lldbassert(segment > 0);
+
+ uint32_t max_section = dbi().getSectionHeaders().size();
+ lldbassert(segment <= max_section + 1);
+
+ // If this is an absolute symbol, it's indicated by the magic section index
+ // |max_section+1|. In this case, the offset is meaningless, so just return.
+ if (segment == max_section + 1)
+ return LLDB_INVALID_ADDRESS;
+
+ const llvm::object::coff_section &cs = dbi().getSectionHeaders()[segment - 1];
+ return m_load_address + static_cast<lldb::addr_t>(cs.VirtualAddress) +
+ static_cast<lldb::addr_t>(offset);
+}
+
+lldb::addr_t PdbIndex::MakeVirtualAddress(const SegmentOffset &so) const {
+ return MakeVirtualAddress(so.segment, so.offset);
+}
+
+llvm::Optional<uint16_t>
+PdbIndex::GetModuleIndexForAddr(uint16_t segment, uint32_t offset) const {
+ return GetModuleIndexForVa(MakeVirtualAddress(segment, offset));
+}
+
+llvm::Optional<uint16_t> PdbIndex::GetModuleIndexForVa(lldb::addr_t va) const {
+ auto iter = m_va_to_modi.find(va);
+ if (iter == m_va_to_modi.end())
+ return llvm::None;
+
+ return iter.value();
+}
+
+void PdbIndex::ParseSectionContribs() {
+ class Visitor : public ISectionContribVisitor {
+ PdbIndex &m_ctx;
+ llvm::IntervalMap<uint64_t, uint16_t> &m_imap;
+
+ public:
+ Visitor(PdbIndex &ctx, llvm::IntervalMap<uint64_t, uint16_t> &imap)
+ : m_ctx(ctx), m_imap(imap) {}
+
+ void visit(const SectionContrib &C) override {
+ if (C.Size == 0)
+ return;
+
+ uint64_t va = m_ctx.MakeVirtualAddress(C.ISect, C.Off);
+ uint64_t end = va + C.Size;
+ // IntervalMap's start and end represent a closed range, not a half-open
+ // range, so we have to subtract 1.
+ m_imap.insert(va, end - 1, C.Imod);
+ }
+ void visit(const SectionContrib2 &C) override { visit(C.Base); }
+ };
+ Visitor v(*this, m_va_to_modi);
+ dbi().visitSectionContributions(v);
+}
+
+void PdbIndex::BuildAddrToSymbolMap(CompilandIndexItem &cci) {
+ lldbassert(cci.m_symbols_by_va.empty() &&
+ "Addr to symbol map is already built!");
+ uint16_t modi = cci.m_id.modi;
+ const CVSymbolArray &syms = cci.m_debug_stream.getSymbolArray();
+ for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
+ if (!SymbolHasAddress(*iter))
+ continue;
+
+ SegmentOffset so = GetSegmentAndOffset(*iter);
+ lldb::addr_t va = MakeVirtualAddress(so);
+
+ PdbCompilandSymId cu_sym_id(modi, iter.offset());
+
+ // If the debug info is incorrect, we could have multiple symbols with the
+ // same address. So use try_emplace instead of insert, and the first one
+ // will win.
+ cci.m_symbols_by_va.insert(std::make_pair(va, PdbSymUid(cu_sym_id)));
+ }
+}
+
+std::vector<SymbolAndUid> PdbIndex::FindSymbolsByVa(lldb::addr_t va) {
+ std::vector<SymbolAndUid> result;
+
+ llvm::Optional<uint16_t> modi = GetModuleIndexForVa(va);
+ if (!modi)
+ return result;
+
+ CompilandIndexItem &cci = compilands().GetOrCreateCompiland(*modi);
+ if (cci.m_symbols_by_va.empty())
+ BuildAddrToSymbolMap(cci);
+
+ // The map is sorted by starting address of the symbol. So for example
+ // we could (in theory) have this situation
+ //
+ // [------------------]
+ // [----------]
+ // [-----------]
+ // [-------------]
+ // [----]
+ // [-----]
+ // ^ Address we're searching for
+ // In order to find this, we use the upper_bound of the key value which would
+ // be the first symbol whose starting address is higher than the element we're
+ // searching for.
+
+ auto ub = cci.m_symbols_by_va.upper_bound(va);
+
+ for (auto iter = cci.m_symbols_by_va.begin(); iter != ub; ++iter) {
+ PdbCompilandSymId cu_sym_id = iter->second.asCompilandSym();
+ CVSymbol sym = ReadSymbolRecord(cu_sym_id);
+
+ SegmentOffsetLength sol;
+ if (SymbolIsCode(sym))
+ sol = GetSegmentOffsetAndLength(sym);
+ else
+ sol.so = GetSegmentAndOffset(sym);
+
+ lldb::addr_t start = MakeVirtualAddress(sol.so);
+ lldb::addr_t end = start + sol.length;
+ if (va >= start && va < end)
+ result.push_back({std::move(sym), iter->second});
+ }
+
+ return result;
+}
+
+CVSymbol PdbIndex::ReadSymbolRecord(PdbCompilandSymId cu_sym) const {
+ // We need to subtract 4 here to adjust for the codeview debug magic
+ // at the beginning of the debug info stream.
+ const CompilandIndexItem *cci = compilands().GetCompiland(cu_sym.modi);
+ auto iter = cci->m_debug_stream.getSymbolArray().at(cu_sym.offset);
+ lldbassert(iter != cci->m_debug_stream.getSymbolArray().end());
+ return *iter;
+}
+
+CVSymbol PdbIndex::ReadSymbolRecord(PdbGlobalSymId global) const {
+ return symrecords().readRecord(global.offset);
+}
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbIndex.h b/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
new file mode 100644
index 000000000000..839d4e6606e4
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
@@ -0,0 +1,162 @@
+//===-- PdbIndex.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_PLUGINS_SYMBOLFILENATIVEPDB_PDBINDEX_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBINDEX_H
+
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "CompileUnitIndex.h"
+#include "PdbSymUid.h"
+
+#include <map>
+#include <memory>
+
+namespace llvm {
+namespace pdb {
+class DbiStream;
+class TpiStream;
+class TpiStream;
+class InfoStream;
+class PublicsStream;
+class GlobalsStream;
+class SymbolStream;
+} // namespace pdb
+} // namespace llvm
+
+namespace lldb_private {
+namespace npdb {
+struct SegmentOffset;
+
+/// PdbIndex - Lazy access to the important parts of a PDB file.
+///
+/// This is a layer on top of LLVM's native PDB support libraries which cache
+/// certain data when it is accessed the first time. The entire PDB file is
+/// mapped into memory, and the underlying support libraries vend out memory
+/// that is always backed by the file, so it is safe to hold StringRefs and
+/// ArrayRefs into the backing memory as long as the PdbIndex instance is
+/// alive.
+class PdbIndex {
+
+ /// The underlying PDB file.
+ std::unique_ptr<llvm::pdb::PDBFile> m_file;
+
+ /// The DBI stream. This contains general high level information about the
+ /// features present in the PDB file, compile units (such as the information
+ /// necessary to locate full symbol information for each compile unit),
+ /// section contributions, and other data which is not specifically symbol or
+ /// type records.
+ llvm::pdb::DbiStream *m_dbi = nullptr;
+
+ /// TPI (types) and IPI (indices) streams. These are both in the exact same
+ /// format with different data. Most type records are stored in the TPI
+ /// stream but certain specific types of records are stored in the IPI stream.
+ /// The IPI stream records can refer to the records in the TPI stream, but not
+ /// the other way around.
+ llvm::pdb::TpiStream *m_tpi = nullptr;
+ llvm::pdb::TpiStream *m_ipi = nullptr;
+
+ /// This is called the "PDB Stream" in the Microsoft reference implementation.
+ /// It contains information about the structure of the file, as well as fields
+ /// used to match EXE and PDB.
+ llvm::pdb::InfoStream *m_info = nullptr;
+
+ /// Publics stream. Is actually a serialized hash table where the keys are
+ /// addresses of symbols in the executable, and values are a record containing
+ /// mangled names and an index which can be used to locate more detailed info
+ /// about the symbol in the Symbol Records stream. The publics stream only
+ /// contains info about externally visible symbols.
+ llvm::pdb::PublicsStream *m_publics = nullptr;
+
+ /// Globals stream. Contrary to its name, this does not contain information
+ /// about all "global variables" or "global functions". Rather, it is the
+ /// "global symbol table", i.e. it contains information about *every* symbol
+ /// in the executable. It is a hash table keyed on name, whose values are
+ /// indices into the symbol records stream to find the full record.
+ llvm::pdb::GlobalsStream *m_globals = nullptr;
+
+ /// Symbol records stream. The publics and globals stream refer to records
+ /// in this stream. For some records, like constants and typedefs, the
+ /// complete record lives in this stream. For other symbol types, such as
+ /// functions, data, and other things that have been materialied into a
+ /// specific compile unit, the records here simply provide a reference
+ /// necessary to locate the full information.
+ llvm::pdb::SymbolStream *m_symrecords = nullptr;
+
+ /// Index of all compile units, mapping identifier to |CompilandIndexItem|
+ /// instance.
+ CompileUnitIndex m_cus;
+
+ /// An allocator for the interval maps
+ llvm::IntervalMap<lldb::addr_t, uint32_t>::Allocator m_allocator;
+
+ /// Maps virtual address to module index
+ llvm::IntervalMap<lldb::addr_t, uint16_t> m_va_to_modi;
+
+ /// The address at which the program has been loaded into memory.
+ lldb::addr_t m_load_address = 0;
+
+ PdbIndex();
+
+ void BuildAddrToSymbolMap(CompilandIndexItem &cci);
+
+public:
+ static llvm::Expected<std::unique_ptr<PdbIndex>>
+ create(std::unique_ptr<llvm::pdb::PDBFile>);
+
+ void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; }
+ void ParseSectionContribs();
+
+ llvm::pdb::PDBFile &pdb() { return *m_file; }
+ const llvm::pdb::PDBFile &pdb() const { return *m_file; }
+
+ llvm::pdb::DbiStream &dbi() { return *m_dbi; }
+ const llvm::pdb::DbiStream &dbi() const { return *m_dbi; }
+
+ llvm::pdb::TpiStream &tpi() { return *m_tpi; }
+ const llvm::pdb::TpiStream &tpi() const { return *m_tpi; }
+
+ llvm::pdb::TpiStream &ipi() { return *m_ipi; }
+ const llvm::pdb::TpiStream &ipi() const { return *m_ipi; }
+
+ llvm::pdb::InfoStream &info() { return *m_info; }
+ const llvm::pdb::InfoStream &info() const { return *m_info; }
+
+ llvm::pdb::PublicsStream &publics() { return *m_publics; }
+ const llvm::pdb::PublicsStream &publics() const { return *m_publics; }
+
+ llvm::pdb::GlobalsStream &globals() { return *m_globals; }
+ const llvm::pdb::GlobalsStream &globals() const { return *m_globals; }
+
+ llvm::pdb::SymbolStream &symrecords() { return *m_symrecords; }
+ const llvm::pdb::SymbolStream &symrecords() const { return *m_symrecords; }
+
+ CompileUnitIndex &compilands() { return m_cus; }
+ const CompileUnitIndex &compilands() const { return m_cus; }
+
+ lldb::addr_t MakeVirtualAddress(uint16_t segment, uint32_t offset) const;
+ lldb::addr_t MakeVirtualAddress(const SegmentOffset &so) const;
+
+ std::vector<SymbolAndUid> FindSymbolsByVa(lldb::addr_t va);
+
+ llvm::codeview::CVSymbol ReadSymbolRecord(PdbCompilandSymId cu_sym) const;
+ llvm::codeview::CVSymbol ReadSymbolRecord(PdbGlobalSymId global) const;
+
+ llvm::Optional<uint16_t> GetModuleIndexForAddr(uint16_t segment,
+ uint32_t offset) const;
+ llvm::Optional<uint16_t> GetModuleIndexForVa(lldb::addr_t va) const;
+};
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp b/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp
new file mode 100644
index 000000000000..e5424568da47
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbSymUid.cpp
@@ -0,0 +1,161 @@
+//===-- PdbSymUid.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbSymUid.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+
+namespace {
+struct GenericIdRepr {
+ uint64_t tag : 4;
+ uint64_t data : 60;
+};
+
+struct CompilandIdRepr {
+ uint64_t tag : 4;
+ uint64_t modi : 16;
+ uint64_t unused : 44;
+};
+
+struct CompilandSymIdRepr {
+ uint64_t tag : 4;
+ uint64_t modi : 16;
+ uint64_t offset : 32;
+ uint64_t unused : 12;
+};
+
+struct GlobalSymIdRepr {
+ uint64_t tag : 4;
+ uint64_t offset : 32;
+ uint64_t pub : 1;
+ uint64_t unused : 27;
+};
+
+struct TypeSymIdRepr {
+ uint64_t tag : 4;
+ uint64_t index : 32;
+ uint64_t ipi : 1;
+ uint64_t unused : 27;
+};
+
+struct FieldListMemberIdRepr {
+ uint64_t tag : 4;
+ uint64_t index : 32;
+ uint64_t offset : 16;
+ uint64_t unused : 12;
+};
+
+static_assert(sizeof(CompilandIdRepr) == 8, "Invalid structure size!");
+static_assert(sizeof(CompilandSymIdRepr) == 8, "Invalid structure size!");
+static_assert(sizeof(GlobalSymIdRepr) == 8, "Invalid structure size!");
+static_assert(sizeof(TypeSymIdRepr) == 8, "Invalid structure size!");
+static_assert(sizeof(FieldListMemberIdRepr) == 8, "Invalid structure size!");
+} // namespace
+
+template <typename OutT, typename InT> static OutT repr_cast(const InT &value) {
+ OutT result;
+ ::memcpy(&result, &value, sizeof(value));
+ return result;
+}
+
+PdbSymUid::PdbSymUid(const PdbCompilandId &cid) {
+ CompilandIdRepr repr;
+ ::memset(&repr, 0, sizeof(repr));
+ repr.modi = cid.modi;
+ repr.tag = static_cast<uint64_t>(PdbSymUidKind::Compiland);
+ m_repr = repr_cast<uint64_t>(repr);
+}
+
+PdbSymUid::PdbSymUid(const PdbCompilandSymId &csid) {
+ CompilandSymIdRepr repr;
+ ::memset(&repr, 0, sizeof(repr));
+ repr.modi = csid.modi;
+ repr.offset = csid.offset;
+ repr.tag = static_cast<uint64_t>(PdbSymUidKind::CompilandSym);
+ m_repr = repr_cast<uint64_t>(repr);
+}
+
+PdbSymUid::PdbSymUid(const PdbGlobalSymId &gsid) {
+ GlobalSymIdRepr repr;
+ ::memset(&repr, 0, sizeof(repr));
+ repr.pub = gsid.is_public;
+ repr.offset = gsid.offset;
+ repr.tag = static_cast<uint64_t>(PdbSymUidKind::GlobalSym);
+ m_repr = repr_cast<uint64_t>(repr);
+}
+
+PdbSymUid::PdbSymUid(const PdbTypeSymId &tsid) {
+ TypeSymIdRepr repr;
+ ::memset(&repr, 0, sizeof(repr));
+ repr.index = tsid.index.getIndex();
+ repr.ipi = tsid.is_ipi;
+ repr.tag = static_cast<uint64_t>(PdbSymUidKind::Type);
+ m_repr = repr_cast<uint64_t>(repr);
+}
+
+PdbSymUid::PdbSymUid(const PdbFieldListMemberId &flmid) {
+ FieldListMemberIdRepr repr;
+ ::memset(&repr, 0, sizeof(repr));
+ repr.index = flmid.index.getIndex();
+ repr.offset = flmid.offset;
+ repr.tag = static_cast<uint64_t>(PdbSymUidKind::FieldListMember);
+ m_repr = repr_cast<uint64_t>(repr);
+}
+
+PdbSymUidKind PdbSymUid::kind() const {
+ GenericIdRepr generic = repr_cast<GenericIdRepr>(m_repr);
+ return static_cast<PdbSymUidKind>(generic.tag);
+}
+
+PdbCompilandId PdbSymUid::asCompiland() const {
+ assert(kind() == PdbSymUidKind::Compiland);
+ auto repr = repr_cast<CompilandIdRepr>(m_repr);
+ PdbCompilandId result;
+ result.modi = repr.modi;
+ return result;
+}
+
+PdbCompilandSymId PdbSymUid::asCompilandSym() const {
+ assert(kind() == PdbSymUidKind::CompilandSym);
+ auto repr = repr_cast<CompilandSymIdRepr>(m_repr);
+ PdbCompilandSymId result;
+ result.modi = repr.modi;
+ result.offset = repr.offset;
+ return result;
+}
+
+PdbGlobalSymId PdbSymUid::asGlobalSym() const {
+ assert(kind() == PdbSymUidKind::GlobalSym ||
+ kind() == PdbSymUidKind::PublicSym);
+ auto repr = repr_cast<GlobalSymIdRepr>(m_repr);
+ PdbGlobalSymId result;
+ result.is_public = repr.pub;
+ result.offset = repr.offset;
+ return result;
+}
+
+PdbTypeSymId PdbSymUid::asTypeSym() const {
+ assert(kind() == PdbSymUidKind::Type);
+ auto repr = repr_cast<TypeSymIdRepr>(m_repr);
+ PdbTypeSymId result;
+ result.index.setIndex(repr.index);
+ result.is_ipi = repr.ipi;
+ return result;
+}
+
+PdbFieldListMemberId PdbSymUid::asFieldListMember() const {
+ assert(kind() == PdbSymUidKind::FieldListMember);
+ auto repr = repr_cast<FieldListMemberIdRepr>(m_repr);
+ PdbFieldListMemberId result;
+ result.index.setIndex(repr.index);
+ result.offset = repr.offset;
+ return result;
+}
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h b/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
new file mode 100644
index 000000000000..1166bee4e327
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
@@ -0,0 +1,126 @@
+//===-- PdbSymUid.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// A unique identification scheme for Pdb records.
+// The scheme is to partition a 64-bit integer into an 8-bit tag field, which
+// will contain some value from the PDB_SymType enumeration. The format of the
+// other 48-bits depend on the tag, but must be sufficient to locate the
+// corresponding entry in the underlying PDB file quickly. For example, for
+// a compile unit, we use 2 bytes to represent the index, which allows fast
+// access to the compile unit's information.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBSYMUID_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBSYMUID_H
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Support/Compiler.h"
+
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+namespace npdb {
+
+enum class PdbSymUidKind : uint8_t {
+ Compiland,
+ CompilandSym,
+ PublicSym,
+ GlobalSym,
+ Type,
+ FieldListMember
+};
+
+struct PdbCompilandId {
+ // 0-based index of module in PDB
+ uint16_t modi;
+};
+
+struct PdbCompilandSymId {
+ PdbCompilandSymId() = default;
+ PdbCompilandSymId(uint16_t modi, uint32_t offset)
+ : modi(modi), offset(offset) {}
+ // 0-based index of module in PDB
+ uint16_t modi = 0;
+
+ // Offset of symbol's record in module stream. This is
+ // offset by 4 from the CVSymbolArray's notion of offset
+ // due to the debug magic at the beginning of the stream.
+ uint32_t offset = 0;
+};
+
+struct PdbGlobalSymId {
+ PdbGlobalSymId() = default;
+ PdbGlobalSymId(uint32_t offset, bool is_public)
+ : offset(offset), is_public(is_public) {}
+
+ // Offset of symbol's record in globals or publics stream.
+ uint32_t offset = 0;
+
+ // True if this symbol is in the public stream, false if it's in the globals
+ // stream.
+ bool is_public = false;
+};
+
+struct PdbTypeSymId {
+ PdbTypeSymId() = default;
+ PdbTypeSymId(llvm::codeview::TypeIndex index, bool is_ipi = false)
+ : index(index), is_ipi(is_ipi) {}
+
+ // The index of the of the type in the TPI or IPI stream.
+ llvm::codeview::TypeIndex index;
+
+ // True if this symbol comes from the IPI stream, false if it's from the TPI
+ // stream.
+ bool is_ipi = false;
+};
+
+struct PdbFieldListMemberId {
+ // The TypeIndex of the LF_FIELDLIST record.
+ llvm::codeview::TypeIndex index;
+
+ // The offset from the beginning of the LF_FIELDLIST record to this record.
+ uint16_t offset = 0;
+};
+
+class PdbSymUid {
+ uint64_t m_repr = 0;
+
+public:
+ PdbSymUid() = default;
+ PdbSymUid(uint64_t repr) : m_repr(repr) {}
+ PdbSymUid(const PdbCompilandId &cid);
+ PdbSymUid(const PdbCompilandSymId &csid);
+ PdbSymUid(const PdbGlobalSymId &gsid);
+ PdbSymUid(const PdbTypeSymId &tsid);
+ PdbSymUid(const PdbFieldListMemberId &flmid);
+
+ uint64_t toOpaqueId() const { return m_repr; }
+
+ PdbSymUidKind kind() const;
+
+ PdbCompilandId asCompiland() const;
+ PdbCompilandSymId asCompilandSym() const;
+ PdbGlobalSymId asGlobalSym() const;
+ PdbTypeSymId asTypeSym() const;
+ PdbFieldListMemberId asFieldListMember() const;
+};
+
+template <typename T> uint64_t toOpaqueUid(const T &cid) {
+ return PdbSymUid(cid).toOpaqueId();
+}
+
+struct SymbolAndUid {
+ llvm::codeview::CVSymbol sym;
+ PdbSymUid uid;
+};
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
new file mode 100644
index 000000000000..317725dd250e
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -0,0 +1,750 @@
+//===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbUtil.h"
+
+#include "DWARFLocationExpression.h"
+#include "PdbIndex.h"
+#include "PdbSymUid.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/lldb-enumerations.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static Variable::RangeList
+MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
+ llvm::ArrayRef<LocalVariableAddrGap> gaps) {
+ lldb::addr_t start =
+ index.MakeVirtualAddress(range.ISectStart, range.OffsetStart);
+ lldb::addr_t end = start + range.Range;
+
+ Variable::RangeList result;
+ while (!gaps.empty()) {
+ const LocalVariableAddrGap &gap = gaps.front();
+
+ lldb::addr_t size = gap.GapStartOffset - start;
+ result.Append(start, size);
+ start += gap.Range;
+ gaps = gaps.drop_front();
+ }
+
+ result.Append(start, end);
+ return result;
+}
+
+CVTagRecord CVTagRecord::create(CVType type) {
+ assert(IsTagRecord(type) && "type is not a tag record!");
+ switch (type.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE: {
+ ClassRecord cr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(type, cr));
+ return CVTagRecord(std::move(cr));
+ }
+ case LF_UNION: {
+ UnionRecord ur;
+ llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(type, ur));
+ return CVTagRecord(std::move(ur));
+ }
+ case LF_ENUM: {
+ EnumRecord er;
+ llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(type, er));
+ return CVTagRecord(std::move(er));
+ }
+ default:
+ llvm_unreachable("Unreachable!");
+ }
+}
+
+CVTagRecord::CVTagRecord(ClassRecord &&c)
+ : cvclass(std::move(c)),
+ m_kind(cvclass.Kind == TypeRecordKind::Struct ? Struct : Class) {}
+CVTagRecord::CVTagRecord(UnionRecord &&u)
+ : cvunion(std::move(u)), m_kind(Union) {}
+CVTagRecord::CVTagRecord(EnumRecord &&e) : cvenum(std::move(e)), m_kind(Enum) {}
+
+PDB_SymType lldb_private::npdb::CVSymToPDBSym(SymbolKind kind) {
+ switch (kind) {
+ case S_COMPILE3:
+ case S_OBJNAME:
+ return PDB_SymType::CompilandDetails;
+ case S_ENVBLOCK:
+ return PDB_SymType::CompilandEnv;
+ case S_THUNK32:
+ case S_TRAMPOLINE:
+ return PDB_SymType::Thunk;
+ case S_COFFGROUP:
+ return PDB_SymType::CoffGroup;
+ case S_EXPORT:
+ return PDB_SymType::Export;
+ case S_LPROC32:
+ case S_GPROC32:
+ case S_LPROC32_DPC:
+ return PDB_SymType::Function;
+ case S_PUB32:
+ return PDB_SymType::PublicSymbol;
+ case S_INLINESITE:
+ return PDB_SymType::InlineSite;
+ case S_LOCAL:
+ case S_BPREL32:
+ case S_REGREL32:
+ case S_MANCONSTANT:
+ case S_CONSTANT:
+ case S_LDATA32:
+ case S_GDATA32:
+ case S_LMANDATA:
+ case S_GMANDATA:
+ case S_LTHREAD32:
+ case S_GTHREAD32:
+ return PDB_SymType::Data;
+ case S_BLOCK32:
+ return PDB_SymType::Block;
+ case S_LABEL32:
+ return PDB_SymType::Label;
+ case S_CALLSITEINFO:
+ return PDB_SymType::CallSite;
+ case S_HEAPALLOCSITE:
+ return PDB_SymType::HeapAllocationSite;
+ case S_CALLEES:
+ return PDB_SymType::Callee;
+ case S_CALLERS:
+ return PDB_SymType::Caller;
+ default:
+ lldbassert(false && "Invalid symbol record kind!");
+ }
+ return PDB_SymType::None;
+}
+
+PDB_SymType lldb_private::npdb::CVTypeToPDBType(TypeLeafKind kind) {
+ switch (kind) {
+ case LF_ARRAY:
+ return PDB_SymType::ArrayType;
+ case LF_ARGLIST:
+ return PDB_SymType::FunctionSig;
+ case LF_BCLASS:
+ return PDB_SymType::BaseClass;
+ case LF_BINTERFACE:
+ return PDB_SymType::BaseInterface;
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ case LF_UNION:
+ return PDB_SymType::UDT;
+ case LF_POINTER:
+ return PDB_SymType::PointerType;
+ case LF_ENUM:
+ return PDB_SymType::Enum;
+ case LF_PROCEDURE:
+ return PDB_SymType::FunctionSig;
+ case LF_BITFIELD:
+ return PDB_SymType::BuiltinType;
+ default:
+ lldbassert(false && "Invalid type record kind!");
+ }
+ return PDB_SymType::None;
+}
+
+bool lldb_private::npdb::SymbolHasAddress(const CVSymbol &sym) {
+ switch (sym.kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ case S_GPROC32_ID:
+ case S_LPROC32_ID:
+ case S_LPROC32_DPC:
+ case S_LPROC32_DPC_ID:
+ case S_THUNK32:
+ case S_TRAMPOLINE:
+ case S_COFFGROUP:
+ case S_BLOCK32:
+ case S_LABEL32:
+ case S_CALLSITEINFO:
+ case S_HEAPALLOCSITE:
+ case S_LDATA32:
+ case S_GDATA32:
+ case S_LMANDATA:
+ case S_GMANDATA:
+ case S_LTHREAD32:
+ case S_GTHREAD32:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool lldb_private::npdb::SymbolIsCode(const CVSymbol &sym) {
+ switch (sym.kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ case S_GPROC32_ID:
+ case S_LPROC32_ID:
+ case S_LPROC32_DPC:
+ case S_LPROC32_DPC_ID:
+ case S_THUNK32:
+ case S_TRAMPOLINE:
+ case S_COFFGROUP:
+ case S_BLOCK32:
+ return true;
+ default:
+ return false;
+ }
+}
+
+template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
+ RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
+ cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
+ return record;
+}
+
+template <typename RecordT>
+static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) {
+ RecordT record = createRecord<RecordT>(sym);
+ return {record.Segment, record.CodeOffset};
+}
+
+template <>
+SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
+ TrampolineSym record = createRecord<TrampolineSym>(sym);
+ return {record.ThunkSection, record.ThunkOffset};
+}
+
+template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
+ Thunk32Sym record = createRecord<Thunk32Sym>(sym);
+ return {record.Segment, record.Offset};
+}
+
+template <>
+SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
+ CoffGroupSym record = createRecord<CoffGroupSym>(sym);
+ return {record.Segment, record.Offset};
+}
+
+template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
+ DataSym record = createRecord<DataSym>(sym);
+ return {record.Segment, record.DataOffset};
+}
+
+template <>
+SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
+ ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
+ return {record.Segment, record.DataOffset};
+}
+
+SegmentOffset lldb_private::npdb::GetSegmentAndOffset(const CVSymbol &sym) {
+ switch (sym.kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ case S_GPROC32_ID:
+ case S_LPROC32_ID:
+ case S_LPROC32_DPC:
+ case S_LPROC32_DPC_ID:
+ return ::GetSegmentAndOffset<ProcSym>(sym);
+ case S_THUNK32:
+ return ::GetSegmentAndOffset<Thunk32Sym>(sym);
+ break;
+ case S_TRAMPOLINE:
+ return ::GetSegmentAndOffset<TrampolineSym>(sym);
+ break;
+ case S_COFFGROUP:
+ return ::GetSegmentAndOffset<CoffGroupSym>(sym);
+ break;
+ case S_BLOCK32:
+ return ::GetSegmentAndOffset<BlockSym>(sym);
+ break;
+ case S_LABEL32:
+ return ::GetSegmentAndOffset<LabelSym>(sym);
+ break;
+ case S_CALLSITEINFO:
+ return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
+ break;
+ case S_HEAPALLOCSITE:
+ return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
+ break;
+ case S_LDATA32:
+ case S_GDATA32:
+ case S_LMANDATA:
+ case S_GMANDATA:
+ return ::GetSegmentAndOffset<DataSym>(sym);
+ break;
+ case S_LTHREAD32:
+ case S_GTHREAD32:
+ return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
+ break;
+ default:
+ lldbassert(false && "Record does not have a segment/offset!");
+ }
+ return {0, 0};
+}
+
+template <typename RecordT>
+SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) {
+ RecordT record = createRecord<RecordT>(sym);
+ return {record.Segment, record.CodeOffset, record.CodeSize};
+}
+
+template <>
+SegmentOffsetLength
+GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
+ TrampolineSym record = createRecord<TrampolineSym>(sym);
+ return {record.ThunkSection, record.ThunkOffset, record.Size};
+}
+
+template <>
+SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
+ Thunk32Sym record = createRecord<Thunk32Sym>(sym);
+ return SegmentOffsetLength{record.Segment, record.Offset, record.Length};
+}
+
+template <>
+SegmentOffsetLength
+GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
+ CoffGroupSym record = createRecord<CoffGroupSym>(sym);
+ return SegmentOffsetLength{record.Segment, record.Offset, record.Size};
+}
+
+SegmentOffsetLength
+lldb_private::npdb::GetSegmentOffsetAndLength(const CVSymbol &sym) {
+ switch (sym.kind()) {
+ case S_GPROC32:
+ case S_LPROC32:
+ case S_GPROC32_ID:
+ case S_LPROC32_ID:
+ case S_LPROC32_DPC:
+ case S_LPROC32_DPC_ID:
+ return ::GetSegmentOffsetAndLength<ProcSym>(sym);
+ case S_THUNK32:
+ return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
+ break;
+ case S_TRAMPOLINE:
+ return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
+ break;
+ case S_COFFGROUP:
+ return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
+ break;
+ case S_BLOCK32:
+ return ::GetSegmentOffsetAndLength<BlockSym>(sym);
+ break;
+ default:
+ lldbassert(false && "Record does not have a segment/offset/length triple!");
+ }
+ return {0, 0, 0};
+}
+
+bool lldb_private::npdb::IsForwardRefUdt(CVType cvt) {
+ ClassRecord cr;
+ UnionRecord ur;
+ EnumRecord er;
+ switch (cvt.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
+ return cr.isForwardRef();
+ case LF_UNION:
+ llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
+ return ur.isForwardRef();
+ case LF_ENUM:
+ llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
+ return er.isForwardRef();
+ default:
+ return false;
+ }
+}
+
+bool lldb_private::npdb::IsTagRecord(llvm::codeview::CVType cvt) {
+ switch (cvt.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_UNION:
+ case LF_ENUM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool lldb_private::npdb::IsClassStructUnion(llvm::codeview::CVType cvt) {
+ switch (cvt.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_UNION:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool lldb_private::npdb::IsForwardRefUdt(const PdbTypeSymId &id,
+ TpiStream &tpi) {
+ if (id.is_ipi || id.index.isSimple())
+ return false;
+ return IsForwardRefUdt(tpi.getType(id.index));
+}
+
+bool lldb_private::npdb::IsTagRecord(const PdbTypeSymId &id, TpiStream &tpi) {
+ if (id.is_ipi || id.index.isSimple())
+ return false;
+ return IsTagRecord(tpi.getType(id.index));
+}
+
+lldb::AccessType
+lldb_private::npdb::TranslateMemberAccess(MemberAccess access) {
+ switch (access) {
+ case MemberAccess::Private:
+ return lldb::eAccessPrivate;
+ case MemberAccess::Protected:
+ return lldb::eAccessProtected;
+ case MemberAccess::Public:
+ return lldb::eAccessPublic;
+ case MemberAccess::None:
+ return lldb::eAccessNone;
+ }
+ llvm_unreachable("unreachable");
+}
+
+TypeIndex lldb_private::npdb::GetFieldListIndex(CVType cvt) {
+ switch (cvt.kind()) {
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE: {
+ ClassRecord cr;
+ cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
+ return cr.FieldList;
+ }
+ case LF_UNION: {
+ UnionRecord ur;
+ cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
+ return ur.FieldList;
+ }
+ case LF_ENUM: {
+ EnumRecord er;
+ cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
+ return er.FieldList;
+ }
+ default:
+ llvm_unreachable("Unreachable!");
+ }
+}
+
+TypeIndex lldb_private::npdb::LookThroughModifierRecord(CVType modifier) {
+ lldbassert(modifier.kind() == LF_MODIFIER);
+ ModifierRecord mr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ModifierRecord>(modifier, mr));
+ return mr.ModifiedType;
+}
+
+llvm::StringRef lldb_private::npdb::DropNameScope(llvm::StringRef name) {
+ return MSVCUndecoratedNameParser::DropScope(name);
+}
+
+VariableInfo lldb_private::npdb::GetVariableNameInfo(CVSymbol sym) {
+ VariableInfo result;
+
+ if (sym.kind() == S_REGREL32) {
+ RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+ result.type = reg.Type;
+ result.name = reg.Name;
+ return result;
+ }
+
+ if (sym.kind() == S_REGISTER) {
+ RegisterSym reg(SymbolRecordKind::RegisterSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+ result.type = reg.Index;
+ result.name = reg.Name;
+ return result;
+ }
+
+ if (sym.kind() == S_LOCAL) {
+ LocalSym local(SymbolRecordKind::LocalSym);
+ cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+ result.type = local.Type;
+ result.name = local.Name;
+ return result;
+ }
+
+ if (sym.kind() == S_GDATA32 || sym.kind() == S_LDATA32) {
+ DataSym data(SymbolRecordKind::DataSym);
+ cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, data));
+ result.type = data.Type;
+ result.name = data.Name;
+ return result;
+ }
+
+ if (sym.kind() == S_GTHREAD32 || sym.kind() == S_LTHREAD32) {
+ ThreadLocalDataSym data(SymbolRecordKind::ThreadLocalDataSym);
+ cantFail(SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, data));
+ result.type = data.Type;
+ result.name = data.Name;
+ return result;
+ }
+
+ if (sym.kind() == S_CONSTANT) {
+ ConstantSym constant(SymbolRecordKind::ConstantSym);
+ cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(sym, constant));
+ result.type = constant.Type;
+ result.name = constant.Name;
+ return result;
+ }
+
+ lldbassert(false && "Invalid variable record kind!");
+ return {};
+}
+
+VariableInfo lldb_private::npdb::GetVariableLocationInfo(
+ PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) {
+
+ CVSymbol sym = index.ReadSymbolRecord(var_id);
+
+ VariableInfo result = GetVariableNameInfo(sym);
+
+ if (sym.kind() == S_REGREL32) {
+ RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
+ result.location =
+ MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
+ result.ranges.emplace();
+ return result;
+ }
+
+ if (sym.kind() == S_REGISTER) {
+ RegisterSym reg(SymbolRecordKind::RegisterSym);
+ cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
+ result.location = MakeEnregisteredLocationExpression(reg.Register, module);
+ result.ranges.emplace();
+ return result;
+ }
+
+ if (sym.kind() == S_LOCAL) {
+ LocalSym local(SymbolRecordKind::LocalSym);
+ cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+
+ PdbCompilandSymId loc_specifier_id(var_id.modi,
+ var_id.offset + sym.RecordData.size());
+ CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
+ if (loc_specifier_cvs.kind() == S_DEFRANGE_FRAMEPOINTER_REL) {
+ DefRangeFramePointerRelSym loc(
+ SymbolRecordKind::DefRangeFramePointerRelSym);
+ cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
+ loc_specifier_cvs, loc));
+ // FIXME: The register needs to come from the S_FRAMEPROC symbol.
+ result.location =
+ MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module);
+ result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+ } else {
+ // FIXME: Handle other kinds
+ }
+ return result;
+ }
+ llvm_unreachable("Symbol is not a local variable!");
+ return result;
+}
+
+lldb::BasicType
+lldb_private::npdb::GetCompilerTypeForSimpleKind(SimpleTypeKind kind) {
+ switch (kind) {
+ case SimpleTypeKind::Boolean128:
+ case SimpleTypeKind::Boolean16:
+ case SimpleTypeKind::Boolean32:
+ case SimpleTypeKind::Boolean64:
+ case SimpleTypeKind::Boolean8:
+ return lldb::eBasicTypeBool;
+ case SimpleTypeKind::Byte:
+ case SimpleTypeKind::UnsignedCharacter:
+ return lldb::eBasicTypeUnsignedChar;
+ case SimpleTypeKind::NarrowCharacter:
+ return lldb::eBasicTypeChar;
+ case SimpleTypeKind::SignedCharacter:
+ case SimpleTypeKind::SByte:
+ return lldb::eBasicTypeSignedChar;
+ case SimpleTypeKind::Character16:
+ return lldb::eBasicTypeChar16;
+ case SimpleTypeKind::Character32:
+ return lldb::eBasicTypeChar32;
+ case SimpleTypeKind::Complex80:
+ return lldb::eBasicTypeLongDoubleComplex;
+ case SimpleTypeKind::Complex64:
+ return lldb::eBasicTypeDoubleComplex;
+ case SimpleTypeKind::Complex32:
+ return lldb::eBasicTypeFloatComplex;
+ case SimpleTypeKind::Float128:
+ case SimpleTypeKind::Float80:
+ return lldb::eBasicTypeLongDouble;
+ case SimpleTypeKind::Float64:
+ return lldb::eBasicTypeDouble;
+ case SimpleTypeKind::Float32:
+ return lldb::eBasicTypeFloat;
+ case SimpleTypeKind::Float16:
+ return lldb::eBasicTypeHalf;
+ case SimpleTypeKind::Int128:
+ return lldb::eBasicTypeInt128;
+ case SimpleTypeKind::Int64:
+ case SimpleTypeKind::Int64Quad:
+ return lldb::eBasicTypeLongLong;
+ case SimpleTypeKind::Int32:
+ return lldb::eBasicTypeInt;
+ case SimpleTypeKind::Int16:
+ case SimpleTypeKind::Int16Short:
+ return lldb::eBasicTypeShort;
+ case SimpleTypeKind::UInt128:
+ return lldb::eBasicTypeUnsignedInt128;
+ case SimpleTypeKind::UInt64:
+ case SimpleTypeKind::UInt64Quad:
+ return lldb::eBasicTypeUnsignedLongLong;
+ case SimpleTypeKind::HResult:
+ case SimpleTypeKind::UInt32:
+ return lldb::eBasicTypeUnsignedInt;
+ case SimpleTypeKind::UInt16:
+ case SimpleTypeKind::UInt16Short:
+ return lldb::eBasicTypeUnsignedShort;
+ case SimpleTypeKind::Int32Long:
+ return lldb::eBasicTypeLong;
+ case SimpleTypeKind::UInt32Long:
+ return lldb::eBasicTypeUnsignedLong;
+ case SimpleTypeKind::Void:
+ return lldb::eBasicTypeVoid;
+ case SimpleTypeKind::WideCharacter:
+ return lldb::eBasicTypeWChar;
+ default:
+ return lldb::eBasicTypeInvalid;
+ }
+}
+
+size_t lldb_private::npdb::GetTypeSizeForSimpleKind(SimpleTypeKind kind) {
+ switch (kind) {
+ case SimpleTypeKind::Boolean128:
+ case SimpleTypeKind::Int128:
+ case SimpleTypeKind::UInt128:
+ case SimpleTypeKind::Float128:
+ return 16;
+ case SimpleTypeKind::Complex80:
+ case SimpleTypeKind::Float80:
+ return 10;
+ case SimpleTypeKind::Boolean64:
+ case SimpleTypeKind::Complex64:
+ case SimpleTypeKind::UInt64:
+ case SimpleTypeKind::UInt64Quad:
+ case SimpleTypeKind::Float64:
+ case SimpleTypeKind::Int64:
+ case SimpleTypeKind::Int64Quad:
+ return 8;
+ case SimpleTypeKind::Boolean32:
+ case SimpleTypeKind::Character32:
+ case SimpleTypeKind::Complex32:
+ case SimpleTypeKind::Float32:
+ case SimpleTypeKind::Int32:
+ case SimpleTypeKind::Int32Long:
+ case SimpleTypeKind::UInt32Long:
+ case SimpleTypeKind::HResult:
+ case SimpleTypeKind::UInt32:
+ return 4;
+ case SimpleTypeKind::Boolean16:
+ case SimpleTypeKind::Character16:
+ case SimpleTypeKind::Float16:
+ case SimpleTypeKind::Int16:
+ case SimpleTypeKind::Int16Short:
+ case SimpleTypeKind::UInt16:
+ case SimpleTypeKind::UInt16Short:
+ case SimpleTypeKind::WideCharacter:
+ return 2;
+ case SimpleTypeKind::Boolean8:
+ case SimpleTypeKind::Byte:
+ case SimpleTypeKind::UnsignedCharacter:
+ case SimpleTypeKind::NarrowCharacter:
+ case SimpleTypeKind::SignedCharacter:
+ case SimpleTypeKind::SByte:
+ return 1;
+ case SimpleTypeKind::Void:
+ default:
+ return 0;
+ }
+}
+
+PdbTypeSymId lldb_private::npdb::GetBestPossibleDecl(PdbTypeSymId id,
+ TpiStream &tpi) {
+ if (id.index.isSimple())
+ return id;
+
+ CVType cvt = tpi.getType(id.index);
+
+ // Only tag records have a best and a worst record.
+ if (!IsTagRecord(cvt))
+ return id;
+
+ // Tag records that are not forward decls are full decls, hence they are the
+ // best.
+ if (!IsForwardRefUdt(cvt))
+ return id;
+
+ return llvm::cantFail(tpi.findFullDeclForForwardRef(id.index));
+}
+
+template <typename RecordType> static size_t GetSizeOfTypeInternal(CVType cvt) {
+ RecordType record;
+ llvm::cantFail(TypeDeserializer::deserializeAs<RecordType>(cvt, record));
+ return record.getSize();
+}
+
+size_t lldb_private::npdb::GetSizeOfType(PdbTypeSymId id,
+ llvm::pdb::TpiStream &tpi) {
+ if (id.index.isSimple()) {
+ switch (id.index.getSimpleMode()) {
+ case SimpleTypeMode::Direct:
+ return GetTypeSizeForSimpleKind(id.index.getSimpleKind());
+ case SimpleTypeMode::NearPointer32:
+ case SimpleTypeMode::FarPointer32:
+ return 4;
+ case SimpleTypeMode::NearPointer64:
+ return 8;
+ case SimpleTypeMode::NearPointer128:
+ return 16;
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ TypeIndex index = id.index;
+ if (IsForwardRefUdt(index, tpi))
+ index = llvm::cantFail(tpi.findFullDeclForForwardRef(index));
+
+ CVType cvt = tpi.getType(index);
+ switch (cvt.kind()) {
+ case LF_MODIFIER:
+ return GetSizeOfType({LookThroughModifierRecord(cvt)}, tpi);
+ case LF_ENUM: {
+ EnumRecord record;
+ llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, record));
+ return GetSizeOfType({record.UnderlyingType}, tpi);
+ }
+ case LF_POINTER:
+ return GetSizeOfTypeInternal<PointerRecord>(cvt);
+ case LF_ARRAY:
+ return GetSizeOfTypeInternal<ArrayRecord>(cvt);
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ case LF_INTERFACE:
+ return GetSizeOfTypeInternal<ClassRecord>(cvt);
+ case LF_UNION:
+ return GetSizeOfTypeInternal<UnionRecord>(cvt);
+ default:
+ break;
+ }
+ return 0;
+}
diff --git a/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
new file mode 100644
index 000000000000..570c300b6a2b
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -0,0 +1,159 @@
+//===-- PdbUtil.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_PLUGINS_SYMBOLFILENATIVEPDB_PDBUTIL_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBUTIL_H
+
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/lldb-enumerations.h"
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "PdbSymUid.h"
+
+#include <tuple>
+#include <utility>
+
+namespace llvm {
+namespace pdb {
+class TpiStream;
+}
+} // namespace llvm
+
+namespace lldb_private {
+namespace npdb {
+
+class PdbIndex;
+
+struct CVTagRecord {
+ enum Kind { Class, Struct, Union, Enum };
+
+ static CVTagRecord create(llvm::codeview::CVType type);
+
+ Kind kind() const { return m_kind; }
+
+ const llvm::codeview::TagRecord &asTag() const {
+ if (m_kind == Struct || m_kind == Class)
+ return cvclass;
+ if (m_kind == Enum)
+ return cvenum;
+ return cvunion;
+ }
+
+ const llvm::codeview::ClassRecord &asClass() const {
+ assert(m_kind == Struct || m_kind == Class);
+ return cvclass;
+ }
+
+ const llvm::codeview::EnumRecord &asEnum() const {
+ assert(m_kind == Enum);
+ return cvenum;
+ }
+
+ const llvm::codeview::UnionRecord &asUnion() const {
+ assert(m_kind == Union);
+ return cvunion;
+ }
+
+ llvm::StringRef name() const {
+ if (m_kind == Struct || m_kind == Union)
+ return cvclass.Name;
+ if (m_kind == Enum)
+ return cvenum.Name;
+ return cvunion.Name;
+ }
+
+private:
+ CVTagRecord(llvm::codeview::ClassRecord &&c);
+ CVTagRecord(llvm::codeview::UnionRecord &&u);
+ CVTagRecord(llvm::codeview::EnumRecord &&e);
+ union {
+ llvm::codeview::ClassRecord cvclass;
+ llvm::codeview::EnumRecord cvenum;
+ llvm::codeview::UnionRecord cvunion;
+ };
+ Kind m_kind;
+};
+
+struct SegmentOffset {
+ SegmentOffset() = default;
+ SegmentOffset(uint16_t s, uint32_t o) : segment(s), offset(o) {}
+ uint16_t segment = 0;
+ uint32_t offset = 0;
+};
+
+struct SegmentOffsetLength {
+ SegmentOffsetLength() = default;
+ SegmentOffsetLength(uint16_t s, uint32_t o, uint32_t l)
+ : so(s, o), length(l) {}
+ SegmentOffset so;
+ uint32_t length = 0;
+};
+
+struct VariableInfo {
+ llvm::StringRef name;
+ llvm::codeview::TypeIndex type;
+ llvm::Optional<DWARFExpression> location;
+ llvm::Optional<Variable::RangeList> ranges;
+};
+
+llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind);
+llvm::pdb::PDB_SymType CVTypeToPDBType(llvm::codeview::TypeLeafKind kind);
+
+bool SymbolHasAddress(const llvm::codeview::CVSymbol &sym);
+bool SymbolIsCode(const llvm::codeview::CVSymbol &sym);
+
+SegmentOffset GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym);
+SegmentOffsetLength
+GetSegmentOffsetAndLength(const llvm::codeview::CVSymbol &sym);
+
+template <typename RecordT> bool IsValidRecord(const RecordT &sym) {
+ return true;
+}
+
+inline bool IsValidRecord(const llvm::codeview::ProcRefSym &sym) {
+ // S_PROCREF symbols have 1-based module indices.
+ return sym.Module > 0;
+}
+
+bool IsForwardRefUdt(llvm::codeview::CVType cvt);
+bool IsTagRecord(llvm::codeview::CVType cvt);
+bool IsClassStructUnion(llvm::codeview::CVType cvt);
+
+bool IsForwardRefUdt(const PdbTypeSymId &id, llvm::pdb::TpiStream &tpi);
+bool IsTagRecord(const PdbTypeSymId &id, llvm::pdb::TpiStream &tpi);
+
+lldb::AccessType TranslateMemberAccess(llvm::codeview::MemberAccess access);
+llvm::codeview::TypeIndex GetFieldListIndex(llvm::codeview::CVType cvt);
+llvm::codeview::TypeIndex
+LookThroughModifierRecord(llvm::codeview::CVType modifier);
+
+llvm::StringRef DropNameScope(llvm::StringRef name);
+
+VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol);
+VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id,
+ lldb::ModuleSP module);
+
+size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
+lldb::BasicType
+GetCompilerTypeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
+
+PdbTypeSymId GetBestPossibleDecl(PdbTypeSymId id, llvm::pdb::TpiStream &tpi);
+
+size_t GetSizeOfType(PdbTypeSymId id, llvm::pdb::TpiStream &tpi);
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
new file mode 100644
index 000000000000..7e97e2b37724
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -0,0 +1,1571 @@
+//===-- SymbolFileNativePDB.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileNativePDB.h"
+
+#include "clang/AST/Attr.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Type.h"
+
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamBuffer.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/ClangUtil.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Demangle/MicrosoftDemangle.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include "DWARFLocationExpression.h"
+#include "PdbAstBuilder.h"
+#include "PdbSymUid.h"
+#include "PdbUtil.h"
+#include "UdtRecordCompleter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
+ switch (lang) {
+ case PDB_Lang::Cpp:
+ return lldb::LanguageType::eLanguageTypeC_plus_plus;
+ case PDB_Lang::C:
+ return lldb::LanguageType::eLanguageTypeC;
+ default:
+ return lldb::LanguageType::eLanguageTypeUnknown;
+ }
+}
+
+static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath,
+ llvm::BumpPtrAllocator &Allocator) {
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
+ llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
+ /*RequiresNullTerminator=*/false);
+ if (!ErrorOrBuffer)
+ return nullptr;
+ std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
+
+ llvm::StringRef Path = Buffer->getBufferIdentifier();
+ auto Stream = llvm::make_unique<llvm::MemoryBufferByteStream>(
+ std::move(Buffer), llvm::support::little);
+
+ auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
+ if (auto EC = File->parseFileHeaders()) {
+ llvm::consumeError(std::move(EC));
+ return nullptr;
+ }
+ if (auto EC = File->parseStreamData()) {
+ llvm::consumeError(std::move(EC));
+ return nullptr;
+ }
+
+ return File;
+}
+
+static std::unique_ptr<PDBFile>
+loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
+ // Try to find a matching PDB for an EXE.
+ using namespace llvm::object;
+ auto expected_binary = createBinary(exe_path);
+
+ // If the file isn't a PE/COFF executable, fail.
+ if (!expected_binary) {
+ llvm::consumeError(expected_binary.takeError());
+ return nullptr;
+ }
+ OwningBinary<Binary> binary = std::move(*expected_binary);
+
+ auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
+ if (!obj)
+ return nullptr;
+ const llvm::codeview::DebugInfo *pdb_info = nullptr;
+
+ // If it doesn't have a debug directory, fail.
+ llvm::StringRef pdb_file;
+ auto ec = obj->getDebugPDBInfo(pdb_info, pdb_file);
+ if (ec)
+ return nullptr;
+
+ // if the file doesn't exist, is not a pdb, or doesn't have a matching guid,
+ // fail.
+ llvm::file_magic magic;
+ ec = llvm::identify_magic(pdb_file, magic);
+ if (ec || magic != llvm::file_magic::pdb)
+ return nullptr;
+ std::unique_ptr<PDBFile> pdb = loadPDBFile(pdb_file, allocator);
+ if (!pdb)
+ return nullptr;
+
+ auto expected_info = pdb->getPDBInfoStream();
+ if (!expected_info) {
+ llvm::consumeError(expected_info.takeError());
+ return nullptr;
+ }
+ llvm::codeview::GUID guid;
+ memcpy(&guid, pdb_info->PDB70.Signature, 16);
+
+ if (expected_info->getGuid() != guid)
+ return nullptr;
+ return pdb;
+}
+
+static bool IsFunctionPrologue(const CompilandIndexItem &cci,
+ lldb::addr_t addr) {
+ // FIXME: Implement this.
+ return false;
+}
+
+static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
+ lldb::addr_t addr) {
+ // FIXME: Implement this.
+ return false;
+}
+
+static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) {
+ switch (kind) {
+ case SimpleTypeKind::Boolean128:
+ case SimpleTypeKind::Boolean16:
+ case SimpleTypeKind::Boolean32:
+ case SimpleTypeKind::Boolean64:
+ case SimpleTypeKind::Boolean8:
+ return "bool";
+ case SimpleTypeKind::Byte:
+ case SimpleTypeKind::UnsignedCharacter:
+ return "unsigned char";
+ case SimpleTypeKind::NarrowCharacter:
+ return "char";
+ case SimpleTypeKind::SignedCharacter:
+ case SimpleTypeKind::SByte:
+ return "signed char";
+ case SimpleTypeKind::Character16:
+ return "char16_t";
+ case SimpleTypeKind::Character32:
+ return "char32_t";
+ case SimpleTypeKind::Complex80:
+ case SimpleTypeKind::Complex64:
+ case SimpleTypeKind::Complex32:
+ return "complex";
+ case SimpleTypeKind::Float128:
+ case SimpleTypeKind::Float80:
+ return "long double";
+ case SimpleTypeKind::Float64:
+ return "double";
+ case SimpleTypeKind::Float32:
+ return "float";
+ case SimpleTypeKind::Float16:
+ return "single";
+ case SimpleTypeKind::Int128:
+ return "__int128";
+ case SimpleTypeKind::Int64:
+ case SimpleTypeKind::Int64Quad:
+ return "int64_t";
+ case SimpleTypeKind::Int32:
+ return "int";
+ case SimpleTypeKind::Int16:
+ return "short";
+ case SimpleTypeKind::UInt128:
+ return "unsigned __int128";
+ case SimpleTypeKind::UInt64:
+ case SimpleTypeKind::UInt64Quad:
+ return "uint64_t";
+ case SimpleTypeKind::HResult:
+ return "HRESULT";
+ case SimpleTypeKind::UInt32:
+ return "unsigned";
+ case SimpleTypeKind::UInt16:
+ case SimpleTypeKind::UInt16Short:
+ return "unsigned short";
+ case SimpleTypeKind::Int32Long:
+ return "long";
+ case SimpleTypeKind::UInt32Long:
+ return "unsigned long";
+ case SimpleTypeKind::Void:
+ return "void";
+ case SimpleTypeKind::WideCharacter:
+ return "wchar_t";
+ default:
+ return "";
+ }
+}
+
+static bool IsClassRecord(TypeLeafKind kind) {
+ switch (kind) {
+ case LF_STRUCTURE:
+ case LF_CLASS:
+ case LF_INTERFACE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void SymbolFileNativePDB::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+}
+
+void SymbolFileNativePDB::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {}
+
+ConstString SymbolFileNativePDB::GetPluginNameStatic() {
+ static ConstString g_name("native-pdb");
+ return g_name;
+}
+
+const char *SymbolFileNativePDB::GetPluginDescriptionStatic() {
+ return "Microsoft PDB debug symbol cross-platform file reader.";
+}
+
+SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFile *obj_file) {
+ return new SymbolFileNativePDB(obj_file);
+}
+
+SymbolFileNativePDB::SymbolFileNativePDB(ObjectFile *object_file)
+ : SymbolFile(object_file) {}
+
+SymbolFileNativePDB::~SymbolFileNativePDB() {}
+
+uint32_t SymbolFileNativePDB::CalculateAbilities() {
+ uint32_t abilities = 0;
+ if (!m_obj_file)
+ return 0;
+
+ if (!m_index) {
+ // Lazily load and match the PDB file, but only do this once.
+ std::unique_ptr<PDBFile> file_up =
+ loadMatchingPDBFile(m_obj_file->GetFileSpec().GetPath(), m_allocator);
+
+ if (!file_up) {
+ auto module_sp = m_obj_file->GetModule();
+ if (!module_sp)
+ return 0;
+ // See if any symbol file is specified through `--symfile` option.
+ FileSpec symfile = module_sp->GetSymbolFileFileSpec();
+ if (!symfile)
+ return 0;
+ file_up = loadPDBFile(symfile.GetPath(), m_allocator);
+ }
+
+ if (!file_up)
+ return 0;
+
+ auto expected_index = PdbIndex::create(std::move(file_up));
+ if (!expected_index) {
+ llvm::consumeError(expected_index.takeError());
+ return 0;
+ }
+ m_index = std::move(*expected_index);
+ }
+ if (!m_index)
+ return 0;
+
+ // We don't especially have to be precise here. We only distinguish between
+ // stripped and not stripped.
+ abilities = kAllAbilities;
+
+ if (m_index->dbi().isStripped())
+ abilities &= ~(Blocks | LocalVariables);
+ return abilities;
+}
+
+void SymbolFileNativePDB::InitializeObject() {
+ m_obj_load_address = m_obj_file->GetFileOffset();
+ m_index->SetLoadAddress(m_obj_load_address);
+ m_index->ParseSectionContribs();
+
+ TypeSystem *ts = m_obj_file->GetModule()->GetTypeSystemForLanguage(
+ lldb::eLanguageTypeC_plus_plus);
+ if (ts)
+ ts->SetSymbolFile(this);
+
+ m_ast = llvm::make_unique<PdbAstBuilder>(*m_obj_file, *m_index);
+}
+
+uint32_t SymbolFileNativePDB::GetNumCompileUnits() {
+ const DbiModuleList &modules = m_index->dbi().modules();
+ uint32_t count = modules.getModuleCount();
+ if (count == 0)
+ return count;
+
+ // The linker can inject an additional "dummy" compilation unit into the
+ // PDB. Ignore this special compile unit for our purposes, if it is there.
+ // It is always the last one.
+ DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
+ if (last.getModuleName() == "* Linker *")
+ --count;
+ return count;
+}
+
+Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) {
+ CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
+ CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
+
+ if (sym.kind() == S_GPROC32 || sym.kind() == S_LPROC32) {
+ // This is a function. It must be global. Creating the Function entry for
+ // it automatically creates a block for it.
+ CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii);
+ return GetOrCreateFunction(block_id, *comp_unit)->GetBlock(false);
+ }
+
+ lldbassert(sym.kind() == S_BLOCK32);
+
+ // This is a block. Its parent is either a function or another block. In
+ // either case, its parent can be viewed as a block (e.g. a function contains
+ // 1 big block. So just get the parent block and add this block to it.
+ BlockSym block(static_cast<SymbolRecordKind>(sym.kind()));
+ cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block));
+ lldbassert(block.Parent != 0);
+ PdbCompilandSymId parent_id(block_id.modi, block.Parent);
+ Block &parent_block = GetOrCreateBlock(parent_id);
+ lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id);
+ BlockSP child_block = std::make_shared<Block>(opaque_block_uid);
+ parent_block.AddChild(child_block);
+
+ m_ast->GetOrCreateBlockDecl(block_id);
+
+ m_blocks.insert({opaque_block_uid, child_block});
+ return *child_block;
+}
+
+lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
+ CompileUnit &comp_unit) {
+ const CompilandIndexItem *cci =
+ m_index->compilands().GetCompiland(func_id.modi);
+ lldbassert(cci);
+ CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
+
+ lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
+ SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record);
+
+ auto file_vm_addr = m_index->MakeVirtualAddress(sol.so);
+ if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+ return nullptr;
+
+ AddressRange func_range(file_vm_addr, sol.length,
+ comp_unit.GetModule()->GetSectionList());
+ if (!func_range.GetBaseAddress().IsValid())
+ return nullptr;
+
+ ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
+ cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
+ if (proc.FunctionType == TypeIndex::None())
+ return nullptr;
+ TypeSP func_type = GetOrCreateType(proc.FunctionType);
+ if (!func_type)
+ return nullptr;
+
+ PdbTypeSymId sig_id(proc.FunctionType, false);
+ Mangled mangled(proc.Name);
+ FunctionSP func_sp = std::make_shared<Function>(
+ &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
+ func_type.get(), func_range);
+
+ comp_unit.AddFunction(func_sp);
+
+ m_ast->GetOrCreateFunctionDecl(func_id);
+
+ return func_sp;
+}
+
+CompUnitSP
+SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
+ lldb::LanguageType lang =
+ cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
+ : lldb::eLanguageTypeUnknown;
+
+ LazyBool optimized = eLazyBoolNo;
+ if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
+ optimized = eLazyBoolYes;
+
+ llvm::SmallString<64> source_file_name =
+ m_index->compilands().GetMainSourceFile(cci);
+ FileSpec fs(source_file_name);
+
+ CompUnitSP cu_sp =
+ std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, fs,
+ toOpaqueUid(cci.m_id), lang, optimized);
+
+ m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(
+ cci.m_id.modi, cu_sp);
+ return cu_sp;
+}
+
+lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id,
+ const ModifierRecord &mr,
+ CompilerType ct) {
+ TpiStream &stream = m_index->tpi();
+
+ std::string name;
+ if (mr.ModifiedType.isSimple())
+ name = GetSimpleTypeName(mr.ModifiedType.getSimpleKind());
+ else
+ name = computeTypeName(stream.typeCollection(), mr.ModifiedType);
+ Declaration decl;
+ lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType);
+
+ return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(name),
+ modified_type->GetByteSize(), nullptr,
+ LLDB_INVALID_UID, Type::eEncodingIsUID, decl,
+ ct, Type::eResolveStateFull);
+}
+
+lldb::TypeSP
+SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id,
+ const llvm::codeview::PointerRecord &pr,
+ CompilerType ct) {
+ TypeSP pointee = GetOrCreateType(pr.ReferentType);
+ if (!pointee)
+ return nullptr;
+
+ if (pr.isPointerToMember()) {
+ MemberPointerInfo mpi = pr.getMemberInfo();
+ GetOrCreateType(mpi.ContainingType);
+ }
+
+ Declaration decl;
+ return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(),
+ pr.getSize(), nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct,
+ Type::eResolveStateFull);
+}
+
+lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti,
+ CompilerType ct) {
+ uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false));
+ if (ti == TypeIndex::NullptrT()) {
+ Declaration decl;
+ return std::make_shared<Type>(
+ uid, this, ConstString("std::nullptr_t"), 0, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
+ }
+
+ if (ti.getSimpleMode() != SimpleTypeMode::Direct) {
+ TypeSP direct_sp = GetOrCreateType(ti.makeDirect());
+ uint32_t pointer_size = 0;
+ switch (ti.getSimpleMode()) {
+ case SimpleTypeMode::FarPointer32:
+ case SimpleTypeMode::NearPointer32:
+ pointer_size = 4;
+ break;
+ case SimpleTypeMode::NearPointer64:
+ pointer_size = 8;
+ break;
+ default:
+ // 128-bit and 16-bit pointers unsupported.
+ return nullptr;
+ }
+ Declaration decl;
+ return std::make_shared<Type>(
+ uid, this, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct, Type::eResolveStateFull);
+ }
+
+ if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated)
+ return nullptr;
+
+ size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind());
+ llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind());
+
+ Declaration decl;
+ return std::make_shared<Type>(uid, this, ConstString(type_name), size,
+ nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID,
+ decl, ct, Type::eResolveStateFull);
+}
+
+static std::string GetUnqualifiedTypeName(const TagRecord &record) {
+ if (!record.hasUniqueName()) {
+ MSVCUndecoratedNameParser parser(record.Name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+
+ return specs.back().GetBaseName();
+ }
+
+ llvm::ms_demangle::Demangler demangler;
+ StringView sv(record.UniqueName.begin(), record.UniqueName.size());
+ llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv);
+ if (demangler.Error)
+ return record.Name;
+
+ llvm::ms_demangle::IdentifierNode *idn =
+ ttn->QualifiedName->getUnqualifiedIdentifier();
+ return idn->toString();
+}
+
+lldb::TypeSP
+SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id,
+ const TagRecord &record,
+ size_t size, CompilerType ct) {
+
+ std::string uname = GetUnqualifiedTypeName(record);
+
+ // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE.
+ Declaration decl;
+ return std::make_shared<Type>(toOpaqueUid(type_id), this, ConstString(uname),
+ size, nullptr, LLDB_INVALID_UID,
+ Type::eEncodingIsUID, decl, ct,
+ Type::eResolveStateForward);
+}
+
+lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
+ const ClassRecord &cr,
+ CompilerType ct) {
+ return CreateClassStructUnion(type_id, cr, cr.getSize(), ct);
+}
+
+lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
+ const UnionRecord &ur,
+ CompilerType ct) {
+ return CreateClassStructUnion(type_id, ur, ur.getSize(), ct);
+}
+
+lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id,
+ const EnumRecord &er,
+ CompilerType ct) {
+ std::string uname = GetUnqualifiedTypeName(er);
+
+ Declaration decl;
+ TypeSP underlying_type = GetOrCreateType(er.UnderlyingType);
+
+ return std::make_shared<lldb_private::Type>(
+ toOpaqueUid(type_id), this, ConstString(uname),
+ underlying_type->GetByteSize(), nullptr, LLDB_INVALID_UID,
+ lldb_private::Type::eEncodingIsUID, decl, ct,
+ lldb_private::Type::eResolveStateForward);
+}
+
+TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id,
+ const ArrayRecord &ar,
+ CompilerType ct) {
+ TypeSP element_type = GetOrCreateType(ar.ElementType);
+
+ Declaration decl;
+ TypeSP array_sp = std::make_shared<lldb_private::Type>(
+ toOpaqueUid(type_id), this, ConstString(), ar.Size, nullptr,
+ LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct,
+ lldb_private::Type::eResolveStateFull);
+ array_sp->SetEncodingType(element_type.get());
+ return array_sp;
+}
+
+TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id,
+ const ProcedureRecord &pr,
+ CompilerType ct) {
+ Declaration decl;
+ return std::make_shared<lldb_private::Type>(
+ toOpaqueUid(type_id), this, ConstString(), 0, nullptr, LLDB_INVALID_UID,
+ lldb_private::Type::eEncodingIsUID, decl, ct,
+ lldb_private::Type::eResolveStateFull);
+}
+
+TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) {
+ if (type_id.index.isSimple())
+ return CreateSimpleType(type_id.index, ct);
+
+ TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi();
+ CVType cvt = stream.getType(type_id.index);
+
+ if (cvt.kind() == LF_MODIFIER) {
+ ModifierRecord modifier;
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier));
+ return CreateModifierType(type_id, modifier, ct);
+ }
+
+ if (cvt.kind() == LF_POINTER) {
+ PointerRecord pointer;
+ llvm::cantFail(
+ TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer));
+ return CreatePointerType(type_id, pointer, ct);
+ }
+
+ if (IsClassRecord(cvt.kind())) {
+ ClassRecord cr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr));
+ return CreateTagType(type_id, cr, ct);
+ }
+
+ if (cvt.kind() == LF_ENUM) {
+ EnumRecord er;
+ llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er));
+ return CreateTagType(type_id, er, ct);
+ }
+
+ if (cvt.kind() == LF_UNION) {
+ UnionRecord ur;
+ llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur));
+ return CreateTagType(type_id, ur, ct);
+ }
+
+ if (cvt.kind() == LF_ARRAY) {
+ ArrayRecord ar;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar));
+ return CreateArrayType(type_id, ar, ct);
+ }
+
+ if (cvt.kind() == LF_PROCEDURE) {
+ ProcedureRecord pr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr));
+ return CreateProcedureType(type_id, pr, ct);
+ }
+
+ return nullptr;
+}
+
+TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) {
+ // If they search for a UDT which is a forward ref, try and resolve the full
+ // decl and just map the forward ref uid to the full decl record.
+ llvm::Optional<PdbTypeSymId> full_decl_uid;
+ if (IsForwardRefUdt(type_id, m_index->tpi())) {
+ auto expected_full_ti =
+ m_index->tpi().findFullDeclForForwardRef(type_id.index);
+ if (!expected_full_ti)
+ llvm::consumeError(expected_full_ti.takeError());
+ else if (*expected_full_ti != type_id.index) {
+ full_decl_uid = PdbTypeSymId(*expected_full_ti, false);
+
+ // It's possible that a lookup would occur for the full decl causing it
+ // to be cached, then a second lookup would occur for the forward decl.
+ // We don't want to create a second full decl, so make sure the full
+ // decl hasn't already been cached.
+ auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid));
+ if (full_iter != m_types.end()) {
+ TypeSP result = full_iter->second;
+ // Map the forward decl to the TypeSP for the full decl so we can take
+ // the fast path next time.
+ m_types[toOpaqueUid(type_id)] = result;
+ return result;
+ }
+ }
+ }
+
+ PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id;
+
+ clang::QualType qt = m_ast->GetOrCreateType(best_decl_id);
+
+ TypeSP result = CreateType(best_decl_id, m_ast->ToCompilerType(qt));
+ if (!result)
+ return nullptr;
+
+ uint64_t best_uid = toOpaqueUid(best_decl_id);
+ m_types[best_uid] = result;
+ // If we had both a forward decl and a full decl, make both point to the new
+ // type.
+ if (full_decl_uid)
+ m_types[toOpaqueUid(type_id)] = result;
+
+ return result;
+}
+
+TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) {
+ // We can't use try_emplace / overwrite here because the process of creating
+ // a type could create nested types, which could invalidate iterators. So
+ // we have to do a 2-phase lookup / insert.
+ auto iter = m_types.find(toOpaqueUid(type_id));
+ if (iter != m_types.end())
+ return iter->second;
+
+ TypeSP type = CreateAndCacheType(type_id);
+ if (type)
+ m_obj_file->GetModule()->GetTypeList()->Insert(type);
+ return type;
+}
+
+VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) {
+ CVSymbol sym = m_index->symrecords().readRecord(var_id.offset);
+ if (sym.kind() == S_CONSTANT)
+ return CreateConstantSymbol(var_id, sym);
+
+ lldb::ValueType scope = eValueTypeInvalid;
+ TypeIndex ti;
+ llvm::StringRef name;
+ lldb::addr_t addr = 0;
+ uint16_t section = 0;
+ uint32_t offset = 0;
+ bool is_external = false;
+ switch (sym.kind()) {
+ case S_GDATA32:
+ is_external = true;
+ LLVM_FALLTHROUGH;
+ case S_LDATA32: {
+ DataSym ds(sym.kind());
+ llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds));
+ ti = ds.Type;
+ scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal
+ : eValueTypeVariableStatic;
+ name = ds.Name;
+ section = ds.Segment;
+ offset = ds.DataOffset;
+ addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset);
+ break;
+ }
+ case S_GTHREAD32:
+ is_external = true;
+ LLVM_FALLTHROUGH;
+ case S_LTHREAD32: {
+ ThreadLocalDataSym tlds(sym.kind());
+ llvm::cantFail(
+ SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds));
+ ti = tlds.Type;
+ name = tlds.Name;
+ section = tlds.Segment;
+ offset = tlds.DataOffset;
+ addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset);
+ scope = eValueTypeVariableThreadLocal;
+ break;
+ }
+ default:
+ llvm_unreachable("unreachable!");
+ }
+
+ CompUnitSP comp_unit;
+ llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr);
+ if (modi) {
+ CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi);
+ comp_unit = GetOrCreateCompileUnit(cci);
+ }
+
+ Declaration decl;
+ PdbTypeSymId tid(ti, false);
+ SymbolFileTypeSP type_sp =
+ std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
+ Variable::RangeList ranges;
+
+ m_ast->GetOrCreateVariableDecl(var_id);
+
+ DWARFExpression location = MakeGlobalLocationExpression(
+ section, offset, GetObjectFile()->GetModule());
+
+ std::string global_name("::");
+ global_name += name;
+ VariableSP var_sp = std::make_shared<Variable>(
+ toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp,
+ scope, comp_unit.get(), ranges, &decl, location, is_external, false,
+ false);
+ var_sp->SetLocationIsConstantValueData(false);
+
+ return var_sp;
+}
+
+lldb::VariableSP
+SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id,
+ const CVSymbol &cvs) {
+ TpiStream &tpi = m_index->tpi();
+ ConstantSym constant(cvs.kind());
+
+ llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant));
+ std::string global_name("::");
+ global_name += constant.Name;
+ PdbTypeSymId tid(constant.Type, false);
+ SymbolFileTypeSP type_sp =
+ std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid));
+
+ Declaration decl;
+ Variable::RangeList ranges;
+ ModuleSP module = GetObjectFile()->GetModule();
+ DWARFExpression location = MakeConstantLocationExpression(
+ constant.Type, tpi, constant.Value, module);
+
+ VariableSP var_sp = std::make_shared<Variable>(
+ toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(),
+ type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location,
+ false, false, false);
+ var_sp->SetLocationIsConstantValueData(true);
+ return var_sp;
+}
+
+VariableSP
+SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) {
+ auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr);
+ if (emplace_result.second)
+ emplace_result.first->second = CreateGlobalVariable(var_id);
+
+ return emplace_result.first->second;
+}
+
+lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) {
+ return GetOrCreateType(PdbTypeSymId(ti, false));
+}
+
+FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id,
+ CompileUnit &comp_unit) {
+ auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr);
+ if (emplace_result.second)
+ emplace_result.first->second = CreateFunction(func_id, comp_unit);
+
+ return emplace_result.first->second;
+}
+
+CompUnitSP
+SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
+
+ auto emplace_result =
+ m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr);
+ if (emplace_result.second)
+ emplace_result.first->second = CreateCompileUnit(cci);
+
+ lldbassert(emplace_result.first->second);
+ return emplace_result.first->second;
+}
+
+Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) {
+ auto iter = m_blocks.find(toOpaqueUid(block_id));
+ if (iter != m_blocks.end())
+ return *iter->second;
+
+ return CreateBlock(block_id);
+}
+
+void SymbolFileNativePDB::ParseDeclsForContext(
+ lldb_private::CompilerDeclContext decl_ctx) {
+ clang::DeclContext *context = m_ast->FromCompilerDeclContext(decl_ctx);
+ if (!context)
+ return;
+ m_ast->ParseDeclsForContext(*context);
+}
+
+lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
+ if (index >= GetNumCompileUnits())
+ return CompUnitSP();
+ lldbassert(index < UINT16_MAX);
+ if (index >= UINT16_MAX)
+ return nullptr;
+
+ CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
+
+ return GetOrCreateCompileUnit(item);
+}
+
+lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) {
+ PdbSymUid uid(comp_unit.GetID());
+ lldbassert(uid.kind() == PdbSymUidKind::Compiland);
+
+ CompilandIndexItem *item =
+ m_index->compilands().GetCompiland(uid.asCompiland().modi);
+ lldbassert(item);
+ if (!item->m_compile_opts)
+ return lldb::eLanguageTypeUnknown;
+
+ return TranslateLanguage(item->m_compile_opts->getLanguage());
+}
+
+void SymbolFileNativePDB::AddSymbols(Symtab &symtab) { return; }
+
+size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) {
+ PdbSymUid uid{comp_unit.GetID()};
+ lldbassert(uid.kind() == PdbSymUidKind::Compiland);
+ uint16_t modi = uid.asCompiland().modi;
+ CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi);
+
+ size_t count = comp_unit.GetNumFunctions();
+ const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray();
+ for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
+ if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32)
+ continue;
+
+ PdbCompilandSymId sym_id{modi, iter.offset()};
+
+ FunctionSP func = GetOrCreateFunction(sym_id, comp_unit);
+ }
+
+ size_t new_count = comp_unit.GetNumFunctions();
+ lldbassert(new_count >= count);
+ return new_count - count;
+}
+
+static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) {
+ // If any of these flags are set, we need to resolve the compile unit.
+ uint32_t flags = eSymbolContextCompUnit;
+ flags |= eSymbolContextVariable;
+ flags |= eSymbolContextFunction;
+ flags |= eSymbolContextBlock;
+ flags |= eSymbolContextLineEntry;
+ return (resolve_scope & flags) != 0;
+}
+
+uint32_t SymbolFileNativePDB::ResolveSymbolContext(
+ const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) {
+ uint32_t resolved_flags = 0;
+ lldb::addr_t file_addr = addr.GetFileAddress();
+
+ if (NeedsResolvedCompileUnit(resolve_scope)) {
+ llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
+ if (!modi)
+ return 0;
+ CompilandIndexItem *cci = m_index->compilands().GetCompiland(*modi);
+ if (!cci)
+ return 0;
+
+ sc.comp_unit = GetOrCreateCompileUnit(*cci).get();
+ resolved_flags |= eSymbolContextCompUnit;
+ }
+
+ if (resolve_scope & eSymbolContextFunction ||
+ resolve_scope & eSymbolContextBlock) {
+ lldbassert(sc.comp_unit);
+ std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr);
+ // Search the matches in reverse. This way if there are multiple matches
+ // (for example we are 3 levels deep in a nested scope) it will find the
+ // innermost one first.
+ for (const auto &match : llvm::reverse(matches)) {
+ if (match.uid.kind() != PdbSymUidKind::CompilandSym)
+ continue;
+
+ PdbCompilandSymId csid = match.uid.asCompilandSym();
+ CVSymbol cvs = m_index->ReadSymbolRecord(csid);
+ PDB_SymType type = CVSymToPDBSym(cvs.kind());
+ if (type != PDB_SymType::Function && type != PDB_SymType::Block)
+ continue;
+ if (type == PDB_SymType::Function) {
+ sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get();
+ sc.block = sc.GetFunctionBlock();
+ }
+
+ if (type == PDB_SymType::Block) {
+ sc.block = &GetOrCreateBlock(csid);
+ sc.function = sc.block->CalculateSymbolContextFunction();
+ }
+ resolved_flags |= eSymbolContextFunction;
+ resolved_flags |= eSymbolContextBlock;
+ break;
+ }
+ }
+
+ if (resolve_scope & eSymbolContextLineEntry) {
+ lldbassert(sc.comp_unit);
+ if (auto *line_table = sc.comp_unit->GetLineTable()) {
+ if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
+ resolved_flags |= eSymbolContextLineEntry;
+ }
+ }
+
+ return resolved_flags;
+}
+
+uint32_t SymbolFileNativePDB::ResolveSymbolContext(
+ const FileSpec &file_spec, uint32_t line, bool check_inlines,
+ lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) {
+ return 0;
+}
+
+static void AppendLineEntryToSequence(LineTable &table, LineSequence &sequence,
+ const CompilandIndexItem &cci,
+ lldb::addr_t base_addr,
+ uint32_t file_number,
+ const LineFragmentHeader &block,
+ const LineNumberEntry &cur) {
+ LineInfo cur_info(cur.Flags);
+
+ if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
+ return;
+
+ uint64_t addr = base_addr + cur.Offset;
+
+ bool is_statement = cur_info.isStatement();
+ bool is_prologue = IsFunctionPrologue(cci, addr);
+ bool is_epilogue = IsFunctionEpilogue(cci, addr);
+
+ uint32_t lno = cur_info.getStartLine();
+
+ table.AppendLineEntryToSequence(&sequence, addr, lno, 0, file_number,
+ is_statement, false, is_prologue, is_epilogue,
+ false);
+}
+
+static void TerminateLineSequence(LineTable &table,
+ const LineFragmentHeader &block,
+ lldb::addr_t base_addr, uint32_t file_number,
+ uint32_t last_line,
+ std::unique_ptr<LineSequence> seq) {
+ // The end is always a terminal entry, so insert it regardless.
+ table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize,
+ last_line, 0, file_number, false, false,
+ false, false, true);
+ table.InsertSequence(seq.release());
+}
+
+bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) {
+ // Unfortunately LLDB is set up to parse the entire compile unit line table
+ // all at once, even if all it really needs is line info for a specific
+ // function. In the future it would be nice if it could set the sc.m_function
+ // member, and we could only get the line info for the function in question.
+ PdbSymUid cu_id(comp_unit.GetID());
+ lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
+ CompilandIndexItem *cci =
+ m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
+ lldbassert(cci);
+ auto line_table = llvm::make_unique<LineTable>(&comp_unit);
+
+ // This is basically a copy of the .debug$S subsections from all original COFF
+ // object files merged together with address relocations applied. We are
+ // looking for all DEBUG_S_LINES subsections.
+ for (const DebugSubsectionRecord &dssr :
+ cci->m_debug_stream.getSubsectionsArray()) {
+ if (dssr.kind() != DebugSubsectionKind::Lines)
+ continue;
+
+ DebugLinesSubsectionRef lines;
+ llvm::BinaryStreamReader reader(dssr.getRecordData());
+ if (auto EC = lines.initialize(reader)) {
+ llvm::consumeError(std::move(EC));
+ return false;
+ }
+
+ const LineFragmentHeader *lfh = lines.header();
+ uint64_t virtual_addr =
+ m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
+
+ const auto &checksums = cci->m_strings.checksums().getArray();
+ const auto &strings = cci->m_strings.strings();
+ for (const LineColumnEntry &group : lines) {
+ // Indices in this structure are actually offsets of records in the
+ // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index
+ // into the global PDB string table.
+ auto iter = checksums.at(group.NameIndex);
+ if (iter == checksums.end())
+ continue;
+
+ llvm::Expected<llvm::StringRef> efn =
+ strings.getString(iter->FileNameOffset);
+ if (!efn) {
+ llvm::consumeError(efn.takeError());
+ continue;
+ }
+
+ // LLDB wants the index of the file in the list of support files.
+ auto fn_iter = llvm::find(cci->m_file_list, *efn);
+ lldbassert(fn_iter != cci->m_file_list.end());
+ // LLDB support file indices are 1-based.
+ uint32_t file_index =
+ 1 + std::distance(cci->m_file_list.begin(), fn_iter);
+
+ std::unique_ptr<LineSequence> sequence(
+ line_table->CreateLineSequenceContainer());
+ lldbassert(!group.LineNumbers.empty());
+
+ for (const LineNumberEntry &entry : group.LineNumbers) {
+ AppendLineEntryToSequence(*line_table, *sequence, *cci, virtual_addr,
+ file_index, *lfh, entry);
+ }
+ LineInfo last_line(group.LineNumbers.back().Flags);
+ TerminateLineSequence(*line_table, *lfh, virtual_addr, file_index,
+ last_line.getEndLine(), std::move(sequence));
+ }
+ }
+
+ if (line_table->GetSize() == 0)
+ return false;
+
+ comp_unit.SetLineTable(line_table.release());
+ return true;
+}
+
+bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) {
+ // PDB doesn't contain information about macros
+ return false;
+}
+
+bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) {
+ PdbSymUid cu_id(comp_unit.GetID());
+ lldbassert(cu_id.kind() == PdbSymUidKind::Compiland);
+ CompilandIndexItem *cci =
+ m_index->compilands().GetCompiland(cu_id.asCompiland().modi);
+ lldbassert(cci);
+
+ for (llvm::StringRef f : cci->m_file_list) {
+ FileSpec::Style style =
+ f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows;
+ FileSpec spec(f, style);
+ support_files.Append(spec);
+ }
+
+ llvm::SmallString<64> main_source_file =
+ m_index->compilands().GetMainSourceFile(*cci);
+ FileSpec::Style style = main_source_file.startswith("/")
+ ? FileSpec::Style::posix
+ : FileSpec::Style::windows;
+ FileSpec spec(main_source_file, style);
+ support_files.Insert(0, spec);
+ return true;
+}
+
+bool SymbolFileNativePDB::ParseImportedModules(
+ const SymbolContext &sc, std::vector<ConstString> &imported_modules) {
+ // PDB does not yet support module debug info
+ return false;
+}
+
+size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) {
+ GetOrCreateBlock(PdbSymUid(func.GetID()).asCompilandSym());
+ // FIXME: Parse child blocks
+ return 1;
+}
+
+void SymbolFileNativePDB::DumpClangAST(Stream &s) { m_ast->Dump(s); }
+
+uint32_t SymbolFileNativePDB::FindGlobalVariables(
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ uint32_t max_matches, VariableList &variables) {
+ using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
+
+ std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName(
+ name.GetStringRef(), m_index->symrecords());
+ for (const SymbolAndOffset &result : results) {
+ VariableSP var;
+ switch (result.second.kind()) {
+ case SymbolKind::S_GDATA32:
+ case SymbolKind::S_LDATA32:
+ case SymbolKind::S_GTHREAD32:
+ case SymbolKind::S_LTHREAD32:
+ case SymbolKind::S_CONSTANT: {
+ PdbGlobalSymId global(result.first, false);
+ var = GetOrCreateGlobalVariable(global);
+ variables.AddVariable(var);
+ break;
+ }
+ default:
+ continue;
+ }
+ }
+ return variables.GetSize();
+}
+
+uint32_t SymbolFileNativePDB::FindFunctions(
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ FunctionNameType name_type_mask, bool include_inlines, bool append,
+ SymbolContextList &sc_list) {
+ // For now we only support lookup by method name.
+ if (!(name_type_mask & eFunctionNameTypeMethod))
+ return 0;
+
+ using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
+
+ std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
+ name.GetStringRef(), m_index->symrecords());
+ for (const SymbolAndOffset &match : matches) {
+ if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
+ continue;
+ ProcRefSym proc(match.second.kind());
+ cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
+
+ if (!IsValidRecord(proc))
+ continue;
+
+ CompilandIndexItem &cci =
+ m_index->compilands().GetOrCreateCompiland(proc.modi());
+ SymbolContext sc;
+
+ sc.comp_unit = GetOrCreateCompileUnit(cci).get();
+ PdbCompilandSymId func_id(proc.modi(), proc.SymOffset);
+ sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get();
+
+ sc_list.Append(sc);
+ }
+
+ return sc_list.GetSize();
+}
+
+uint32_t SymbolFileNativePDB::FindFunctions(const RegularExpression &regex,
+ bool include_inlines, bool append,
+ SymbolContextList &sc_list) {
+ return 0;
+}
+
+uint32_t SymbolFileNativePDB::FindTypes(
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, uint32_t max_matches,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {
+ if (!append)
+ types.Clear();
+ if (!name)
+ return 0;
+
+ searched_symbol_files.clear();
+ searched_symbol_files.insert(this);
+
+ // There is an assumption 'name' is not a regex
+ size_t match_count = FindTypesByName(name.GetStringRef(), max_matches, types);
+
+ return match_count;
+}
+
+size_t
+SymbolFileNativePDB::FindTypes(const std::vector<CompilerContext> &context,
+ bool append, TypeMap &types) {
+ return 0;
+}
+
+size_t SymbolFileNativePDB::FindTypesByName(llvm::StringRef name,
+ uint32_t max_matches,
+ TypeMap &types) {
+
+ size_t match_count = 0;
+ std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name);
+ if (max_matches > 0 && max_matches < matches.size())
+ matches.resize(max_matches);
+
+ for (TypeIndex ti : matches) {
+ TypeSP type = GetOrCreateType(ti);
+ if (!type)
+ continue;
+
+ types.Insert(type);
+ ++match_count;
+ }
+ return match_count;
+}
+
+size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) {
+ // Only do the full type scan the first time.
+ if (m_done_full_type_scan)
+ return 0;
+
+ size_t old_count = m_obj_file->GetModule()->GetTypeList()->GetSize();
+ LazyRandomTypeCollection &types = m_index->tpi().typeCollection();
+
+ // First process the entire TPI stream.
+ for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) {
+ TypeSP type = GetOrCreateType(*ti);
+ if (type)
+ (void)type->GetFullCompilerType();
+ }
+
+ // Next look for S_UDT records in the globals stream.
+ for (const uint32_t gid : m_index->globals().getGlobalsTable()) {
+ PdbGlobalSymId global{gid, false};
+ CVSymbol sym = m_index->ReadSymbolRecord(global);
+ if (sym.kind() != S_UDT)
+ continue;
+
+ UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+ bool is_typedef = true;
+ if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) {
+ CVType cvt = m_index->tpi().getType(udt.Type);
+ llvm::StringRef name = CVTagRecord::create(cvt).name();
+ if (name == udt.Name)
+ is_typedef = false;
+ }
+
+ if (is_typedef)
+ GetOrCreateTypedef(global);
+ }
+
+ size_t new_count = m_obj_file->GetModule()->GetTypeList()->GetSize();
+
+ m_done_full_type_scan = true;
+
+ return new_count - old_count;
+}
+
+size_t
+SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit,
+ VariableList &variables) {
+ PdbSymUid sym_uid(comp_unit.GetID());
+ lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland);
+ return 0;
+}
+
+VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id,
+ PdbCompilandSymId var_id,
+ bool is_param) {
+ ModuleSP module = GetObjectFile()->GetModule();
+ VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module);
+ if (!var_info.location || !var_info.ranges)
+ return nullptr;
+
+ CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
+ CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
+ TypeSP type_sp = GetOrCreateType(var_info.type);
+ std::string name = var_info.name.str();
+ Declaration decl;
+ SymbolFileTypeSP sftype =
+ std::make_shared<SymbolFileType>(*this, type_sp->GetID());
+
+ ValueType var_scope =
+ is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal;
+ VariableSP var_sp = std::make_shared<Variable>(
+ toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
+ comp_unit_sp.get(), *var_info.ranges, &decl, *var_info.location, false,
+ false, false);
+
+ if (!is_param)
+ m_ast->GetOrCreateVariableDecl(scope_id, var_id);
+
+ m_local_variables[toOpaqueUid(var_id)] = var_sp;
+ return var_sp;
+}
+
+VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable(
+ PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) {
+ auto iter = m_local_variables.find(toOpaqueUid(var_id));
+ if (iter != m_local_variables.end())
+ return iter->second;
+
+ return CreateLocalVariable(scope_id, var_id, is_param);
+}
+
+TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) {
+ CVSymbol sym = m_index->ReadSymbolRecord(id);
+ lldbassert(sym.kind() == SymbolKind::S_UDT);
+
+ UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym));
+
+ TypeSP target_type = GetOrCreateType(udt.Type);
+
+ (void)m_ast->GetOrCreateTypedefDecl(id);
+
+ Declaration decl;
+ return std::make_shared<lldb_private::Type>(
+ toOpaqueUid(id), this, ConstString(udt.Name), target_type->GetByteSize(),
+ nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID,
+ decl, target_type->GetForwardCompilerType(),
+ lldb_private::Type::eResolveStateForward);
+}
+
+TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) {
+ auto iter = m_types.find(toOpaqueUid(id));
+ if (iter != m_types.end())
+ return iter->second;
+
+ return CreateTypedef(id);
+}
+
+size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) {
+ Block &block = GetOrCreateBlock(block_id);
+
+ size_t count = 0;
+
+ CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi);
+ CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset);
+ uint32_t params_remaining = 0;
+ switch (sym.kind()) {
+ case S_GPROC32:
+ case S_LPROC32: {
+ ProcSym proc(static_cast<SymbolRecordKind>(sym.kind()));
+ cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc));
+ CVType signature = m_index->tpi().getType(proc.FunctionType);
+ ProcedureRecord sig;
+ cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(signature, sig));
+ params_remaining = sig.getParameterCount();
+ break;
+ }
+ case S_BLOCK32:
+ break;
+ default:
+ lldbassert(false && "Symbol is not a block!");
+ return 0;
+ }
+
+ VariableListSP variables = block.GetBlockVariableList(false);
+ if (!variables) {
+ variables = std::make_shared<VariableList>();
+ block.SetVariableList(variables);
+ }
+
+ CVSymbolArray syms = limitSymbolArrayToScope(
+ cii->m_debug_stream.getSymbolArray(), block_id.offset);
+
+ // Skip the first record since it's a PROC32 or BLOCK32, and there's
+ // no point examining it since we know it's not a local variable.
+ syms.drop_front();
+ auto iter = syms.begin();
+ auto end = syms.end();
+
+ while (iter != end) {
+ uint32_t record_offset = iter.offset();
+ CVSymbol variable_cvs = *iter;
+ PdbCompilandSymId child_sym_id(block_id.modi, record_offset);
+ ++iter;
+
+ // If this is a block, recurse into its children and then skip it.
+ if (variable_cvs.kind() == S_BLOCK32) {
+ uint32_t block_end = getScopeEndOffset(variable_cvs);
+ count += ParseVariablesForBlock(child_sym_id);
+ iter = syms.at(block_end);
+ continue;
+ }
+
+ bool is_param = params_remaining > 0;
+ VariableSP variable;
+ switch (variable_cvs.kind()) {
+ case S_REGREL32:
+ case S_REGISTER:
+ case S_LOCAL:
+ variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param);
+ if (is_param)
+ --params_remaining;
+ if (variable)
+ variables->AddVariableIfUnique(variable);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Pass false for set_children, since we call this recursively so that the
+ // children will call this for themselves.
+ block.SetDidParseVariables(true, false);
+
+ return count;
+}
+
+size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) {
+ lldbassert(sc.function || sc.comp_unit);
+
+ VariableListSP variables;
+ if (sc.block) {
+ PdbSymUid block_id(sc.block->GetID());
+
+ size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
+ return count;
+ }
+
+ if (sc.function) {
+ PdbSymUid block_id(sc.function->GetID());
+
+ size_t count = ParseVariablesForBlock(block_id.asCompilandSym());
+ return count;
+ }
+
+ if (sc.comp_unit) {
+ variables = sc.comp_unit->GetVariableList(false);
+ if (!variables) {
+ variables = std::make_shared<VariableList>();
+ sc.comp_unit->SetVariableList(variables);
+ }
+ return ParseVariablesForCompileUnit(*sc.comp_unit, *variables);
+ }
+
+ llvm_unreachable("Unreachable!");
+}
+
+CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) {
+ clang::Decl *decl = m_ast->GetOrCreateDeclForUid(PdbSymUid(uid));
+
+ return m_ast->ToCompilerDecl(*decl);
+}
+
+CompilerDeclContext
+SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) {
+ clang::DeclContext *context =
+ m_ast->GetOrCreateDeclContextForUid(PdbSymUid(uid));
+ if (!context)
+ return {};
+
+ return m_ast->ToCompilerDeclContext(*context);
+}
+
+CompilerDeclContext
+SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
+ clang::DeclContext *context = m_ast->GetParentDeclContext(PdbSymUid(uid));
+ return m_ast->ToCompilerDeclContext(*context);
+}
+
+Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
+ auto iter = m_types.find(type_uid);
+ // lldb should not be passing us non-sensical type uids. the only way it
+ // could have a type uid in the first place is if we handed it out, in which
+ // case we should know about the type. However, that doesn't mean we've
+ // instantiated it yet. We can vend out a UID for a future type. So if the
+ // type doesn't exist, let's instantiate it now.
+ if (iter != m_types.end())
+ return &*iter->second;
+
+ PdbSymUid uid(type_uid);
+ lldbassert(uid.kind() == PdbSymUidKind::Type);
+ PdbTypeSymId type_id = uid.asTypeSym();
+ if (type_id.index.isNoneType())
+ return nullptr;
+
+ TypeSP type_sp = CreateAndCacheType(type_id);
+ return &*type_sp;
+}
+
+llvm::Optional<SymbolFile::ArrayInfo>
+SymbolFileNativePDB::GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
+ return llvm::None;
+}
+
+
+bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) {
+ clang::QualType qt =
+ clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType());
+
+ return m_ast->CompleteType(qt);
+}
+
+size_t SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
+ TypeClass type_mask,
+ lldb_private::TypeList &type_list) {
+ return 0;
+}
+
+CompilerDeclContext
+SymbolFileNativePDB::FindNamespace(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx) {
+ return {};
+}
+
+TypeSystem *
+SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
+ auto type_system =
+ m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+ if (type_system)
+ type_system->SetSymbolFile(this);
+ return type_system;
+}
+
+ConstString SymbolFileNativePDB::GetPluginName() {
+ static ConstString g_name("pdb");
+ return g_name;
+}
+
+uint32_t SymbolFileNativePDB::GetPluginVersion() { return 1; }
diff --git a/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
new file mode 100644
index 000000000000..dcf3fe365ef1
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -0,0 +1,245 @@
+//===-- SymbolFileNativePDB.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_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H
+#define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_SYMBOLFILENATIVEPDB_H
+
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "CompileUnitIndex.h"
+#include "PdbIndex.h"
+
+namespace clang {
+class TagDecl;
+}
+
+namespace llvm {
+namespace codeview {
+class ClassRecord;
+class EnumRecord;
+class ModifierRecord;
+class PointerRecord;
+struct UnionRecord;
+} // namespace codeview
+} // namespace llvm
+
+namespace lldb_private {
+class ClangASTImporter;
+
+namespace npdb {
+class PdbAstBuilder;
+
+class SymbolFileNativePDB : public SymbolFile {
+ friend class UdtRecordCompleter;
+
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+
+ static void Terminate();
+
+ static void DebuggerInitialize(Debugger &debugger);
+
+ static ConstString GetPluginNameStatic();
+
+ static const char *GetPluginDescriptionStatic();
+
+ static SymbolFile *CreateInstance(ObjectFile *obj_file);
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ SymbolFileNativePDB(ObjectFile *ofile);
+
+ ~SymbolFileNativePDB() override;
+
+ uint32_t CalculateAbilities() override;
+
+ void InitializeObject() override;
+
+ //------------------------------------------------------------------
+ // Compile Unit function calls
+ //------------------------------------------------------------------
+
+ uint32_t GetNumCompileUnits() override;
+
+ void
+ ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;
+
+ lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
+
+ lldb::LanguageType
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
+
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
+
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ FileSpecList &support_files) override;
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
+
+ bool
+ ParseImportedModules(const SymbolContext &sc,
+ std::vector<ConstString> &imported_modules) override;
+
+ size_t ParseBlocksRecursive(Function &func) override;
+
+ uint32_t FindGlobalVariables(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ uint32_t max_matches,
+ VariableList &variables) override;
+
+ size_t ParseVariablesForContext(const SymbolContext &sc) override;
+
+ void AddSymbols(Symtab &symtab) override;
+
+ CompilerDecl GetDeclForUID(lldb::user_id_t uid) override;
+ CompilerDeclContext GetDeclContextForUID(lldb::user_id_t uid) override;
+ CompilerDeclContext GetDeclContextContainingUID(lldb::user_id_t uid) override;
+ Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
+
+ bool CompleteType(CompilerType &compiler_type) override;
+ uint32_t ResolveSymbolContext(const Address &so_addr,
+ lldb::SymbolContextItem resolve_scope,
+ SymbolContext &sc) override;
+ uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
+ bool check_inlines,
+ lldb::SymbolContextItem resolve_scope,
+ SymbolContextList &sc_list) override;
+
+ size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
+ TypeList &type_list) override;
+
+ uint32_t FindFunctions(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx,
+ lldb::FunctionNameType name_type_mask,
+ bool include_inlines, bool append,
+ SymbolContextList &sc_list) override;
+
+ uint32_t FindFunctions(const RegularExpression &regex, bool include_inlines,
+ bool append, SymbolContextList &sc_list) override;
+
+ uint32_t FindTypes(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx, bool append,
+ uint32_t max_matches,
+ llvm::DenseSet<SymbolFile *> &searched_symbol_files,
+ TypeMap &types) override;
+
+ size_t FindTypes(const std::vector<CompilerContext> &context, bool append,
+ TypeMap &types) override;
+
+ TypeSystem *GetTypeSystemForLanguage(lldb::LanguageType language) override;
+
+ CompilerDeclContext
+ FindNamespace(const ConstString &name,
+ const CompilerDeclContext *parent_decl_ctx) override;
+
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); }
+ const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); }
+
+ void DumpClangAST(Stream &s) override;
+
+private:
+
+ size_t FindTypesByName(llvm::StringRef name, uint32_t max_matches,
+ TypeMap &types);
+
+ lldb::TypeSP CreateModifierType(PdbTypeSymId type_id,
+ const llvm::codeview::ModifierRecord &mr,
+ CompilerType ct);
+ lldb::TypeSP CreatePointerType(PdbTypeSymId type_id,
+ const llvm::codeview::PointerRecord &pr,
+ CompilerType ct);
+ lldb::TypeSP CreateSimpleType(llvm::codeview::TypeIndex ti, CompilerType ct);
+ lldb::TypeSP CreateTagType(PdbTypeSymId type_id,
+ const llvm::codeview::ClassRecord &cr,
+ CompilerType ct);
+ lldb::TypeSP CreateTagType(PdbTypeSymId type_id,
+ const llvm::codeview::EnumRecord &er,
+ CompilerType ct);
+ lldb::TypeSP CreateTagType(PdbTypeSymId type_id,
+ const llvm::codeview::UnionRecord &ur,
+ CompilerType ct);
+ lldb::TypeSP CreateArrayType(PdbTypeSymId type_id,
+ const llvm::codeview::ArrayRecord &ar,
+ CompilerType ct);
+ lldb::TypeSP CreateProcedureType(PdbTypeSymId type_id,
+ const llvm::codeview::ProcedureRecord &pr,
+ CompilerType ct);
+ lldb::TypeSP CreateClassStructUnion(PdbTypeSymId type_id,
+ const llvm::codeview::TagRecord &record,
+ size_t size, CompilerType ct);
+
+ lldb::FunctionSP GetOrCreateFunction(PdbCompilandSymId func_id,
+ CompileUnit &comp_unit);
+ lldb::CompUnitSP GetOrCreateCompileUnit(const CompilandIndexItem &cci);
+ lldb::TypeSP GetOrCreateType(PdbTypeSymId type_id);
+ lldb::TypeSP GetOrCreateType(llvm::codeview::TypeIndex ti);
+ lldb::VariableSP GetOrCreateGlobalVariable(PdbGlobalSymId var_id);
+ Block &GetOrCreateBlock(PdbCompilandSymId block_id);
+ lldb::VariableSP GetOrCreateLocalVariable(PdbCompilandSymId scope_id,
+ PdbCompilandSymId var_id,
+ bool is_param);
+ lldb::TypeSP GetOrCreateTypedef(PdbGlobalSymId id);
+
+ lldb::FunctionSP CreateFunction(PdbCompilandSymId func_id,
+ CompileUnit &comp_unit);
+ Block &CreateBlock(PdbCompilandSymId block_id);
+ lldb::VariableSP CreateLocalVariable(PdbCompilandSymId scope_id,
+ PdbCompilandSymId var_id, bool is_param);
+ lldb::TypeSP CreateTypedef(PdbGlobalSymId id);
+ lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
+ lldb::TypeSP CreateType(PdbTypeSymId type_id, CompilerType ct);
+ lldb::TypeSP CreateAndCacheType(PdbTypeSymId type_id);
+ lldb::VariableSP CreateGlobalVariable(PdbGlobalSymId var_id);
+ lldb::VariableSP CreateConstantSymbol(PdbGlobalSymId var_id,
+ const llvm::codeview::CVSymbol &cvs);
+ size_t ParseVariablesForCompileUnit(CompileUnit &comp_unit,
+ VariableList &variables);
+ size_t ParseVariablesForBlock(PdbCompilandSymId block_id);
+
+ llvm::BumpPtrAllocator m_allocator;
+
+ lldb::addr_t m_obj_load_address = 0;
+ bool m_done_full_type_scan = false;
+
+ std::unique_ptr<PdbIndex> m_index;
+
+ std::unique_ptr<PdbAstBuilder> m_ast;
+
+ llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_global_vars;
+ llvm::DenseMap<lldb::user_id_t, lldb::VariableSP> m_local_variables;
+ llvm::DenseMap<lldb::user_id_t, lldb::BlockSP> m_blocks;
+ llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions;
+ llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands;
+ llvm::DenseMap<lldb::user_id_t, lldb::TypeSP> m_types;
+};
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
diff --git a/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
new file mode 100644
index 000000000000..239dfbee625d
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp
@@ -0,0 +1,191 @@
+#include "UdtRecordCompleter.h"
+
+#include "PdbAstBuilder.h"
+#include "PdbIndex.h"
+#include "PdbSymUid.h"
+#include "PdbUtil.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+
+using Error = llvm::Error;
+
+UdtRecordCompleter::UdtRecordCompleter(PdbTypeSymId id,
+ CompilerType &derived_ct,
+ clang::TagDecl &tag_decl,
+ PdbAstBuilder &ast_builder,
+ TpiStream &tpi)
+ : m_id(id), m_derived_ct(derived_ct), m_tag_decl(tag_decl),
+ m_ast_builder(ast_builder), m_tpi(tpi) {
+ CVType cvt = m_tpi.getType(m_id.index);
+ switch (cvt.kind()) {
+ case LF_ENUM:
+ llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, m_cvr.er));
+ break;
+ case LF_UNION:
+ llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, m_cvr.ur));
+ break;
+ case LF_CLASS:
+ case LF_STRUCTURE:
+ llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, m_cvr.cr));
+ break;
+ default:
+ llvm_unreachable("unreachable!");
+ }
+}
+
+clang::QualType UdtRecordCompleter::AddBaseClassForTypeIndex(
+ llvm::codeview::TypeIndex ti, llvm::codeview::MemberAccess access) {
+ PdbTypeSymId type_id(ti);
+ clang::QualType qt = m_ast_builder.GetOrCreateType(type_id);
+
+ CVType udt_cvt = m_tpi.getType(ti);
+
+ std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
+ m_ast_builder.clang().CreateBaseClassSpecifier(
+ qt.getAsOpaquePtr(), TranslateMemberAccess(access), false,
+ udt_cvt.kind() == LF_CLASS);
+ lldbassert(base_spec);
+ m_bases.push_back(std::move(base_spec));
+ return qt;
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ BaseClassRecord &base) {
+ clang::QualType base_qt =
+ AddBaseClassForTypeIndex(base.Type, base.getAccess());
+
+ auto decl =
+ m_ast_builder.clang().GetAsCXXRecordDecl(base_qt.getAsOpaquePtr());
+ lldbassert(decl);
+
+ auto offset = clang::CharUnits::fromQuantity(base.getBaseOffset());
+ m_layout.base_offsets.insert(std::make_pair(decl, offset));
+
+ return llvm::Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ VirtualBaseClassRecord &base) {
+ AddBaseClassForTypeIndex(base.BaseType, base.getAccess());
+
+ // FIXME: Handle virtual base offsets.
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ ListContinuationRecord &cont) {
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ VFPtrRecord &vfptr) {
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(
+ CVMemberRecord &cvr, StaticDataMemberRecord &static_data_member) {
+ clang::QualType member_type =
+ m_ast_builder.GetOrCreateType(PdbTypeSymId(static_data_member.Type));
+
+ m_ast_builder.CompleteType(member_type);
+
+ CompilerType member_ct = m_ast_builder.ToCompilerType(member_type);
+
+ lldb::AccessType access =
+ TranslateMemberAccess(static_data_member.getAccess());
+ ClangASTContext::AddVariableToRecordType(
+ m_derived_ct, static_data_member.Name, member_ct, access);
+
+ // FIXME: Add a PdbSymUid namespace for field list members and update
+ // the m_uid_to_decl map with this decl.
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ NestedTypeRecord &nested) {
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ DataMemberRecord &data_member) {
+
+ uint64_t offset = data_member.FieldOffset * 8;
+ uint32_t bitfield_width = 0;
+
+ TypeIndex ti(data_member.Type);
+ if (!ti.isSimple()) {
+ CVType cvt = m_tpi.getType(ti);
+ if (cvt.kind() == LF_BITFIELD) {
+ BitFieldRecord bfr;
+ llvm::cantFail(TypeDeserializer::deserializeAs<BitFieldRecord>(cvt, bfr));
+ offset += bfr.BitOffset;
+ bitfield_width = bfr.BitSize;
+ ti = bfr.Type;
+ }
+ }
+
+ clang::QualType member_qt = m_ast_builder.GetOrCreateType(PdbTypeSymId(ti));
+ m_ast_builder.CompleteType(member_qt);
+
+ lldb::AccessType access = TranslateMemberAccess(data_member.getAccess());
+
+ clang::FieldDecl *decl = ClangASTContext::AddFieldToRecordType(
+ m_derived_ct, data_member.Name, m_ast_builder.ToCompilerType(member_qt),
+ access, bitfield_width);
+ // FIXME: Add a PdbSymUid namespace for field list members and update
+ // the m_uid_to_decl map with this decl.
+
+ m_layout.field_offsets.insert(std::make_pair(decl, offset));
+
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ OneMethodRecord &one_method) {
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ OverloadedMethodRecord &overloaded) {
+ return Error::success();
+}
+
+Error UdtRecordCompleter::visitKnownMember(CVMemberRecord &cvr,
+ EnumeratorRecord &enumerator) {
+ Declaration decl;
+ llvm::StringRef name = DropNameScope(enumerator.getName());
+
+ m_ast_builder.clang().AddEnumerationValueToEnumerationType(
+ m_derived_ct, decl, name.str().c_str(), enumerator.Value);
+ return Error::success();
+}
+
+void UdtRecordCompleter::complete() {
+ ClangASTContext &clang = m_ast_builder.clang();
+ clang.TransferBaseClasses(m_derived_ct.GetOpaqueQualType(),
+ std::move(m_bases));
+
+ clang.AddMethodOverridesForCXXRecordType(m_derived_ct.GetOpaqueQualType());
+ ClangASTContext::BuildIndirectFields(m_derived_ct);
+ ClangASTContext::CompleteTagDeclarationDefinition(m_derived_ct);
+
+ if (auto *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(&m_tag_decl)) {
+ m_ast_builder.importer().InsertRecordDecl(record_decl, m_layout);
+ }
+}
diff --git a/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h b/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
new file mode 100644
index 000000000000..469685126e59
--- /dev/null
+++ b/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.h
@@ -0,0 +1,75 @@
+//===-- SymbolFileNativePDB.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_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H
+#define LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H
+
+#include "lldb/Symbol/ClangASTImporter.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+#include "PdbSymUid.h"
+
+namespace clang {
+class CXXBaseSpecifier;
+class QualType;
+class TagDecl;
+} // namespace clang
+
+namespace llvm {
+namespace pdb {
+class TpiStream;
+}
+} // namespace llvm
+
+namespace lldb_private {
+class Type;
+class CompilerType;
+namespace npdb {
+class PdbAstBuilder;
+
+class UdtRecordCompleter : public llvm::codeview::TypeVisitorCallbacks {
+ union UdtTagRecord {
+ UdtTagRecord() {}
+ llvm::codeview::UnionRecord ur;
+ llvm::codeview::ClassRecord cr;
+ llvm::codeview::EnumRecord er;
+ } m_cvr;
+
+ PdbTypeSymId m_id;
+ CompilerType &m_derived_ct;
+ clang::TagDecl &m_tag_decl;
+ PdbAstBuilder &m_ast_builder;
+ llvm::pdb::TpiStream &m_tpi;
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> m_bases;
+ ClangASTImporter::LayoutInfo m_layout;
+
+public:
+ UdtRecordCompleter(PdbTypeSymId id, CompilerType &derived_ct,
+ clang::TagDecl &tag_decl, PdbAstBuilder &ast_builder,
+ llvm::pdb::TpiStream &tpi);
+
+#define MEMBER_RECORD(EnumName, EnumVal, Name) \
+ llvm::Error visitKnownMember(llvm::codeview::CVMemberRecord &CVR, \
+ llvm::codeview::Name##Record &Record) override;
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
+
+ void complete();
+
+private:
+ clang::QualType AddBaseClassForTypeIndex(llvm::codeview::TypeIndex ti,
+ llvm::codeview::MemberAccess access);
+};
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif // LLDB_PLUGINS_SYMBOLFILE_NATIVEPDB_UDTRECORDCOMPLETER_H
diff --git a/source/Plugins/SymbolFile/PDB/CMakeLists.txt b/source/Plugins/SymbolFile/PDB/CMakeLists.txt
index 1c176c32224d..19698a7187f7 100644
--- a/source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ b/source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -9,6 +9,7 @@ add_lldb_library(lldbPluginSymbolFilePDB PLUGIN
lldbCore
lldbSymbol
lldbUtility
+ lldbPluginSymbolFileNativePDB
LINK_COMPONENTS
DebugInfoPDB
Support
diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
index 8bea994aae5d..65e718bedaf1 100644
--- a/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
+++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp
@@ -9,14 +9,19 @@
#include "PDBASTParser.h"
+#include "SymbolFilePDB.h"
+
#include "clang/AST/CharUnits.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
+#include "lldb/Core/Module.h"
#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/Declaration.h"
#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/TypeMap.h"
#include "lldb/Symbol/TypeSystem.h"
#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
@@ -33,12 +38,13 @@
#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+
using namespace lldb;
using namespace lldb_private;
using namespace llvm::pdb;
-namespace {
-int TranslateUdtKind(PDB_UdtType pdb_kind) {
+static int TranslateUdtKind(PDB_UdtType pdb_kind) {
switch (pdb_kind) {
case PDB_UdtType::Class:
return clang::TTK_Class;
@@ -49,10 +55,10 @@ int TranslateUdtKind(PDB_UdtType pdb_kind) {
case PDB_UdtType::Interface:
return clang::TTK_Interface;
}
- return -1;
+ llvm_unreachable("unsuported PDB UDT type");
}
-lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
+static lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
switch (type) {
case PDB_BuiltinType::Float:
return lldb::eEncodingIEEE754;
@@ -73,7 +79,7 @@ lldb::Encoding TranslateBuiltinEncoding(PDB_BuiltinType type) {
}
}
-lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) {
+static lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) {
switch (type) {
case PDB_VariantType::Int8:
case PDB_VariantType::Int16:
@@ -94,7 +100,7 @@ lldb::Encoding TranslateEnumEncoding(PDB_VariantType type) {
return lldb::eEncodingSint;
}
-CompilerType
+static CompilerType
GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
const PDBSymbolTypeBuiltin &pdb_type,
Encoding encoding, uint32_t width) {
@@ -109,6 +115,8 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
return CompilerType();
case PDB_BuiltinType::Void:
return clang_ast.GetBasicType(eBasicTypeVoid);
+ case PDB_BuiltinType::Char:
+ return clang_ast.GetBasicType(eBasicTypeChar);
case PDB_BuiltinType::Bool:
return clang_ast.GetBasicType(eBasicTypeBool);
case PDB_BuiltinType::Long:
@@ -143,8 +151,8 @@ GetBuiltinTypeForPDBEncodingAndBitSize(ClangASTContext &clang_ast,
return clang_ast.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
}
-ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type,
- CompilerType &compiler_type) {
+static ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type,
+ CompilerType &compiler_type) {
PDB_BuiltinType kind = pdb_type.getBuiltinType();
switch (kind) {
default:
@@ -175,7 +183,8 @@ ConstString GetPDBBuiltinTypeName(const PDBSymbolTypeBuiltin &pdb_type,
return compiler_type.GetTypeName();
}
-bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) {
+static bool GetDeclarationForSymbol(const PDBSymbol &symbol,
+ Declaration &decl) {
auto &raw_sym = symbol.getRawSymbol();
auto first_line_up = raw_sym.getSrcLineOnTypeDefn();
@@ -193,13 +202,159 @@ bool GetDeclarationForSymbol(const PDBSymbol &symbol, Declaration &decl) {
if (!src_file_up)
return false;
- FileSpec spec(src_file_up->getFileName(), /*resolve_path*/ false);
+ FileSpec spec(src_file_up->getFileName());
decl.SetFile(spec);
decl.SetColumn(first_line_up->getColumnNumber());
decl.SetLine(first_line_up->getLineNumber());
return true;
}
-} // namespace
+
+static AccessType TranslateMemberAccess(PDB_MemberAccess access) {
+ switch (access) {
+ case PDB_MemberAccess::Private:
+ return eAccessPrivate;
+ case PDB_MemberAccess::Protected:
+ return eAccessProtected;
+ case PDB_MemberAccess::Public:
+ return eAccessPublic;
+ }
+ return eAccessNone;
+}
+
+static AccessType GetDefaultAccessibilityForUdtKind(PDB_UdtType udt_kind) {
+ switch (udt_kind) {
+ case PDB_UdtType::Struct:
+ case PDB_UdtType::Union:
+ return eAccessPublic;
+ case PDB_UdtType::Class:
+ case PDB_UdtType::Interface:
+ return eAccessPrivate;
+ }
+ llvm_unreachable("unsupported PDB UDT type");
+}
+
+static AccessType GetAccessibilityForUdt(const PDBSymbolTypeUDT &udt) {
+ AccessType access = TranslateMemberAccess(udt.getAccess());
+ if (access != lldb::eAccessNone || !udt.isNested())
+ return access;
+
+ auto parent = udt.getClassParent();
+ if (!parent)
+ return lldb::eAccessNone;
+
+ auto parent_udt = llvm::dyn_cast<PDBSymbolTypeUDT>(parent.get());
+ if (!parent_udt)
+ return lldb::eAccessNone;
+
+ return GetDefaultAccessibilityForUdtKind(parent_udt->getUdtKind());
+}
+
+static clang::MSInheritanceAttr::Spelling
+GetMSInheritance(const PDBSymbolTypeUDT &udt) {
+ int base_count = 0;
+ bool has_virtual = false;
+
+ auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>();
+ if (bases_enum) {
+ while (auto base = bases_enum->getNext()) {
+ base_count++;
+ has_virtual |= base->isVirtualBaseClass();
+ }
+ }
+
+ if (has_virtual)
+ return clang::MSInheritanceAttr::Keyword_virtual_inheritance;
+ if (base_count > 1)
+ return clang::MSInheritanceAttr::Keyword_multiple_inheritance;
+ return clang::MSInheritanceAttr::Keyword_single_inheritance;
+}
+
+static std::unique_ptr<llvm::pdb::PDBSymbol>
+GetClassOrFunctionParent(const llvm::pdb::PDBSymbol &symbol) {
+ const IPDBSession &session = symbol.getSession();
+ const IPDBRawSymbol &raw = symbol.getRawSymbol();
+ auto tag = symbol.getSymTag();
+
+ // For items that are nested inside of a class, return the class that it is
+ // nested inside of.
+ // Note that only certain items can be nested inside of classes.
+ switch (tag) {
+ case PDB_SymType::Function:
+ case PDB_SymType::Data:
+ case PDB_SymType::UDT:
+ case PDB_SymType::Enum:
+ case PDB_SymType::FunctionSig:
+ case PDB_SymType::Typedef:
+ case PDB_SymType::BaseClass:
+ case PDB_SymType::VTable: {
+ auto class_parent_id = raw.getClassParentId();
+ if (auto class_parent = session.getSymbolById(class_parent_id))
+ return class_parent;
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Otherwise, if it is nested inside of a function, return the function.
+ // Note that only certain items can be nested inside of functions.
+ switch (tag) {
+ case PDB_SymType::Block:
+ case PDB_SymType::Data: {
+ auto lexical_parent_id = raw.getLexicalParentId();
+ auto lexical_parent = session.getSymbolById(lexical_parent_id);
+ if (!lexical_parent)
+ return nullptr;
+
+ auto lexical_parent_tag = lexical_parent->getSymTag();
+ if (lexical_parent_tag == PDB_SymType::Function)
+ return lexical_parent;
+ if (lexical_parent_tag == PDB_SymType::Exe)
+ return nullptr;
+
+ return GetClassOrFunctionParent(*lexical_parent);
+ }
+ default:
+ return nullptr;
+ }
+}
+
+static clang::NamedDecl *
+GetDeclFromContextByName(const clang::ASTContext &ast,
+ const clang::DeclContext &decl_context,
+ llvm::StringRef name) {
+ clang::IdentifierInfo &ident = ast.Idents.get(name);
+ clang::DeclarationName decl_name = ast.DeclarationNames.getIdentifier(&ident);
+ clang::DeclContext::lookup_result result = decl_context.lookup(decl_name);
+ if (result.empty())
+ return nullptr;
+
+ return result[0];
+}
+
+static bool IsAnonymousNamespaceName(llvm::StringRef name) {
+ return name == "`anonymous namespace'" || name == "`anonymous-namespace'";
+}
+
+static clang::CallingConv TranslateCallingConvention(PDB_CallingConv pdb_cc) {
+ switch (pdb_cc) {
+ case llvm::codeview::CallingConvention::NearC:
+ return clang::CC_C;
+ case llvm::codeview::CallingConvention::NearStdCall:
+ return clang::CC_X86StdCall;
+ case llvm::codeview::CallingConvention::NearFast:
+ return clang::CC_X86FastCall;
+ case llvm::codeview::CallingConvention::ThisCall:
+ return clang::CC_X86ThisCall;
+ case llvm::codeview::CallingConvention::NearVector:
+ return clang::CC_X86VectorCall;
+ case llvm::codeview::CallingConvention::NearPascal:
+ return clang::CC_X86Pascal;
+ default:
+ assert(false && "Unknown calling convention");
+ return clang::CC_C;
+ }
+}
PDBASTParser::PDBASTParser(lldb_private::ClangASTContext &ast) : m_ast(ast) {}
@@ -208,76 +363,167 @@ PDBASTParser::~PDBASTParser() {}
// DebugInfoASTParser interface
lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
- // PDB doesn't maintain enough information to robustly rebuild the entire
- // tree, and this is most problematic when it comes to figure out the right
- // DeclContext to put a type in. So for now, everything goes in the
- // translation unit decl as a fully qualified type.
- clang::DeclContext *tu_decl_ctx = m_ast.GetTranslationUnitDecl();
Declaration decl;
-
switch (type.getSymTag()) {
+ case PDB_SymType::BaseClass: {
+ auto symbol_file = m_ast.GetSymbolFile();
+ if (!symbol_file)
+ return nullptr;
+
+ auto ty = symbol_file->ResolveTypeUID(type.getRawSymbol().getTypeId());
+ return ty ? ty->shared_from_this() : nullptr;
+ } break;
case PDB_SymType::UDT: {
auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&type);
assert(udt);
- AccessType access = lldb::eAccessPublic;
- PDB_UdtType udt_kind = udt->getUdtKind();
- auto tag_type_kind = TranslateUdtKind(udt_kind);
- if (tag_type_kind == -1)
+
+ // Note that, unnamed UDT being typedef-ed is generated as a UDT symbol
+ // other than a Typedef symbol in PDB. For example,
+ // typedef union { short Row; short Col; } Union;
+ // is generated as a named UDT in PDB:
+ // union Union { short Row; short Col; }
+ // Such symbols will be handled here.
+
+ // Some UDT with trival ctor has zero length. Just ignore.
+ if (udt->getLength() == 0)
+ return nullptr;
+
+ // Ignore unnamed-tag UDTs.
+ std::string name = MSVCUndecoratedNameParser::DropScope(udt->getName());
+ if (name.empty())
return nullptr;
- if (udt_kind == PDB_UdtType::Class)
- access = lldb::eAccessPrivate;
+ auto decl_context = GetDeclContextContainingSymbol(type);
- CompilerType clang_type = m_ast.CreateRecordType(
- tu_decl_ctx, access, udt->getName().c_str(), tag_type_kind,
- lldb::eLanguageTypeC_plus_plus, nullptr);
+ // Check if such an UDT already exists in the current context.
+ // This may occur with const or volatile types. There are separate type
+ // symbols in PDB for types with const or volatile modifiers, but we need
+ // to create only one declaration for them all.
+ Type::ResolveStateTag type_resolve_state_tag;
+ CompilerType clang_type = m_ast.GetTypeForIdentifier<clang::CXXRecordDecl>(
+ ConstString(name), decl_context);
+ if (!clang_type.IsValid()) {
+ auto access = GetAccessibilityForUdt(*udt);
- m_ast.SetHasExternalStorage(clang_type.GetOpaqueQualType(), true);
+ auto tag_type_kind = TranslateUdtKind(udt->getUdtKind());
+ ClangASTMetadata metadata;
+ metadata.SetUserID(type.getSymIndexId());
+ metadata.SetIsDynamicCXXType(false);
+
+ clang_type = m_ast.CreateRecordType(
+ decl_context, access, name.c_str(), tag_type_kind,
+ lldb::eLanguageTypeC_plus_plus, &metadata);
+ assert(clang_type.IsValid());
+
+ auto record_decl =
+ m_ast.GetAsCXXRecordDecl(clang_type.GetOpaqueQualType());
+ assert(record_decl);
+ m_uid_to_decl[type.getSymIndexId()] = record_decl;
+
+ auto inheritance_attr = clang::MSInheritanceAttr::CreateImplicit(
+ *m_ast.getASTContext(), GetMSInheritance(*udt));
+ record_decl->addAttr(inheritance_attr);
+
+ ClangASTContext::StartTagDeclarationDefinition(clang_type);
+
+ auto children = udt->findAllChildren();
+ if (!children || children->getChildCount() == 0) {
+ // PDB does not have symbol of forwarder. We assume we get an udt w/o
+ // any fields. Just complete it at this point.
+ ClangASTContext::CompleteTagDeclarationDefinition(clang_type);
+
+ ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
+ false);
+
+ type_resolve_state_tag = Type::eResolveStateFull;
+ } else {
+ // Add the type to the forward declarations. It will help us to avoid
+ // an endless recursion in CompleteTypeFromUdt function.
+ m_forward_decl_to_uid[record_decl] = type.getSymIndexId();
+
+ ClangASTContext::SetHasExternalStorage(clang_type.GetOpaqueQualType(),
+ true);
+
+ type_resolve_state_tag = Type::eResolveStateForward;
+ }
+ } else
+ type_resolve_state_tag = Type::eResolveStateForward;
+
+ if (udt->isConstType())
+ clang_type = clang_type.AddConstModifier();
+
+ if (udt->isVolatileType())
+ clang_type = clang_type.AddVolatileModifier();
+
+ GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
- type.getSymIndexId(), m_ast.GetSymbolFile(),
- ConstString(udt->getName()), udt->getLength(), nullptr,
- LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, clang_type,
- lldb_private::Type::eResolveStateForward);
+ type.getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
+ udt->getLength(), nullptr, LLDB_INVALID_UID,
+ lldb_private::Type::eEncodingIsUID, decl, clang_type,
+ type_resolve_state_tag);
} break;
case PDB_SymType::Enum: {
auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(&type);
assert(enum_type);
- auto underlying_type_up = enum_type->getUnderlyingType();
- if (!underlying_type_up)
- return nullptr;
- lldb::Encoding encoding =
- TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
- // FIXME: Type of underlying builtin is always `Int`. We correct it with
- // the very first enumerator's encoding if any.
- auto first_child = enum_type->findOneChild<PDBSymbolData>();
- if (first_child) {
- encoding = TranslateEnumEncoding(first_child->getValue().Type);
- }
- std::string name = enum_type->getName();
+
+ std::string name =
+ MSVCUndecoratedNameParser::DropScope(enum_type->getName());
+ auto decl_context = GetDeclContextContainingSymbol(type);
uint64_t bytes = enum_type->getLength();
- CompilerType builtin_type;
- if (bytes > 0)
- builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
- m_ast, *underlying_type_up, encoding, bytes * 8);
- else
- builtin_type = m_ast.GetBasicType(eBasicTypeInt);
- // FIXME: PDB does not have information about scoped enumeration (Enum
- // Class). Set it false for now.
- bool isScoped = false;
-
- CompilerType ast_enum = m_ast.CreateEnumerationType(
- name.c_str(), tu_decl_ctx, decl, builtin_type, isScoped);
- auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
- if (enum_values) {
- while (auto enum_value = enum_values->getNext()) {
- if (enum_value->getDataKind() != PDB_DataKind::Constant)
- continue;
- AddEnumValue(ast_enum, *enum_value);
+
+ // Check if such an enum already exists in the current context
+ CompilerType ast_enum = m_ast.GetTypeForIdentifier<clang::EnumDecl>(
+ ConstString(name), decl_context);
+ if (!ast_enum.IsValid()) {
+ auto underlying_type_up = enum_type->getUnderlyingType();
+ if (!underlying_type_up)
+ return nullptr;
+
+ lldb::Encoding encoding =
+ TranslateBuiltinEncoding(underlying_type_up->getBuiltinType());
+ // FIXME: Type of underlying builtin is always `Int`. We correct it with
+ // the very first enumerator's encoding if any.
+ auto first_child = enum_type->findOneChild<PDBSymbolData>();
+ if (first_child)
+ encoding = TranslateEnumEncoding(first_child->getValue().Type);
+
+ CompilerType builtin_type;
+ if (bytes > 0)
+ builtin_type = GetBuiltinTypeForPDBEncodingAndBitSize(
+ m_ast, *underlying_type_up, encoding, bytes * 8);
+ else
+ builtin_type = m_ast.GetBasicType(eBasicTypeInt);
+
+ // FIXME: PDB does not have information about scoped enumeration (Enum
+ // Class). Set it false for now.
+ bool isScoped = false;
+
+ ast_enum = m_ast.CreateEnumerationType(name.c_str(), decl_context, decl,
+ builtin_type, isScoped);
+
+ auto enum_decl = ClangASTContext::GetAsEnumDecl(ast_enum);
+ assert(enum_decl);
+ m_uid_to_decl[type.getSymIndexId()] = enum_decl;
+
+ auto enum_values = enum_type->findAllChildren<PDBSymbolData>();
+ if (enum_values) {
+ while (auto enum_value = enum_values->getNext()) {
+ if (enum_value->getDataKind() != PDB_DataKind::Constant)
+ continue;
+ AddEnumValue(ast_enum, *enum_value);
+ }
}
+
+ if (ClangASTContext::StartTagDeclarationDefinition(ast_enum))
+ ClangASTContext::CompleteTagDeclarationDefinition(ast_enum);
}
- if (ClangASTContext::StartTagDeclarationDefinition(ast_enum))
- ClangASTContext::CompleteTagDeclarationDefinition(ast_enum);
+
+ if (enum_type->isConstType())
+ ast_enum = ast_enum.AddConstModifier();
+
+ if (enum_type->isVolatileType())
+ ast_enum = ast_enum.AddVolatileModifier();
GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
@@ -288,23 +534,43 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
case PDB_SymType::Typedef: {
auto type_def = llvm::dyn_cast<PDBSymbolTypeTypedef>(&type);
assert(type_def);
+
lldb_private::Type *target_type =
m_ast.GetSymbolFile()->ResolveTypeUID(type_def->getTypeId());
if (!target_type)
return nullptr;
- std::string name = type_def->getName();
- uint64_t bytes = type_def->getLength();
- CompilerType target_ast_type = target_type->GetFullCompilerType();
- CompilerDeclContext target_decl_ctx =
- m_ast.GetSymbolFile()->GetDeclContextForUID(target_type->GetID());
+
+ std::string name =
+ MSVCUndecoratedNameParser::DropScope(type_def->getName());
+ auto decl_ctx = GetDeclContextContainingSymbol(type);
+
+ // Check if such a typedef already exists in the current context
CompilerType ast_typedef =
- m_ast.CreateTypedefType(target_ast_type, name.c_str(), target_decl_ctx);
- if (!ast_typedef)
- return nullptr;
+ m_ast.GetTypeForIdentifier<clang::TypedefNameDecl>(ConstString(name),
+ decl_ctx);
+ if (!ast_typedef.IsValid()) {
+ CompilerType target_ast_type = target_type->GetFullCompilerType();
+
+ ast_typedef = m_ast.CreateTypedefType(
+ target_ast_type, name.c_str(), CompilerDeclContext(&m_ast, decl_ctx));
+ if (!ast_typedef)
+ return nullptr;
+
+ auto typedef_decl = ClangASTContext::GetAsTypedefDecl(ast_typedef);
+ assert(typedef_decl);
+ m_uid_to_decl[type.getSymIndexId()] = typedef_decl;
+ }
+
+ if (type_def->isConstType())
+ ast_typedef = ast_typedef.AddConstModifier();
+
+ if (type_def->isVolatileType())
+ ast_typedef = ast_typedef.AddVolatileModifier();
+ GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
type_def->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(name),
- bytes, nullptr, target_type->GetID(),
+ type_def->getLength(), nullptr, target_type->GetID(),
lldb_private::Type::eEncodingIsTypedefUID, decl, ast_typedef,
lldb_private::Type::eResolveStateFull);
} break;
@@ -321,7 +587,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
return nullptr;
func_sig = sig.release();
// Function type is named.
- name = pdb_func->getName();
+ name = MSVCUndecoratedNameParser::DropScope(pdb_func->getName());
} else if (auto pdb_func_sig =
llvm::dyn_cast<PDBSymbolTypeFunctionSig>(&type)) {
func_sig = const_cast<PDBSymbolTypeFunctionSig *>(pdb_func_sig);
@@ -364,9 +630,10 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
type_quals |= clang::Qualifiers::Const;
if (func_sig->isVolatileType())
type_quals |= clang::Qualifiers::Volatile;
+ auto cc = TranslateCallingConvention(func_sig->getCallingConvention());
CompilerType func_sig_ast_type =
m_ast.CreateFunctionType(return_ast_type, arg_list.data(),
- arg_list.size(), is_variadic, type_quals);
+ arg_list.size(), is_variadic, type_quals, cc);
GetDeclarationForSymbol(type, decl);
return std::make_shared<lldb_private::Type>(
@@ -391,7 +658,7 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
CompilerType element_ast_type = element_type->GetForwardCompilerType();
// If element type is UDT, it needs to be complete.
if (ClangASTContext::IsCXXClassType(element_ast_type) &&
- element_ast_type.GetCompleteType() == false) {
+ !element_ast_type.GetCompleteType()) {
if (ClangASTContext::StartTagDeclarationDefinition(element_ast_type)) {
ClangASTContext::CompleteTagDeclarationDefinition(element_ast_type);
} else {
@@ -441,6 +708,26 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
if (!pointee_type)
return nullptr;
+ if (pointer_type->isPointerToDataMember() ||
+ pointer_type->isPointerToMemberFunction()) {
+ auto class_parent_uid = pointer_type->getRawSymbol().getClassParentId();
+ auto class_parent_type =
+ m_ast.GetSymbolFile()->ResolveTypeUID(class_parent_uid);
+ assert(class_parent_type);
+
+ CompilerType pointer_ast_type;
+ pointer_ast_type = ClangASTContext::CreateMemberPointerType(
+ class_parent_type->GetLayoutCompilerType(),
+ pointee_type->GetForwardCompilerType());
+ assert(pointer_ast_type);
+
+ return std::make_shared<lldb_private::Type>(
+ pointer_type->getSymIndexId(), m_ast.GetSymbolFile(), ConstString(),
+ pointer_type->getLength(), nullptr, LLDB_INVALID_UID,
+ lldb_private::Type::eEncodingIsUID, decl, pointer_ast_type,
+ lldb_private::Type::eResolveStateForward);
+ }
+
CompilerType pointer_ast_type;
pointer_ast_type = pointee_type->GetFullCompilerType();
if (pointer_type->isReference())
@@ -471,11 +758,363 @@ lldb::TypeSP PDBASTParser::CreateLLDBTypeFromPDBType(const PDBSymbol &type) {
return nullptr;
}
+bool PDBASTParser::CompleteTypeFromPDB(
+ lldb_private::CompilerType &compiler_type) {
+ if (GetClangASTImporter().CanImport(compiler_type))
+ return GetClangASTImporter().CompleteType(compiler_type);
+
+ // Remove the type from the forward declarations to avoid
+ // an endless recursion for types like a linked list.
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType());
+ auto uid_it = m_forward_decl_to_uid.find(record_decl);
+ if (uid_it == m_forward_decl_to_uid.end())
+ return true;
+
+ auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ if (!symbol_file)
+ return false;
+
+ std::unique_ptr<PDBSymbol> symbol =
+ symbol_file->GetPDBSession().getSymbolById(uid_it->getSecond());
+ if (!symbol)
+ return false;
+
+ m_forward_decl_to_uid.erase(uid_it);
+
+ ClangASTContext::SetHasExternalStorage(compiler_type.GetOpaqueQualType(),
+ false);
+
+ switch (symbol->getSymTag()) {
+ case PDB_SymType::UDT: {
+ auto udt = llvm::dyn_cast<PDBSymbolTypeUDT>(symbol.get());
+ if (!udt)
+ return false;
+
+ return CompleteTypeFromUDT(*symbol_file, compiler_type, *udt);
+ }
+ default:
+ llvm_unreachable("not a forward clang type decl!");
+ }
+}
+
+clang::Decl *
+PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) {
+ uint32_t sym_id = symbol.getSymIndexId();
+ auto it = m_uid_to_decl.find(sym_id);
+ if (it != m_uid_to_decl.end())
+ return it->second;
+
+ auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ if (!symbol_file)
+ return nullptr;
+
+ // First of all, check if the symbol is a member of a class. Resolve the full
+ // class type and return the declaration from the cache if so.
+ auto tag = symbol.getSymTag();
+ if (tag == PDB_SymType::Data || tag == PDB_SymType::Function) {
+ const IPDBSession &session = symbol.getSession();
+ const IPDBRawSymbol &raw = symbol.getRawSymbol();
+
+ auto class_parent_id = raw.getClassParentId();
+ if (std::unique_ptr<PDBSymbol> class_parent =
+ session.getSymbolById(class_parent_id)) {
+ auto class_parent_type = symbol_file->ResolveTypeUID(class_parent_id);
+ if (!class_parent_type)
+ return nullptr;
+
+ CompilerType class_parent_ct = class_parent_type->GetFullCompilerType();
+
+ // Look a declaration up in the cache after completing the class
+ clang::Decl *decl = m_uid_to_decl.lookup(sym_id);
+ if (decl)
+ return decl;
+
+ // A declaration was not found in the cache. It means that the symbol
+ // has the class parent, but the class doesn't have the symbol in its
+ // children list.
+ if (auto func = llvm::dyn_cast_or_null<PDBSymbolFunc>(&symbol)) {
+ // Try to find a class child method with the same RVA and use its
+ // declaration if found.
+ if (uint32_t rva = func->getRelativeVirtualAddress()) {
+ if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolFunc>>
+ methods_enum =
+ class_parent->findAllChildren<PDBSymbolFunc>()) {
+ while (std::unique_ptr<PDBSymbolFunc> method =
+ methods_enum->getNext()) {
+ if (method->getRelativeVirtualAddress() == rva) {
+ decl = m_uid_to_decl.lookup(method->getSymIndexId());
+ if (decl)
+ break;
+ }
+ }
+ }
+ }
+
+ // If no class methods with the same RVA were found, then create a new
+ // method. It is possible for template methods.
+ if (!decl)
+ decl = AddRecordMethod(*symbol_file, class_parent_ct, *func);
+ }
+
+ if (decl)
+ m_uid_to_decl[sym_id] = decl;
+
+ return decl;
+ }
+ }
+
+ // If we are here, then the symbol is not belonging to a class and is not
+ // contained in the cache. So create a declaration for it.
+ switch (symbol.getSymTag()) {
+ case PDB_SymType::Data: {
+ auto data = llvm::dyn_cast<PDBSymbolData>(&symbol);
+ assert(data);
+
+ auto decl_context = GetDeclContextContainingSymbol(symbol);
+ assert(decl_context);
+
+ // May be the current context is a class really, but we haven't found
+ // any class parent. This happens e.g. in the case of class static
+ // variables - they has two symbols, one is a child of the class when
+ // another is a child of the exe. So always complete the parent and use
+ // an existing declaration if possible.
+ if (auto parent_decl = llvm::dyn_cast_or_null<clang::TagDecl>(decl_context))
+ m_ast.GetCompleteDecl(parent_decl);
+
+ std::string name = MSVCUndecoratedNameParser::DropScope(data->getName());
+
+ // Check if the current context already contains the symbol with the name.
+ clang::Decl *decl =
+ GetDeclFromContextByName(*m_ast.getASTContext(), *decl_context, name);
+ if (!decl) {
+ auto type = symbol_file->ResolveTypeUID(data->getTypeId());
+ if (!type)
+ return nullptr;
+
+ decl = m_ast.CreateVariableDeclaration(
+ decl_context, name.c_str(),
+ ClangUtil::GetQualType(type->GetLayoutCompilerType()));
+ }
+
+ m_uid_to_decl[sym_id] = decl;
+
+ return decl;
+ }
+ case PDB_SymType::Function: {
+ auto func = llvm::dyn_cast<PDBSymbolFunc>(&symbol);
+ assert(func);
+
+ auto decl_context = GetDeclContextContainingSymbol(symbol);
+ assert(decl_context);
+
+ std::string name = MSVCUndecoratedNameParser::DropScope(func->getName());
+
+ Type *type = symbol_file->ResolveTypeUID(sym_id);
+ if (!type)
+ return nullptr;
+
+ auto storage = func->isStatic() ? clang::StorageClass::SC_Static
+ : clang::StorageClass::SC_None;
+
+ auto decl = m_ast.CreateFunctionDeclaration(
+ decl_context, name.c_str(), type->GetForwardCompilerType(), storage,
+ func->hasInlineAttribute());
+
+ std::vector<clang::ParmVarDecl *> params;
+ if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) {
+ if (std::unique_ptr<ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg>>
+ arg_enum = sig->findAllChildren<PDBSymbolTypeFunctionArg>()) {
+ while (std::unique_ptr<PDBSymbolTypeFunctionArg> arg =
+ arg_enum->getNext()) {
+ Type *arg_type = symbol_file->ResolveTypeUID(arg->getTypeId());
+ if (!arg_type)
+ continue;
+
+ clang::ParmVarDecl *param = m_ast.CreateParameterDeclaration(
+ decl, nullptr, arg_type->GetForwardCompilerType(),
+ clang::SC_None);
+ if (param)
+ params.push_back(param);
+ }
+ }
+ }
+ if (params.size())
+ m_ast.SetFunctionParameters(decl, params.data(), params.size());
+
+ m_uid_to_decl[sym_id] = decl;
+
+ return decl;
+ }
+ default: {
+ // It's not a variable and not a function, check if it's a type
+ Type *type = symbol_file->ResolveTypeUID(sym_id);
+ if (!type)
+ return nullptr;
+
+ return m_uid_to_decl.lookup(sym_id);
+ }
+ }
+}
+
+clang::DeclContext *
+PDBASTParser::GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol) {
+ if (symbol.getSymTag() == PDB_SymType::Function) {
+ clang::DeclContext *result =
+ llvm::dyn_cast_or_null<clang::FunctionDecl>(GetDeclForSymbol(symbol));
+
+ if (result)
+ m_decl_context_to_uid[result] = symbol.getSymIndexId();
+
+ return result;
+ }
+
+ auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ if (!symbol_file)
+ return nullptr;
+
+ auto type = symbol_file->ResolveTypeUID(symbol.getSymIndexId());
+ if (!type)
+ return nullptr;
+
+ clang::DeclContext *result =
+ m_ast.GetDeclContextForType(type->GetForwardCompilerType());
+
+ if (result)
+ m_decl_context_to_uid[result] = symbol.getSymIndexId();
+
+ return result;
+}
+
+clang::DeclContext *PDBASTParser::GetDeclContextContainingSymbol(
+ const llvm::pdb::PDBSymbol &symbol) {
+ auto parent = GetClassOrFunctionParent(symbol);
+ while (parent) {
+ if (auto parent_context = GetDeclContextForSymbol(*parent))
+ return parent_context;
+
+ parent = GetClassOrFunctionParent(*parent);
+ }
+
+ // We can't find any class or function parent of the symbol. So analyze
+ // the full symbol name. The symbol may be belonging to a namespace
+ // or function (or even to a class if it's e.g. a static variable symbol).
+
+ // TODO: Make clang to emit full names for variables in namespaces
+ // (as MSVC does)
+
+ std::string name(symbol.getRawSymbol().getName());
+ MSVCUndecoratedNameParser parser(name);
+ llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
+ if (specs.empty())
+ return m_ast.GetTranslationUnitDecl();
+
+ auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ if (!symbol_file)
+ return m_ast.GetTranslationUnitDecl();
+
+ auto global = symbol_file->GetPDBSession().getGlobalScope();
+ if (!global)
+ return m_ast.GetTranslationUnitDecl();
+
+ bool has_type_or_function_parent = false;
+ clang::DeclContext *curr_context = m_ast.GetTranslationUnitDecl();
+ for (std::size_t i = 0; i < specs.size() - 1; i++) {
+ // Check if there is a function or a type with the current context's name.
+ if (std::unique_ptr<IPDBEnumSymbols> children_enum = global->findChildren(
+ PDB_SymType::None, specs[i].GetFullName(), NS_CaseSensitive)) {
+ while (IPDBEnumChildren<PDBSymbol>::ChildTypePtr child =
+ children_enum->getNext()) {
+ if (clang::DeclContext *child_context =
+ GetDeclContextForSymbol(*child)) {
+ // Note that `GetDeclContextForSymbol' retrieves
+ // a declaration context for functions and types only,
+ // so if we are here then `child_context' is guaranteed
+ // a function or a type declaration context.
+ has_type_or_function_parent = true;
+ curr_context = child_context;
+ }
+ }
+ }
+
+ // If there were no functions or types above then retrieve a namespace with
+ // the current context's name. There can be no namespaces inside a function
+ // or a type. We check it to avoid fake namespaces such as `__l2':
+ // `N0::N1::CClass::PrivateFunc::__l2::InnerFuncStruct'
+ if (!has_type_or_function_parent) {
+ std::string namespace_name = specs[i].GetBaseName();
+ const char *namespace_name_c_str =
+ IsAnonymousNamespaceName(namespace_name) ? nullptr
+ : namespace_name.data();
+ clang::NamespaceDecl *namespace_decl =
+ m_ast.GetUniqueNamespaceDeclaration(namespace_name_c_str,
+ curr_context);
+
+ m_parent_to_namespaces[curr_context].insert(namespace_decl);
+ m_namespaces.insert(namespace_decl);
+
+ curr_context = namespace_decl;
+ }
+ }
+
+ return curr_context;
+}
+
+void PDBASTParser::ParseDeclsForDeclContext(
+ const clang::DeclContext *decl_context) {
+ auto symbol_file = static_cast<SymbolFilePDB *>(m_ast.GetSymbolFile());
+ if (!symbol_file)
+ return;
+
+ IPDBSession &session = symbol_file->GetPDBSession();
+ auto symbol_up =
+ session.getSymbolById(m_decl_context_to_uid.lookup(decl_context));
+ auto global_up = session.getGlobalScope();
+
+ PDBSymbol *symbol;
+ if (symbol_up)
+ symbol = symbol_up.get();
+ else if (global_up)
+ symbol = global_up.get();
+ else
+ return;
+
+ if (auto children = symbol->findAllChildren())
+ while (auto child = children->getNext())
+ GetDeclForSymbol(*child);
+}
+
+clang::NamespaceDecl *
+PDBASTParser::FindNamespaceDecl(const clang::DeclContext *parent,
+ llvm::StringRef name) {
+ NamespacesSet *set;
+ if (parent) {
+ auto pit = m_parent_to_namespaces.find(parent);
+ if (pit == m_parent_to_namespaces.end())
+ return nullptr;
+
+ set = &pit->second;
+ } else {
+ set = &m_namespaces;
+ }
+ assert(set);
+
+ for (clang::NamespaceDecl *namespace_decl : *set)
+ if (namespace_decl->getName().equals(name))
+ return namespace_decl;
+
+ for (clang::NamespaceDecl *namespace_decl : *set)
+ if (namespace_decl->isAnonymousNamespace())
+ return FindNamespaceDecl(namespace_decl, name);
+
+ return nullptr;
+}
+
bool PDBASTParser::AddEnumValue(CompilerType enum_type,
- const PDBSymbolData &enum_value) const {
+ const PDBSymbolData &enum_value) {
Declaration decl;
Variant v = enum_value.getValue();
- std::string name = enum_value.getName();
+ std::string name = MSVCUndecoratedNameParser::DropScope(enum_value.getName());
int64_t raw_value;
switch (v.Type) {
case PDB_VariantType::Int8:
@@ -509,7 +1148,213 @@ bool PDBASTParser::AddEnumValue(CompilerType enum_type,
m_ast.GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
uint32_t byte_size = m_ast.getASTContext()->getTypeSize(
ClangUtil::GetQualType(underlying_type));
- return m_ast.AddEnumerationValueToEnumerationType(
- enum_type.GetOpaqueQualType(), underlying_type, decl, name.c_str(),
- raw_value, byte_size * 8);
+ auto enum_constant_decl = m_ast.AddEnumerationValueToEnumerationType(
+ enum_type, decl, name.c_str(), raw_value, byte_size * 8);
+ if (!enum_constant_decl)
+ return false;
+
+ m_uid_to_decl[enum_value.getSymIndexId()] = enum_constant_decl;
+
+ return true;
+}
+
+bool PDBASTParser::CompleteTypeFromUDT(
+ lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &compiler_type,
+ llvm::pdb::PDBSymbolTypeUDT &udt) {
+ ClangASTImporter::LayoutInfo layout_info;
+ layout_info.bit_size = udt.getLength() * 8;
+
+ auto nested_enums = udt.findAllChildren<PDBSymbolTypeUDT>();
+ if (nested_enums)
+ while (auto nested = nested_enums->getNext())
+ symbol_file.ResolveTypeUID(nested->getSymIndexId());
+
+ auto bases_enum = udt.findAllChildren<PDBSymbolTypeBaseClass>();
+ if (bases_enum)
+ AddRecordBases(symbol_file, compiler_type,
+ TranslateUdtKind(udt.getUdtKind()), *bases_enum,
+ layout_info);
+
+ auto members_enum = udt.findAllChildren<PDBSymbolData>();
+ if (members_enum)
+ AddRecordMembers(symbol_file, compiler_type, *members_enum, layout_info);
+
+ auto methods_enum = udt.findAllChildren<PDBSymbolFunc>();
+ if (methods_enum)
+ AddRecordMethods(symbol_file, compiler_type, *methods_enum);
+
+ m_ast.AddMethodOverridesForCXXRecordType(compiler_type.GetOpaqueQualType());
+ ClangASTContext::BuildIndirectFields(compiler_type);
+ ClangASTContext::CompleteTagDeclarationDefinition(compiler_type);
+
+ clang::CXXRecordDecl *record_decl =
+ m_ast.GetAsCXXRecordDecl(compiler_type.GetOpaqueQualType());
+ if (!record_decl)
+ return static_cast<bool>(compiler_type);
+
+ GetClangASTImporter().InsertRecordDecl(record_decl, layout_info);
+
+ return static_cast<bool>(compiler_type);
+}
+
+void PDBASTParser::AddRecordMembers(
+ lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type,
+ PDBDataSymbolEnumerator &members_enum,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info) {
+ while (auto member = members_enum.getNext()) {
+ if (member->isCompilerGenerated())
+ continue;
+
+ auto member_name = member->getName();
+
+ auto member_type = symbol_file.ResolveTypeUID(member->getTypeId());
+ if (!member_type)
+ continue;
+
+ auto member_comp_type = member_type->GetLayoutCompilerType();
+ if (!member_comp_type.GetCompleteType()) {
+ symbol_file.GetObjectFile()->GetModule()->ReportError(
+ ":: Class '%s' has a member '%s' of type '%s' "
+ "which does not have a complete definition.",
+ record_type.GetTypeName().GetCString(), member_name.c_str(),
+ member_comp_type.GetTypeName().GetCString());
+ if (ClangASTContext::StartTagDeclarationDefinition(member_comp_type))
+ ClangASTContext::CompleteTagDeclarationDefinition(member_comp_type);
+ }
+
+ auto access = TranslateMemberAccess(member->getAccess());
+
+ switch (member->getDataKind()) {
+ case PDB_DataKind::Member: {
+ auto location_type = member->getLocationType();
+
+ auto bit_size = member->getLength();
+ if (location_type == PDB_LocType::ThisRel)
+ bit_size *= 8;
+
+ auto decl = ClangASTContext::AddFieldToRecordType(
+ record_type, member_name.c_str(), member_comp_type, access, bit_size);
+ if (!decl)
+ continue;
+
+ m_uid_to_decl[member->getSymIndexId()] = decl;
+
+ auto offset = member->getOffset() * 8;
+ if (location_type == PDB_LocType::BitField)
+ offset += member->getBitPosition();
+
+ layout_info.field_offsets.insert(std::make_pair(decl, offset));
+
+ break;
+ }
+ case PDB_DataKind::StaticMember: {
+ auto decl = ClangASTContext::AddVariableToRecordType(
+ record_type, member_name.c_str(), member_comp_type, access);
+ if (!decl)
+ continue;
+
+ m_uid_to_decl[member->getSymIndexId()] = decl;
+
+ break;
+ }
+ default:
+ llvm_unreachable("unsupported PDB data kind");
+ }
+ }
+}
+
+void PDBASTParser::AddRecordBases(
+ lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type, int record_kind,
+ PDBBaseClassSymbolEnumerator &bases_enum,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info) const {
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> base_classes;
+
+ while (auto base = bases_enum.getNext()) {
+ auto base_type = symbol_file.ResolveTypeUID(base->getTypeId());
+ if (!base_type)
+ continue;
+
+ auto base_comp_type = base_type->GetFullCompilerType();
+ if (!base_comp_type.GetCompleteType()) {
+ symbol_file.GetObjectFile()->GetModule()->ReportError(
+ ":: Class '%s' has a base class '%s' "
+ "which does not have a complete definition.",
+ record_type.GetTypeName().GetCString(),
+ base_comp_type.GetTypeName().GetCString());
+ if (ClangASTContext::StartTagDeclarationDefinition(base_comp_type))
+ ClangASTContext::CompleteTagDeclarationDefinition(base_comp_type);
+ }
+
+ auto access = TranslateMemberAccess(base->getAccess());
+
+ auto is_virtual = base->isVirtualBaseClass();
+
+ std::unique_ptr<clang::CXXBaseSpecifier> base_spec =
+ m_ast.CreateBaseClassSpecifier(base_comp_type.GetOpaqueQualType(),
+ access, is_virtual,
+ record_kind == clang::TTK_Class);
+ lldbassert(base_spec);
+
+ base_classes.push_back(std::move(base_spec));
+
+ if (is_virtual)
+ continue;
+
+ auto decl = m_ast.GetAsCXXRecordDecl(base_comp_type.GetOpaqueQualType());
+ if (!decl)
+ continue;
+
+ auto offset = clang::CharUnits::fromQuantity(base->getOffset());
+ layout_info.base_offsets.insert(std::make_pair(decl, offset));
+ }
+
+ m_ast.TransferBaseClasses(record_type.GetOpaqueQualType(),
+ std::move(base_classes));
+}
+
+void PDBASTParser::AddRecordMethods(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type,
+ PDBFuncSymbolEnumerator &methods_enum) {
+ while (std::unique_ptr<PDBSymbolFunc> method = methods_enum.getNext())
+ if (clang::CXXMethodDecl *decl =
+ AddRecordMethod(symbol_file, record_type, *method))
+ m_uid_to_decl[method->getSymIndexId()] = decl;
+}
+
+clang::CXXMethodDecl *
+PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type,
+ const llvm::pdb::PDBSymbolFunc &method) const {
+ std::string name = MSVCUndecoratedNameParser::DropScope(method.getName());
+
+ Type *method_type = symbol_file.ResolveTypeUID(method.getSymIndexId());
+ // MSVC specific __vecDelDtor.
+ if (!method_type)
+ return nullptr;
+
+ CompilerType method_comp_type = method_type->GetFullCompilerType();
+ if (!method_comp_type.GetCompleteType()) {
+ symbol_file.GetObjectFile()->GetModule()->ReportError(
+ ":: Class '%s' has a method '%s' whose type cannot be completed.",
+ record_type.GetTypeName().GetCString(),
+ method_comp_type.GetTypeName().GetCString());
+ if (ClangASTContext::StartTagDeclarationDefinition(method_comp_type))
+ ClangASTContext::CompleteTagDeclarationDefinition(method_comp_type);
+ }
+
+ AccessType access = TranslateMemberAccess(method.getAccess());
+ if (access == eAccessNone)
+ access = eAccessPublic;
+
+ // TODO: get mangled name for the method.
+ return m_ast.AddMethodToCXXRecordType(
+ record_type.GetOpaqueQualType(), name.c_str(),
+ /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(),
+ method.isStatic(), method.hasInlineAttribute(),
+ /*is_explicit*/ false, // FIXME: Need this field in CodeView.
+ /*is_attr_used*/ false,
+ /*is_artificial*/ method.isCompilerGenerated());
}
diff --git a/source/Plugins/SymbolFile/PDB/PDBASTParser.h b/source/Plugins/SymbolFile/PDB/PDBASTParser.h
index d1ac138b8115..02353870ab60 100644
--- a/source/Plugins/SymbolFile/PDB/PDBASTParser.h
+++ b/source/Plugins/SymbolFile/PDB/PDBASTParser.h
@@ -14,6 +14,8 @@
#include "lldb/Symbol/ClangASTImporter.h"
+class SymbolFilePDB;
+
namespace clang {
class CharUnits;
class CXXRecordDecl;
@@ -28,9 +30,14 @@ class CompilerType;
namespace llvm {
namespace pdb {
+template <typename ChildType> class ConcreteSymbolEnumerator;
+
class PDBSymbol;
class PDBSymbolData;
+class PDBSymbolFunc;
+class PDBSymbolTypeBaseClass;
class PDBSymbolTypeBuiltin;
+class PDBSymbolTypeUDT;
} // namespace pdb
} // namespace llvm
@@ -40,13 +47,71 @@ public:
~PDBASTParser();
lldb::TypeSP CreateLLDBTypeFromPDBType(const llvm::pdb::PDBSymbol &type);
+ bool CompleteTypeFromPDB(lldb_private::CompilerType &compiler_type);
+
+ clang::Decl *GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol);
+
+ clang::DeclContext *
+ GetDeclContextForSymbol(const llvm::pdb::PDBSymbol &symbol);
+ clang::DeclContext *
+ GetDeclContextContainingSymbol(const llvm::pdb::PDBSymbol &symbol);
+
+ void ParseDeclsForDeclContext(const clang::DeclContext *decl_context);
+
+ clang::NamespaceDecl *FindNamespaceDecl(const clang::DeclContext *parent,
+ llvm::StringRef name);
+
+ lldb_private::ClangASTImporter &GetClangASTImporter() {
+ return m_ast_importer;
+ }
private:
+ typedef llvm::DenseMap<clang::CXXRecordDecl *, lldb::user_id_t>
+ CXXRecordDeclToUidMap;
+ typedef llvm::DenseMap<lldb::user_id_t, clang::Decl *> UidToDeclMap;
+ typedef std::set<clang::NamespaceDecl *> NamespacesSet;
+ typedef llvm::DenseMap<clang::DeclContext *, NamespacesSet>
+ ParentToNamespacesMap;
+ typedef llvm::DenseMap<clang::DeclContext *, lldb::user_id_t>
+ DeclContextToUidMap;
+ typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolData>
+ PDBDataSymbolEnumerator;
+ typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolTypeBaseClass>
+ PDBBaseClassSymbolEnumerator;
+ typedef llvm::pdb::ConcreteSymbolEnumerator<llvm::pdb::PDBSymbolFunc>
+ PDBFuncSymbolEnumerator;
+
bool AddEnumValue(lldb_private::CompilerType enum_type,
- const llvm::pdb::PDBSymbolData &data) const;
+ const llvm::pdb::PDBSymbolData &data);
+ bool CompleteTypeFromUDT(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &compiler_type,
+ llvm::pdb::PDBSymbolTypeUDT &udt);
+ void
+ AddRecordMembers(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type,
+ PDBDataSymbolEnumerator &members_enum,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info);
+ void
+ AddRecordBases(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type, int record_kind,
+ PDBBaseClassSymbolEnumerator &bases_enum,
+ lldb_private::ClangASTImporter::LayoutInfo &layout_info) const;
+ void AddRecordMethods(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type,
+ PDBFuncSymbolEnumerator &methods_enum);
+ clang::CXXMethodDecl *
+ AddRecordMethod(lldb_private::SymbolFile &symbol_file,
+ lldb_private::CompilerType &record_type,
+ const llvm::pdb::PDBSymbolFunc &method) const;
lldb_private::ClangASTContext &m_ast;
lldb_private::ClangASTImporter m_ast_importer;
+
+ CXXRecordDeclToUidMap m_forward_decl_to_uid;
+ UidToDeclMap m_uid_to_decl;
+ ParentToNamespacesMap m_parent_to_namespaces;
+ NamespacesSet m_namespaces;
+ DeclContextToUidMap m_decl_context_to_uid;
};
#endif // LLDB_PLUGINS_SYMBOLFILE_PDB_PDBASTPARSER_H
diff --git a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
index 69ef70cc508c..9f398ef9b047 100644
--- a/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
+++ b/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
@@ -26,51 +26,51 @@ using namespace llvm::pdb;
namespace {
const uint32_t g_code_view_to_lldb_registers_x86[] = {
- LLDB_INVALID_REGNUM, // CVRegNONE
- lldb_al_i386, // CVRegAL
- lldb_cl_i386, // CVRegCL
- lldb_dl_i386, // CVRegDL
- lldb_bl_i386, // CVRegBL
- lldb_ah_i386, // CVRegAH
- lldb_ch_i386, // CVRegCH
- lldb_dh_i386, // CVRegDH
- lldb_bh_i386, // CVRegBH
- lldb_ax_i386, // CVRegAX
- lldb_cx_i386, // CVRegCX
- lldb_dx_i386, // CVRegDX
- lldb_bx_i386, // CVRegBX
- lldb_sp_i386, // CVRegSP
- lldb_bp_i386, // CVRegBP
- lldb_si_i386, // CVRegSI
- lldb_di_i386, // CVRegDI
- lldb_eax_i386, // CVRegEAX
- lldb_ecx_i386, // CVRegECX
- lldb_edx_i386, // CVRegEDX
- lldb_ebx_i386, // CVRegEBX
- lldb_esp_i386, // CVRegESP
- lldb_ebp_i386, // CVRegEBP
- lldb_esi_i386, // CVRegESI
- lldb_edi_i386, // CVRegEDI
- lldb_es_i386, // CVRegES
- lldb_cs_i386, // CVRegCS
- lldb_ss_i386, // CVRegSS
- lldb_ds_i386, // CVRegDS
- lldb_fs_i386, // CVRegFS
- lldb_gs_i386, // CVRegGS
- LLDB_INVALID_REGNUM, // CVRegIP
- LLDB_INVALID_REGNUM, // CVRegFLAGS
- lldb_eip_i386, // CVRegEIP
- lldb_eflags_i386, // CVRegEFLAGS
+ LLDB_INVALID_REGNUM, // NONE
+ lldb_al_i386, // AL
+ lldb_cl_i386, // CL
+ lldb_dl_i386, // DL
+ lldb_bl_i386, // BL
+ lldb_ah_i386, // AH
+ lldb_ch_i386, // CH
+ lldb_dh_i386, // DH
+ lldb_bh_i386, // BH
+ lldb_ax_i386, // AX
+ lldb_cx_i386, // CX
+ lldb_dx_i386, // DX
+ lldb_bx_i386, // BX
+ lldb_sp_i386, // SP
+ lldb_bp_i386, // BP
+ lldb_si_i386, // SI
+ lldb_di_i386, // DI
+ lldb_eax_i386, // EAX
+ lldb_ecx_i386, // ECX
+ lldb_edx_i386, // EDX
+ lldb_ebx_i386, // EBX
+ lldb_esp_i386, // ESP
+ lldb_ebp_i386, // EBP
+ lldb_esi_i386, // ESI
+ lldb_edi_i386, // EDI
+ lldb_es_i386, // ES
+ lldb_cs_i386, // CS
+ lldb_ss_i386, // SS
+ lldb_ds_i386, // DS
+ lldb_fs_i386, // FS
+ lldb_gs_i386, // GS
+ LLDB_INVALID_REGNUM, // IP
+ LLDB_INVALID_REGNUM, // FLAGS
+ lldb_eip_i386, // EIP
+ lldb_eflags_i386, // EFLAGS
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegTEMP
- LLDB_INVALID_REGNUM, // CVRegTEMPH
- LLDB_INVALID_REGNUM, // CVRegQUOTE
- LLDB_INVALID_REGNUM, // CVRegPCDR3
- LLDB_INVALID_REGNUM, // CVRegPCDR4
- LLDB_INVALID_REGNUM, // CVRegPCDR5
- LLDB_INVALID_REGNUM, // CVRegPCDR6
- LLDB_INVALID_REGNUM, // CVRegPCDR7
+ LLDB_INVALID_REGNUM, // TEMP
+ LLDB_INVALID_REGNUM, // TEMPH
+ LLDB_INVALID_REGNUM, // QUOTE
+ LLDB_INVALID_REGNUM, // PCDR3
+ LLDB_INVALID_REGNUM, // PCDR4
+ LLDB_INVALID_REGNUM, // PCDR5
+ LLDB_INVALID_REGNUM, // PCDR6
+ LLDB_INVALID_REGNUM, // PCDR7
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
@@ -82,123 +82,123 @@ const uint32_t g_code_view_to_lldb_registers_x86[] = {
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegCR0
- LLDB_INVALID_REGNUM, // CVRegCR1
- LLDB_INVALID_REGNUM, // CVRegCR2
- LLDB_INVALID_REGNUM, // CVRegCR3
- LLDB_INVALID_REGNUM, // CVRegCR4
+ LLDB_INVALID_REGNUM, // CR0
+ LLDB_INVALID_REGNUM, // CR1
+ LLDB_INVALID_REGNUM, // CR2
+ LLDB_INVALID_REGNUM, // CR3
+ LLDB_INVALID_REGNUM, // CR4
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- lldb_dr0_i386, // CVRegDR0
- lldb_dr1_i386, // CVRegDR1
- lldb_dr2_i386, // CVRegDR2
- lldb_dr3_i386, // CVRegDR3
- lldb_dr4_i386, // CVRegDR4
- lldb_dr5_i386, // CVRegDR5
- lldb_dr6_i386, // CVRegDR6
- lldb_dr7_i386, // CVRegDR7
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegGDTR
- LLDB_INVALID_REGNUM, // CVRegGDTL
- LLDB_INVALID_REGNUM, // CVRegIDTR
- LLDB_INVALID_REGNUM, // CVRegIDTL
- LLDB_INVALID_REGNUM, // CVRegLDTR
- LLDB_INVALID_REGNUM, // CVRegTR
- LLDB_INVALID_REGNUM, // CVRegPSEUDO1
- LLDB_INVALID_REGNUM, // CVRegPSEUDO2
- LLDB_INVALID_REGNUM, // CVRegPSEUDO3
- LLDB_INVALID_REGNUM, // CVRegPSEUDO4
- LLDB_INVALID_REGNUM, // CVRegPSEUDO5
- LLDB_INVALID_REGNUM, // CVRegPSEUDO6
- LLDB_INVALID_REGNUM, // CVRegPSEUDO7
- LLDB_INVALID_REGNUM, // CVRegPSEUDO8
- LLDB_INVALID_REGNUM, // CVRegPSEUDO9
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- lldb_st0_i386, // CVRegST0
- lldb_st1_i386, // CVRegST1
- lldb_st2_i386, // CVRegST2
- lldb_st3_i386, // CVRegST3
- lldb_st4_i386, // CVRegST4
- lldb_st5_i386, // CVRegST5
- lldb_st6_i386, // CVRegST6
- lldb_st7_i386, // CVRegST7
- LLDB_INVALID_REGNUM, // CVRegCTRL
- LLDB_INVALID_REGNUM, // CVRegSTAT
- LLDB_INVALID_REGNUM, // CVRegTAG
- LLDB_INVALID_REGNUM, // CVRegFPIP
- LLDB_INVALID_REGNUM, // CVRegFPCS
- LLDB_INVALID_REGNUM, // CVRegFPDO
- LLDB_INVALID_REGNUM, // CVRegFPDS
- LLDB_INVALID_REGNUM, // CVRegISEM
- LLDB_INVALID_REGNUM, // CVRegFPEIP
- LLDB_INVALID_REGNUM, // CVRegFPEDO
- lldb_mm0_i386, // CVRegMM0
- lldb_mm1_i386, // CVRegMM1
- lldb_mm2_i386, // CVRegMM2
- lldb_mm3_i386, // CVRegMM3
- lldb_mm4_i386, // CVRegMM4
- lldb_mm5_i386, // CVRegMM5
- lldb_mm6_i386, // CVRegMM6
- lldb_mm7_i386, // CVRegMM7
- lldb_xmm0_i386, // CVRegXMM0
- lldb_xmm1_i386, // CVRegXMM1
- lldb_xmm2_i386, // CVRegXMM2
- lldb_xmm3_i386, // CVRegXMM3
- lldb_xmm4_i386, // CVRegXMM4
- lldb_xmm5_i386, // CVRegXMM5
- lldb_xmm6_i386, // CVRegXMM6
- lldb_xmm7_i386 // CVRegXMM7
+ lldb_dr0_i386, // DR0
+ lldb_dr1_i386, // DR1
+ lldb_dr2_i386, // DR2
+ lldb_dr3_i386, // DR3
+ lldb_dr4_i386, // DR4
+ lldb_dr5_i386, // DR5
+ lldb_dr6_i386, // DR6
+ lldb_dr7_i386, // DR7
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, // GDTR
+ LLDB_INVALID_REGNUM, // GDTL
+ LLDB_INVALID_REGNUM, // IDTR
+ LLDB_INVALID_REGNUM, // IDTL
+ LLDB_INVALID_REGNUM, // LDTR
+ LLDB_INVALID_REGNUM, // TR
+ LLDB_INVALID_REGNUM, // PSEUDO1
+ LLDB_INVALID_REGNUM, // PSEUDO2
+ LLDB_INVALID_REGNUM, // PSEUDO3
+ LLDB_INVALID_REGNUM, // PSEUDO4
+ LLDB_INVALID_REGNUM, // PSEUDO5
+ LLDB_INVALID_REGNUM, // PSEUDO6
+ LLDB_INVALID_REGNUM, // PSEUDO7
+ LLDB_INVALID_REGNUM, // PSEUDO8
+ LLDB_INVALID_REGNUM, // PSEUDO9
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_st0_i386, // ST0
+ lldb_st1_i386, // ST1
+ lldb_st2_i386, // ST2
+ lldb_st3_i386, // ST3
+ lldb_st4_i386, // ST4
+ lldb_st5_i386, // ST5
+ lldb_st6_i386, // ST6
+ lldb_st7_i386, // ST7
+ LLDB_INVALID_REGNUM, // CTRL
+ LLDB_INVALID_REGNUM, // STAT
+ LLDB_INVALID_REGNUM, // TAG
+ LLDB_INVALID_REGNUM, // FPIP
+ LLDB_INVALID_REGNUM, // FPCS
+ LLDB_INVALID_REGNUM, // FPDO
+ LLDB_INVALID_REGNUM, // FPDS
+ LLDB_INVALID_REGNUM, // ISEM
+ LLDB_INVALID_REGNUM, // FPEIP
+ LLDB_INVALID_REGNUM, // FPEDO
+ lldb_mm0_i386, // MM0
+ lldb_mm1_i386, // MM1
+ lldb_mm2_i386, // MM2
+ lldb_mm3_i386, // MM3
+ lldb_mm4_i386, // MM4
+ lldb_mm5_i386, // MM5
+ lldb_mm6_i386, // MM6
+ lldb_mm7_i386, // MM7
+ lldb_xmm0_i386, // XMM0
+ lldb_xmm1_i386, // XMM1
+ lldb_xmm2_i386, // XMM2
+ lldb_xmm3_i386, // XMM3
+ lldb_xmm4_i386, // XMM4
+ lldb_xmm5_i386, // XMM5
+ lldb_xmm6_i386, // XMM6
+ lldb_xmm7_i386 // XMM7
};
const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
- LLDB_INVALID_REGNUM, // CVRegNONE
- lldb_al_x86_64, // CVRegAL
- lldb_cl_x86_64, // CVRegCL
- lldb_dl_x86_64, // CVRegDL
- lldb_bl_x86_64, // CVRegBL
- lldb_ah_x86_64, // CVRegAH
- lldb_ch_x86_64, // CVRegCH
- lldb_dh_x86_64, // CVRegDH
- lldb_bh_x86_64, // CVRegBH
- lldb_ax_x86_64, // CVRegAX
- lldb_cx_x86_64, // CVRegCX
- lldb_dx_x86_64, // CVRegDX
- lldb_bx_x86_64, // CVRegBX
- lldb_sp_x86_64, // CVRegSP
- lldb_bp_x86_64, // CVRegBP
- lldb_si_x86_64, // CVRegSI
- lldb_di_x86_64, // CVRegDI
- lldb_eax_x86_64, // CVRegEAX
- lldb_ecx_x86_64, // CVRegECX
- lldb_edx_x86_64, // CVRegEDX
- lldb_ebx_x86_64, // CVRegEBX
- lldb_esp_x86_64, // CVRegESP
- lldb_ebp_x86_64, // CVRegEBP
- lldb_esi_x86_64, // CVRegESI
- lldb_edi_x86_64, // CVRegEDI
- lldb_es_x86_64, // CVRegES
- lldb_cs_x86_64, // CVRegCS
- lldb_ss_x86_64, // CVRegSS
- lldb_ds_x86_64, // CVRegDS
- lldb_fs_x86_64, // CVRegFS
- lldb_gs_x86_64, // CVRegGS
- LLDB_INVALID_REGNUM, // CVRegIP
- LLDB_INVALID_REGNUM, // CVRegFLAGS
- LLDB_INVALID_REGNUM, // CVRegEIP
- LLDB_INVALID_REGNUM, // CVRegEFLAGS
+ LLDB_INVALID_REGNUM, // NONE
+ lldb_al_x86_64, // AL
+ lldb_cl_x86_64, // CL
+ lldb_dl_x86_64, // DL
+ lldb_bl_x86_64, // BL
+ lldb_ah_x86_64, // AH
+ lldb_ch_x86_64, // CH
+ lldb_dh_x86_64, // DH
+ lldb_bh_x86_64, // BH
+ lldb_ax_x86_64, // AX
+ lldb_cx_x86_64, // CX
+ lldb_dx_x86_64, // DX
+ lldb_bx_x86_64, // BX
+ lldb_sp_x86_64, // SP
+ lldb_bp_x86_64, // BP
+ lldb_si_x86_64, // SI
+ lldb_di_x86_64, // DI
+ lldb_eax_x86_64, // EAX
+ lldb_ecx_x86_64, // ECX
+ lldb_edx_x86_64, // EDX
+ lldb_ebx_x86_64, // EBX
+ lldb_esp_x86_64, // ESP
+ lldb_ebp_x86_64, // EBP
+ lldb_esi_x86_64, // ESI
+ lldb_edi_x86_64, // EDI
+ lldb_es_x86_64, // ES
+ lldb_cs_x86_64, // CS
+ lldb_ss_x86_64, // SS
+ lldb_ds_x86_64, // DS
+ lldb_fs_x86_64, // FS
+ lldb_gs_x86_64, // GS
+ LLDB_INVALID_REGNUM, // IP
+ LLDB_INVALID_REGNUM, // FLAGS
+ LLDB_INVALID_REGNUM, // EIP
+ LLDB_INVALID_REGNUM, // EFLAGS
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegTEMP
- LLDB_INVALID_REGNUM, // CVRegTEMPH
- LLDB_INVALID_REGNUM, // CVRegQUOTE
- LLDB_INVALID_REGNUM, // CVRegPCDR3
- LLDB_INVALID_REGNUM, // CVRegPCDR4
- LLDB_INVALID_REGNUM, // CVRegPCDR5
- LLDB_INVALID_REGNUM, // CVRegPCDR6
- LLDB_INVALID_REGNUM, // CVRegPCDR7
+ LLDB_INVALID_REGNUM, // TEMP
+ LLDB_INVALID_REGNUM, // TEMPH
+ LLDB_INVALID_REGNUM, // QUOTE
+ LLDB_INVALID_REGNUM, // PCDR3
+ LLDB_INVALID_REGNUM, // PCDR4
+ LLDB_INVALID_REGNUM, // PCDR5
+ LLDB_INVALID_REGNUM, // PCDR6
+ LLDB_INVALID_REGNUM, // PCDR7
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
@@ -210,75 +210,75 @@ const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegCR0
- LLDB_INVALID_REGNUM, // CVRegCR1
- LLDB_INVALID_REGNUM, // CVRegCR2
- LLDB_INVALID_REGNUM, // CVRegCR3
- LLDB_INVALID_REGNUM, // CVRegCR4
+ LLDB_INVALID_REGNUM, // CR0
+ LLDB_INVALID_REGNUM, // CR1
+ LLDB_INVALID_REGNUM, // CR2
+ LLDB_INVALID_REGNUM, // CR3
+ LLDB_INVALID_REGNUM, // CR4
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- lldb_dr0_x86_64, // CVRegDR0
- lldb_dr1_x86_64, // CVRegDR1
- lldb_dr2_x86_64, // CVRegDR2
- lldb_dr3_x86_64, // CVRegDR3
- lldb_dr4_x86_64, // CVRegDR4
- lldb_dr5_x86_64, // CVRegDR5
- lldb_dr6_x86_64, // CVRegDR6
- lldb_dr7_x86_64, // CVRegDR7
+ lldb_dr0_x86_64, // DR0
+ lldb_dr1_x86_64, // DR1
+ lldb_dr2_x86_64, // DR2
+ lldb_dr3_x86_64, // DR3
+ lldb_dr4_x86_64, // DR4
+ lldb_dr5_x86_64, // DR5
+ lldb_dr6_x86_64, // DR6
+ lldb_dr7_x86_64, // DR7
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegGDTR
- LLDB_INVALID_REGNUM, // CVRegGDTL
- LLDB_INVALID_REGNUM, // CVRegIDTR
- LLDB_INVALID_REGNUM, // CVRegIDTL
- LLDB_INVALID_REGNUM, // CVRegLDTR
- LLDB_INVALID_REGNUM, // CVRegTR
- LLDB_INVALID_REGNUM, // CVRegPSEUDO1
- LLDB_INVALID_REGNUM, // CVRegPSEUDO2
- LLDB_INVALID_REGNUM, // CVRegPSEUDO3
- LLDB_INVALID_REGNUM, // CVRegPSEUDO4
- LLDB_INVALID_REGNUM, // CVRegPSEUDO5
- LLDB_INVALID_REGNUM, // CVRegPSEUDO6
- LLDB_INVALID_REGNUM, // CVRegPSEUDO7
- LLDB_INVALID_REGNUM, // CVRegPSEUDO8
- LLDB_INVALID_REGNUM, // CVRegPSEUDO9
+ LLDB_INVALID_REGNUM, // GDTR
+ LLDB_INVALID_REGNUM, // GDTL
+ LLDB_INVALID_REGNUM, // IDTR
+ LLDB_INVALID_REGNUM, // IDTL
+ LLDB_INVALID_REGNUM, // LDTR
+ LLDB_INVALID_REGNUM, // TR
+ LLDB_INVALID_REGNUM, // PSEUDO1
+ LLDB_INVALID_REGNUM, // PSEUDO2
+ LLDB_INVALID_REGNUM, // PSEUDO3
+ LLDB_INVALID_REGNUM, // PSEUDO4
+ LLDB_INVALID_REGNUM, // PSEUDO5
+ LLDB_INVALID_REGNUM, // PSEUDO6
+ LLDB_INVALID_REGNUM, // PSEUDO7
+ LLDB_INVALID_REGNUM, // PSEUDO8
+ LLDB_INVALID_REGNUM, // PSEUDO9
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- lldb_st0_x86_64, // CVRegST0
- lldb_st1_x86_64, // CVRegST1
- lldb_st2_x86_64, // CVRegST2
- lldb_st3_x86_64, // CVRegST3
- lldb_st4_x86_64, // CVRegST4
- lldb_st5_x86_64, // CVRegST5
- lldb_st6_x86_64, // CVRegST6
- lldb_st7_x86_64, // CVRegST7
- LLDB_INVALID_REGNUM, // CVRegCTRL
- LLDB_INVALID_REGNUM, // CVRegSTAT
- LLDB_INVALID_REGNUM, // CVRegTAG
- LLDB_INVALID_REGNUM, // CVRegFPIP
- LLDB_INVALID_REGNUM, // CVRegFPCS
- LLDB_INVALID_REGNUM, // CVRegFPDO
- LLDB_INVALID_REGNUM, // CVRegFPDS
- LLDB_INVALID_REGNUM, // CVRegISEM
- LLDB_INVALID_REGNUM, // CVRegFPEIP
- LLDB_INVALID_REGNUM, // CVRegFPEDO
- lldb_mm0_x86_64, // CVRegMM0
- lldb_mm1_x86_64, // CVRegMM1
- lldb_mm2_x86_64, // CVRegMM2
- lldb_mm3_x86_64, // CVRegMM3
- lldb_mm4_x86_64, // CVRegMM4
- lldb_mm5_x86_64, // CVRegMM5
- lldb_mm6_x86_64, // CVRegMM6
- lldb_mm7_x86_64, // CVRegMM7
- lldb_xmm0_x86_64, // CVRegXMM0
- lldb_xmm1_x86_64, // CVRegXMM1
- lldb_xmm2_x86_64, // CVRegXMM2
- lldb_xmm3_x86_64, // CVRegXMM3
- lldb_xmm4_x86_64, // CVRegXMM4
- lldb_xmm5_x86_64, // CVRegXMM5
- lldb_xmm6_x86_64, // CVRegXMM6
- lldb_xmm7_x86_64, // CVRegXMM7
+ lldb_st0_x86_64, // ST0
+ lldb_st1_x86_64, // ST1
+ lldb_st2_x86_64, // ST2
+ lldb_st3_x86_64, // ST3
+ lldb_st4_x86_64, // ST4
+ lldb_st5_x86_64, // ST5
+ lldb_st6_x86_64, // ST6
+ lldb_st7_x86_64, // ST7
+ LLDB_INVALID_REGNUM, // CTRL
+ LLDB_INVALID_REGNUM, // STAT
+ LLDB_INVALID_REGNUM, // TAG
+ LLDB_INVALID_REGNUM, // FPIP
+ LLDB_INVALID_REGNUM, // FPCS
+ LLDB_INVALID_REGNUM, // FPDO
+ LLDB_INVALID_REGNUM, // FPDS
+ LLDB_INVALID_REGNUM, // ISEM
+ LLDB_INVALID_REGNUM, // FPEIP
+ LLDB_INVALID_REGNUM, // FPEDO
+ lldb_mm0_x86_64, // MM0
+ lldb_mm1_x86_64, // MM1
+ lldb_mm2_x86_64, // MM2
+ lldb_mm3_x86_64, // MM3
+ lldb_mm4_x86_64, // MM4
+ lldb_mm5_x86_64, // MM5
+ lldb_mm6_x86_64, // MM6
+ lldb_mm7_x86_64, // MM7
+ lldb_xmm0_x86_64, // XMM0
+ lldb_xmm1_x86_64, // XMM1
+ lldb_xmm2_x86_64, // XMM2
+ lldb_xmm3_x86_64, // XMM3
+ lldb_xmm4_x86_64, // XMM4
+ lldb_xmm5_x86_64, // XMM5
+ lldb_xmm6_x86_64, // XMM6
+ lldb_xmm7_x86_64, // XMM7
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
@@ -296,51 +296,51 @@ const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM,
- lldb_mxcsr_x86_64, // CVRegMXCSR
- LLDB_INVALID_REGNUM, // CVRegEDXEAX
+ lldb_mxcsr_x86_64, // MXCSR
+ LLDB_INVALID_REGNUM, // EDXEAX
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, // CVRegEMM0L
- LLDB_INVALID_REGNUM, // CVRegEMM1L
- LLDB_INVALID_REGNUM, // CVRegEMM2L
- LLDB_INVALID_REGNUM, // CVRegEMM3L
- LLDB_INVALID_REGNUM, // CVRegEMM4L
- LLDB_INVALID_REGNUM, // CVRegEMM5L
- LLDB_INVALID_REGNUM, // CVRegEMM6L
- LLDB_INVALID_REGNUM, // CVRegEMM7L
- LLDB_INVALID_REGNUM, // CVRegEMM0H
- LLDB_INVALID_REGNUM, // CVRegEMM1H
- LLDB_INVALID_REGNUM, // CVRegEMM2H
- LLDB_INVALID_REGNUM, // CVRegEMM3H
- LLDB_INVALID_REGNUM, // CVRegEMM4H
- LLDB_INVALID_REGNUM, // CVRegEMM5H
- LLDB_INVALID_REGNUM, // CVRegEMM6H
- LLDB_INVALID_REGNUM, // CVRegEMM7H
- LLDB_INVALID_REGNUM, // CVRegMM00
- LLDB_INVALID_REGNUM, // CVRegMM01
- LLDB_INVALID_REGNUM, // CVRegMM10
- LLDB_INVALID_REGNUM, // CVRegMM11
- LLDB_INVALID_REGNUM, // CVRegMM20
- LLDB_INVALID_REGNUM, // CVRegMM21
- LLDB_INVALID_REGNUM, // CVRegMM30
- LLDB_INVALID_REGNUM, // CVRegMM31
- LLDB_INVALID_REGNUM, // CVRegMM40
- LLDB_INVALID_REGNUM, // CVRegMM41
- LLDB_INVALID_REGNUM, // CVRegMM50
- LLDB_INVALID_REGNUM, // CVRegMM51
- LLDB_INVALID_REGNUM, // CVRegMM60
- LLDB_INVALID_REGNUM, // CVRegMM61
- LLDB_INVALID_REGNUM, // CVRegMM70
- LLDB_INVALID_REGNUM, // CVRegMM71
- lldb_xmm8_x86_64, // CVRegXMM8
- lldb_xmm9_x86_64, // CVRegXMM9
- lldb_xmm10_x86_64, // CVRegXMM10
- lldb_xmm11_x86_64, // CVRegXMM11
- lldb_xmm12_x86_64, // CVRegXMM12
- lldb_xmm13_x86_64, // CVRegXMM13
- lldb_xmm14_x86_64, // CVRegXMM14
- lldb_xmm15_x86_64, // CVRegXMM15
+ LLDB_INVALID_REGNUM, // EMM0L
+ LLDB_INVALID_REGNUM, // EMM1L
+ LLDB_INVALID_REGNUM, // EMM2L
+ LLDB_INVALID_REGNUM, // EMM3L
+ LLDB_INVALID_REGNUM, // EMM4L
+ LLDB_INVALID_REGNUM, // EMM5L
+ LLDB_INVALID_REGNUM, // EMM6L
+ LLDB_INVALID_REGNUM, // EMM7L
+ LLDB_INVALID_REGNUM, // EMM0H
+ LLDB_INVALID_REGNUM, // EMM1H
+ LLDB_INVALID_REGNUM, // EMM2H
+ LLDB_INVALID_REGNUM, // EMM3H
+ LLDB_INVALID_REGNUM, // EMM4H
+ LLDB_INVALID_REGNUM, // EMM5H
+ LLDB_INVALID_REGNUM, // EMM6H
+ LLDB_INVALID_REGNUM, // EMM7H
+ LLDB_INVALID_REGNUM, // MM00
+ LLDB_INVALID_REGNUM, // MM01
+ LLDB_INVALID_REGNUM, // MM10
+ LLDB_INVALID_REGNUM, // MM11
+ LLDB_INVALID_REGNUM, // MM20
+ LLDB_INVALID_REGNUM, // MM21
+ LLDB_INVALID_REGNUM, // MM30
+ LLDB_INVALID_REGNUM, // MM31
+ LLDB_INVALID_REGNUM, // MM40
+ LLDB_INVALID_REGNUM, // MM41
+ LLDB_INVALID_REGNUM, // MM50
+ LLDB_INVALID_REGNUM, // MM51
+ LLDB_INVALID_REGNUM, // MM60
+ LLDB_INVALID_REGNUM, // MM61
+ LLDB_INVALID_REGNUM, // MM70
+ LLDB_INVALID_REGNUM, // MM71
+ lldb_xmm8_x86_64, // XMM8
+ lldb_xmm9_x86_64, // XMM9
+ lldb_xmm10_x86_64, // XMM10
+ lldb_xmm11_x86_64, // XMM11
+ lldb_xmm12_x86_64, // XMM12
+ lldb_xmm13_x86_64, // XMM13
+ lldb_xmm14_x86_64, // XMM14
+ lldb_xmm15_x86_64, // XMM15
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
@@ -363,73 +363,73 @@ const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM,
- lldb_sil_x86_64, // CVRegSIL
- lldb_dil_x86_64, // CVRegDIL
- lldb_bpl_x86_64, // CVRegBPL
- lldb_spl_x86_64, // CVRegSPL
- lldb_rax_x86_64, // CVRegRAX
- lldb_rbx_x86_64, // CVRegRBX
- lldb_rcx_x86_64, // CVRegRCX
- lldb_rdx_x86_64, // CVRegRDX
- lldb_rsi_x86_64, // CVRegRSI
- lldb_rdi_x86_64, // CVRegRDI
- lldb_rbp_x86_64, // CVRegRBP
- lldb_rsp_x86_64, // CVRegRSP
- lldb_r8_x86_64, // CVRegR8
- lldb_r9_x86_64, // CVRegR9
- lldb_r10_x86_64, // CVRegR10
- lldb_r11_x86_64, // CVRegR11
- lldb_r12_x86_64, // CVRegR12
- lldb_r13_x86_64, // CVRegR13
- lldb_r14_x86_64, // CVRegR14
- lldb_r15_x86_64, // CVRegR15
- lldb_r8l_x86_64, // CVRegR8B
- lldb_r9l_x86_64, // CVRegR9B
- lldb_r10l_x86_64, // CVRegR10B
- lldb_r11l_x86_64, // CVRegR11B
- lldb_r12l_x86_64, // CVRegR12B
- lldb_r13l_x86_64, // CVRegR13B
- lldb_r14l_x86_64, // CVRegR14B
- lldb_r15l_x86_64, // CVRegR15B
- lldb_r8w_x86_64, // CVRegR8W
- lldb_r9w_x86_64, // CVRegR9W
- lldb_r10w_x86_64, // CVRegR10W
- lldb_r11w_x86_64, // CVRegR11W
- lldb_r12w_x86_64, // CVRegR12W
- lldb_r13w_x86_64, // CVRegR13W
- lldb_r14w_x86_64, // CVRegR14W
- lldb_r15w_x86_64, // CVRegR15W
- lldb_r8d_x86_64, // CVRegR8D
- lldb_r9d_x86_64, // CVRegR9D
- lldb_r10d_x86_64, // CVRegR10D
- lldb_r11d_x86_64, // CVRegR11D
- lldb_r12d_x86_64, // CVRegR12D
- lldb_r13d_x86_64, // CVRegR13D
- lldb_r14d_x86_64, // CVRegR14D
- lldb_r15d_x86_64, // CVRegR15D
- lldb_ymm0_x86_64, // CVRegAMD64_YMM0
- lldb_ymm1_x86_64, // CVRegAMD64_YMM1
- lldb_ymm2_x86_64, // CVRegAMD64_YMM2
- lldb_ymm3_x86_64, // CVRegAMD64_YMM3
- lldb_ymm4_x86_64, // CVRegAMD64_YMM4
- lldb_ymm5_x86_64, // CVRegAMD64_YMM5
- lldb_ymm6_x86_64, // CVRegAMD64_YMM6
- lldb_ymm7_x86_64, // CVRegAMD64_YMM7
- lldb_ymm8_x86_64, // CVRegAMD64_YMM8
- lldb_ymm9_x86_64, // CVRegAMD64_YMM9
- lldb_ymm10_x86_64, // CVRegAMD64_YMM10
- lldb_ymm11_x86_64, // CVRegAMD64_YMM11
- lldb_ymm12_x86_64, // CVRegAMD64_YMM12
- lldb_ymm13_x86_64, // CVRegAMD64_YMM13
- lldb_ymm14_x86_64, // CVRegAMD64_YMM14
- lldb_ymm15_x86_64, // CVRegAMD64_YMM15
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
- lldb_bnd0_x86_64, // CVRegBND0
- lldb_bnd1_x86_64, // CVRegBND1
- lldb_bnd2_x86_64 // CVRegBND2
+ lldb_sil_x86_64, // SIL
+ lldb_dil_x86_64, // DIL
+ lldb_bpl_x86_64, // BPL
+ lldb_spl_x86_64, // SPL
+ lldb_rax_x86_64, // RAX
+ lldb_rbx_x86_64, // RBX
+ lldb_rcx_x86_64, // RCX
+ lldb_rdx_x86_64, // RDX
+ lldb_rsi_x86_64, // RSI
+ lldb_rdi_x86_64, // RDI
+ lldb_rbp_x86_64, // RBP
+ lldb_rsp_x86_64, // RSP
+ lldb_r8_x86_64, // R8
+ lldb_r9_x86_64, // R9
+ lldb_r10_x86_64, // R10
+ lldb_r11_x86_64, // R11
+ lldb_r12_x86_64, // R12
+ lldb_r13_x86_64, // R13
+ lldb_r14_x86_64, // R14
+ lldb_r15_x86_64, // R15
+ lldb_r8l_x86_64, // R8B
+ lldb_r9l_x86_64, // R9B
+ lldb_r10l_x86_64, // R10B
+ lldb_r11l_x86_64, // R11B
+ lldb_r12l_x86_64, // R12B
+ lldb_r13l_x86_64, // R13B
+ lldb_r14l_x86_64, // R14B
+ lldb_r15l_x86_64, // R15B
+ lldb_r8w_x86_64, // R8W
+ lldb_r9w_x86_64, // R9W
+ lldb_r10w_x86_64, // R10W
+ lldb_r11w_x86_64, // R11W
+ lldb_r12w_x86_64, // R12W
+ lldb_r13w_x86_64, // R13W
+ lldb_r14w_x86_64, // R14W
+ lldb_r15w_x86_64, // R15W
+ lldb_r8d_x86_64, // R8D
+ lldb_r9d_x86_64, // R9D
+ lldb_r10d_x86_64, // R10D
+ lldb_r11d_x86_64, // R11D
+ lldb_r12d_x86_64, // R12D
+ lldb_r13d_x86_64, // R13D
+ lldb_r14d_x86_64, // R14D
+ lldb_r15d_x86_64, // R15D
+ lldb_ymm0_x86_64, // AMD64_YMM0
+ lldb_ymm1_x86_64, // AMD64_YMM1
+ lldb_ymm2_x86_64, // AMD64_YMM2
+ lldb_ymm3_x86_64, // AMD64_YMM3
+ lldb_ymm4_x86_64, // AMD64_YMM4
+ lldb_ymm5_x86_64, // AMD64_YMM5
+ lldb_ymm6_x86_64, // AMD64_YMM6
+ lldb_ymm7_x86_64, // AMD64_YMM7
+ lldb_ymm8_x86_64, // AMD64_YMM8
+ lldb_ymm9_x86_64, // AMD64_YMM9
+ lldb_ymm10_x86_64, // AMD64_YMM10
+ lldb_ymm11_x86_64, // AMD64_YMM11
+ lldb_ymm12_x86_64, // AMD64_YMM12
+ lldb_ymm13_x86_64, // AMD64_YMM13
+ lldb_ymm14_x86_64, // AMD64_YMM14
+ lldb_ymm15_x86_64, // AMD64_YMM15
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ lldb_bnd0_x86_64, // BND0
+ lldb_bnd1_x86_64, // BND1
+ lldb_bnd2_x86_64 // BND2
};
uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
@@ -443,13 +443,13 @@ uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
register_id)];
switch (register_id) {
- case llvm::codeview::RegisterId::CVRegMXCSR:
+ case llvm::codeview::RegisterId::MXCSR:
return lldb_mxcsr_i386;
- case llvm::codeview::RegisterId::CVRegBND0:
+ case llvm::codeview::RegisterId::BND0:
return lldb_bnd0_i386;
- case llvm::codeview::RegisterId::CVRegBND1:
+ case llvm::codeview::RegisterId::BND1:
return lldb_bnd1_i386;
- case llvm::codeview::RegisterId::CVRegBND2:
+ case llvm::codeview::RegisterId::BND2:
return lldb_bnd2_i386;
default:
return LLDB_INVALID_REGNUM;
@@ -468,7 +468,7 @@ uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
}
uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
- if (register_id == llvm::codeview::RegisterId::CVRegVFRAME)
+ if (register_id == llvm::codeview::RegisterId::VFRAME)
return LLDB_REGNUM_GENERIC_FP;
return LLDB_INVALID_REGNUM;
diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
index 05f3017819fa..ad25842f4d05 100644
--- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -9,6 +9,9 @@
#include "SymbolFilePDB.h"
+#include "PDBASTParser.h"
+#include "PDBLocationToDWARFExpression.h"
+
#include "clang/Lex/Lexer.h"
#include "lldb/Core/Module.h"
@@ -46,8 +49,8 @@
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
-#include "Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h"
+#include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h"
#include <regex>
@@ -74,14 +77,32 @@ bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line,
}
} // namespace
+static bool ShouldUseNativeReader() {
+#if defined(_WIN32)
+ llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER");
+ return use_native.equals_lower("on") || use_native.equals_lower("yes") ||
+ use_native.equals_lower("1") || use_native.equals_lower("true");
+#else
+ return true;
+#endif
+}
+
void SymbolFilePDB::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- GetPluginDescriptionStatic(), CreateInstance,
- DebuggerInitialize);
+ if (ShouldUseNativeReader()) {
+ npdb::SymbolFileNativePDB::Initialize();
+ } else {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+ }
}
void SymbolFilePDB::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
+ if (ShouldUseNativeReader()) {
+ npdb::SymbolFileNativePDB::Terminate();
+ } else {
+ PluginManager::UnregisterPlugin(CreateInstance);
+ }
}
void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
@@ -246,14 +267,8 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) {
return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index);
}
-lldb::LanguageType
-SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
- // What fields should I expect to be filled out on the SymbolContext? Is it
- // safe to assume that `sc.comp_unit` is valid?
- if (!sc.comp_unit)
- return lldb::eLanguageTypeUnknown;
-
- auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+lldb::LanguageType SymbolFilePDB::ParseLanguage(CompileUnit &comp_unit) {
+ auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
if (!compiland_up)
return lldb::eLanguageTypeUnknown;
auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>();
@@ -262,9 +277,11 @@ SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) {
return TranslateLanguage(details->getLanguage());
}
-lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(
- const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) {
- lldbassert(sc.comp_unit && sc.module_sp.get());
+lldb_private::Function *
+SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(const PDBSymbolFunc &pdb_func,
+ CompileUnit &comp_unit) {
+ if (FunctionSP result = comp_unit.FindFunctionByUID(pdb_func.getSymIndexId()))
+ return result.get();
auto file_vm_addr = pdb_func.getVirtualAddress();
if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
@@ -272,7 +289,8 @@ lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(
auto func_length = pdb_func.getLength();
AddressRange func_range =
- AddressRange(file_vm_addr, func_length, sc.module_sp->GetSectionList());
+ AddressRange(file_vm_addr, func_length,
+ GetObjectFile()->GetModule()->GetSectionList());
if (!func_range.GetBaseAddress().IsValid())
return nullptr;
@@ -285,59 +303,61 @@ lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc(
Mangled mangled = GetMangledForPDBFunc(pdb_func);
FunctionSP func_sp =
- std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(),
+ std::make_shared<Function>(&comp_unit, pdb_func.getSymIndexId(),
func_type_uid, mangled, func_type, func_range);
- sc.comp_unit->AddFunction(func_sp);
+ comp_unit.AddFunction(func_sp);
+
+ TypeSystem *type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ if (!type_system)
+ return nullptr;
+ ClangASTContext *clang_type_system =
+ llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ if (!clang_type_system)
+ return nullptr;
+ clang_type_system->GetPDBParser()->GetDeclForSymbol(pdb_func);
+
return func_sp.get();
}
-size_t SymbolFilePDB::ParseCompileUnitFunctions(
- const lldb_private::SymbolContext &sc) {
- lldbassert(sc.comp_unit);
+size_t SymbolFilePDB::ParseFunctions(CompileUnit &comp_unit) {
size_t func_added = 0;
- auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
if (!compiland_up)
return 0;
auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>();
if (!results_up)
return 0;
while (auto pdb_func_up = results_up->getNext()) {
- auto func_sp =
- sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId());
+ auto func_sp = comp_unit.FindFunctionByUID(pdb_func_up->getSymIndexId());
if (!func_sp) {
- if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, sc))
+ if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, comp_unit))
++func_added;
}
}
return func_added;
}
-bool SymbolFilePDB::ParseCompileUnitLineTable(
- const lldb_private::SymbolContext &sc) {
- lldbassert(sc.comp_unit);
- if (sc.comp_unit->GetLineTable())
+bool SymbolFilePDB::ParseLineTable(CompileUnit &comp_unit) {
+ if (comp_unit.GetLineTable())
return true;
- return ParseCompileUnitLineTable(sc, 0);
+ return ParseCompileUnitLineTable(comp_unit, 0);
}
-bool SymbolFilePDB::ParseCompileUnitDebugMacros(
- const lldb_private::SymbolContext &sc) {
+bool SymbolFilePDB::ParseDebugMacros(CompileUnit &comp_unit) {
// PDB doesn't contain information about macros
return false;
}
-bool SymbolFilePDB::ParseCompileUnitSupportFiles(
- const lldb_private::SymbolContext &sc,
- lldb_private::FileSpecList &support_files) {
- lldbassert(sc.comp_unit);
+bool SymbolFilePDB::ParseSupportFiles(
+ CompileUnit &comp_unit, lldb_private::FileSpecList &support_files) {
// In theory this is unnecessary work for us, because all of this information
// is easily (and quickly) accessible from DebugInfoPDB, so caching it a
// second time seems like a waste. Unfortunately, there's no good way around
// this short of a moderate refactor since SymbolVendor depends on being able
// to cache this list.
- auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
if (!compiland_up)
return false;
auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
@@ -345,13 +365,13 @@ bool SymbolFilePDB::ParseCompileUnitSupportFiles(
return false;
while (auto file = files->getNext()) {
- FileSpec spec(file->getFileName(), false, FileSpec::Style::windows);
+ FileSpec spec(file->getFileName(), FileSpec::Style::windows);
support_files.AppendIfUnique(spec);
}
// LLDB uses the DWARF-like file numeration (one based),
// the zeroth file is the compile unit itself
- support_files.Insert(0, *sc.comp_unit);
+ support_files.Insert(0, comp_unit);
return true;
}
@@ -364,9 +384,8 @@ bool SymbolFilePDB::ParseImportedModules(
}
static size_t ParseFunctionBlocksForPDBSymbol(
- const lldb_private::SymbolContext &sc, uint64_t func_file_vm_addr,
- const llvm::pdb::PDBSymbol *pdb_symbol, lldb_private::Block *parent_block,
- bool is_top_parent) {
+ uint64_t func_file_vm_addr, const llvm::pdb::PDBSymbol *pdb_symbol,
+ lldb_private::Block *parent_block, bool is_top_parent) {
assert(pdb_symbol && parent_block);
size_t num_added = 0;
@@ -405,7 +424,7 @@ static size_t ParseFunctionBlocksForPDBSymbol(
break;
while (auto symbol_up = results_up->getNext()) {
num_added += ParseFunctionBlocksForPDBSymbol(
- sc, func_file_vm_addr, symbol_up.get(), block, false);
+ func_file_vm_addr, symbol_up.get(), block, false);
}
} break;
default:
@@ -414,28 +433,22 @@ static size_t ParseFunctionBlocksForPDBSymbol(
return num_added;
}
-size_t
-SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) {
- lldbassert(sc.comp_unit && sc.function);
+size_t SymbolFilePDB::ParseBlocksRecursive(Function &func) {
size_t num_added = 0;
- auto uid = sc.function->GetID();
+ auto uid = func.GetID();
auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid);
if (!pdb_func_up)
return 0;
- Block &parent_block = sc.function->GetBlock(false);
- num_added =
- ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(),
- pdb_func_up.get(), &parent_block, true);
+ Block &parent_block = func.GetBlock(false);
+ num_added = ParseFunctionBlocksForPDBSymbol(
+ pdb_func_up->getVirtualAddress(), pdb_func_up.get(), &parent_block, true);
return num_added;
}
-size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
- lldbassert(sc.module_sp.get());
- if (!sc.comp_unit)
- return 0;
+size_t SymbolFilePDB::ParseTypes(CompileUnit &comp_unit) {
size_t num_added = 0;
- auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID());
+ auto compiland = GetPDBCompilandByUID(comp_unit.GetID());
if (!compiland)
return 0;
@@ -459,31 +472,26 @@ size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) {
// This should cause the type to get cached and stored in the `m_types`
// lookup.
- if (!ResolveTypeUID(symbol->getSymIndexId()))
- continue;
-
- ++num_added;
+ if (auto type = ResolveTypeUID(symbol->getSymIndexId())) {
+ // Resolve the type completely to avoid a completion
+ // (and so a list change, which causes an iterators invalidation)
+ // during a TypeList dumping
+ type->GetFullCompilerType();
+ ++num_added;
+ }
}
}
};
- if (sc.function) {
- auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(
- sc.function->GetID());
- if (!pdb_func)
- return 0;
- ParseTypesByTagFn(*pdb_func);
- } else {
- ParseTypesByTagFn(*compiland);
-
- // Also parse global types particularly coming from this compiland.
- // Unfortunately, PDB has no compiland information for each global type. We
- // have to parse them all. But ensure we only do this once.
- static bool parse_all_global_types = false;
- if (!parse_all_global_types) {
- ParseTypesByTagFn(*m_global_scope_up);
- parse_all_global_types = true;
- }
+ ParseTypesByTagFn(*compiland);
+
+ // Also parse global types particularly coming from this compiland.
+ // Unfortunately, PDB has no compiland information for each global type. We
+ // have to parse them all. But ensure we only do this once.
+ static bool parse_all_global_types = false;
+ if (!parse_all_global_types) {
+ ParseTypesByTagFn(*m_global_scope_up);
+ parse_all_global_types = true;
}
return num_added;
}
@@ -513,7 +521,7 @@ SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) {
auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
if (results && results->getChildCount()) {
while (auto result = results->getNext()) {
- auto cu_id = result->getCompilandId();
+ auto cu_id = GetCompilandId(*result);
// FIXME: We are not able to determine variable's compile unit.
if (cu_id == 0)
continue;
@@ -548,8 +556,7 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
llvm::dyn_cast_or_null<ClangASTContext>(type_system);
if (!clang_type_system)
return nullptr;
- PDBASTParser *pdb =
- llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser());
+ PDBASTParser *pdb = clang_type_system->GetPDBParser();
if (!pdb)
return nullptr;
@@ -567,34 +574,109 @@ lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) {
return result.get();
}
+llvm::Optional<SymbolFile::ArrayInfo> SymbolFilePDB::GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
+ return llvm::None;
+}
+
bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) {
- // TODO: Implement this
- return false;
+ std::lock_guard<std::recursive_mutex> guard(
+ GetObjectFile()->GetModule()->GetMutex());
+
+ ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ if (!clang_ast_ctx)
+ return false;
+
+ PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+ if (!pdb)
+ return false;
+
+ return pdb->CompleteTypeFromPDB(compiler_type);
}
lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) {
- return lldb_private::CompilerDecl();
+ ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ if (!clang_ast_ctx)
+ return CompilerDecl();
+
+ PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+ if (!pdb)
+ return CompilerDecl();
+
+ auto symbol = m_session_up->getSymbolById(uid);
+ if (!symbol)
+ return CompilerDecl();
+
+ auto decl = pdb->GetDeclForSymbol(*symbol);
+ if (!decl)
+ return CompilerDecl();
+
+ return CompilerDecl(clang_ast_ctx, decl);
}
lldb_private::CompilerDeclContext
SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) {
- // PDB always uses the translation unit decl context for everything. We can
- // improve this later but it's not easy because PDB doesn't provide a high
- // enough level of type fidelity in this area.
- return *m_tu_decl_ctx_up;
+ ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ if (!clang_ast_ctx)
+ return CompilerDeclContext();
+
+ PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+ if (!pdb)
+ return CompilerDeclContext();
+
+ auto symbol = m_session_up->getSymbolById(uid);
+ if (!symbol)
+ return CompilerDeclContext();
+
+ auto decl_context = pdb->GetDeclContextForSymbol(*symbol);
+ if (!decl_context)
+ return GetDeclContextContainingUID(uid);
+
+ return CompilerDeclContext(clang_ast_ctx, decl_context);
}
lldb_private::CompilerDeclContext
SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) {
- return *m_tu_decl_ctx_up;
+ ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ if (!clang_ast_ctx)
+ return CompilerDeclContext();
+
+ PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+ if (!pdb)
+ return CompilerDeclContext();
+
+ auto symbol = m_session_up->getSymbolById(uid);
+ if (!symbol)
+ return CompilerDeclContext();
+
+ auto decl_context = pdb->GetDeclContextContainingSymbol(*symbol);
+ assert(decl_context);
+
+ return CompilerDeclContext(clang_ast_ctx, decl_context);
}
void SymbolFilePDB::ParseDeclsForContext(
- lldb_private::CompilerDeclContext decl_ctx) {}
+ lldb_private::CompilerDeclContext decl_ctx) {
+ ClangASTContext *clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ if (!clang_ast_ctx)
+ return;
+
+ PDBASTParser *pdb = clang_ast_ctx->GetPDBParser();
+ if (!pdb)
+ return;
+
+ pdb->ParseDeclsForDeclContext(
+ static_cast<clang::DeclContext *>(decl_ctx.GetOpaqueDeclContext()));
+}
uint32_t
SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
- uint32_t resolve_scope,
+ SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) {
uint32_t resolved_flags = 0;
if (resolve_scope & eSymbolContextCompUnit ||
@@ -614,7 +696,8 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
lldbassert(sc.module_sp == cu_sp->GetModule());
}
- if (resolve_scope & eSymbolContextFunction) {
+ if (resolve_scope & eSymbolContextFunction ||
+ resolve_scope & eSymbolContextBlock) {
addr_t file_vm_addr = so_addr.GetFileAddress();
auto symbol_up =
m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function);
@@ -624,12 +707,16 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
auto func_uid = pdb_func->getSymIndexId();
sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get();
if (sc.function == nullptr)
- sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+ sc.function =
+ ParseCompileUnitFunctionForPDBFunc(*pdb_func, *sc.comp_unit);
if (sc.function) {
resolved_flags |= eSymbolContextFunction;
if (resolve_scope & eSymbolContextBlock) {
- Block &block = sc.function->GetBlock(true);
- sc.block = block.FindBlockByID(sc.function->GetID());
+ auto block_symbol = m_session_up->findSymbolByAddress(
+ file_vm_addr, PDB_SymType::Block);
+ auto block_id = block_symbol ? block_symbol->getSymIndexId()
+ : sc.function->GetID();
+ sc.block = sc.function->GetBlock(true).FindBlockByID(block_id);
if (sc.block)
resolved_flags |= eSymbolContextBlock;
}
@@ -650,7 +737,7 @@ SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
uint32_t SymbolFilePDB::ResolveSymbolContext(
const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines,
- uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) {
+ SymbolContextItem resolve_scope, lldb_private::SymbolContextList &sc_list) {
const size_t old_size = sc_list.GetSize();
if (resolve_scope & lldb::eSymbolContextCompUnit) {
// Locate all compilation units with line numbers referencing the specified
@@ -674,7 +761,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
std::string source_file = compiland->getSourceFileFullPath();
if (source_file.empty())
continue;
- FileSpec this_spec(source_file, false, FileSpec::Style::windows);
+ FileSpec this_spec(source_file, FileSpec::Style::windows);
bool need_full_match = !file_spec.GetDirectory().IsEmpty();
if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0)
continue;
@@ -691,7 +778,7 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
// table that match the requested line (or all lines if `line` == 0).
if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock |
eSymbolContextLineEntry)) {
- bool has_line_table = ParseCompileUnitLineTable(sc, line);
+ bool has_line_table = ParseCompileUnitLineTable(*sc.comp_unit, line);
if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) {
// The query asks for line entries, but we can't get them for the
@@ -734,7 +821,8 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
if (sc.function == nullptr) {
auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get());
assert(pdb_func);
- sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc);
+ sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func,
+ *sc.comp_unit);
}
if (sc.function && (resolve_scope & eSymbolContextBlock)) {
Block &block = sc.function->GetBlock(true);
@@ -759,24 +847,16 @@ uint32_t SymbolFilePDB::ResolveSymbolContext(
}
std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) {
- std::string decorated_name;
- auto vm_addr = pdb_data.getVirtualAddress();
- if (vm_addr != LLDB_INVALID_ADDRESS && vm_addr) {
- auto result_up =
- m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol);
- if (result_up) {
- while (auto symbol_up = result_up->getNext()) {
- if (symbol_up->getRawSymbol().getVirtualAddress() == vm_addr) {
- decorated_name = symbol_up->getRawSymbol().getName();
- break;
- }
- }
- }
- }
- if (!decorated_name.empty())
- return decorated_name;
-
- return std::string();
+ // Cache public names at first
+ if (m_public_names.empty())
+ if (auto result_up =
+ m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol))
+ while (auto symbol_up = result_up->getNext())
+ if (auto addr = symbol_up->getRawSymbol().getVirtualAddress())
+ m_public_names[addr] = symbol_up->getRawSymbol().getName();
+
+ // Look up the name in the cache
+ return m_public_names.lookup(pdb_data.getVirtualAddress());
}
VariableSP SymbolFilePDB::ParseVariableForPDBData(
@@ -843,7 +923,7 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData(
uint32_t src_file_id = first_line->getSourceFileId();
auto src_file = m_session_up->getSourceFileById(src_file_id);
if (src_file) {
- FileSpec spec(src_file->getFileName(), /*resolve_path*/ false);
+ FileSpec spec(src_file->getFileName());
decl.SetFile(spec);
decl.SetColumn(first_line->getColumnNumber());
decl.SetLine(first_line->getLineNumber());
@@ -857,7 +937,7 @@ VariableSP SymbolFilePDB::ParseVariableForPDBData(
if (scope == eValueTypeVariableLocal) {
if (sc.function) {
context_scope = sc.function->GetBlock(true).FindBlockByID(
- pdb_data.getClassParentId());
+ pdb_data.getLexicalParentId());
if (context_scope == nullptr)
context_scope = sc.function;
}
@@ -937,6 +1017,9 @@ SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc,
if (variable_list)
variable_list->AddVariableIfUnique(var_sp);
++num_added;
+ PDBASTParser *ast = GetPDBAstParser();
+ if (ast)
+ ast->GetDeclForSymbol(*pdb_data);
}
}
}
@@ -959,9 +1042,7 @@ uint32_t SymbolFilePDB::FindGlobalVariables(
if (name.IsEmpty())
return 0;
- auto results =
- m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(),
- PDB_NameSearchFlags::NS_CaseSensitive);
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolData>();
if (!results)
return 0;
@@ -976,11 +1057,19 @@ uint32_t SymbolFilePDB::FindGlobalVariables(
sc.module_sp = m_obj_file->GetModule();
lldbassert(sc.module_sp.get());
- sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+ if (!name.GetStringRef().equals(
+ MSVCUndecoratedNameParser::DropScope(pdb_data->getName())))
+ continue;
+
+ sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
// FIXME: We are not able to determine the compile unit.
if (sc.comp_unit == nullptr)
continue;
+ if (parent_decl_ctx && GetDeclContextContainingUID(
+ result->getSymIndexId()) != *parent_decl_ctx)
+ continue;
+
ParseVariables(sc, *pdb_data, &variables);
matches = variables.GetSize() - old_size;
}
@@ -1013,7 +1102,7 @@ SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression &regex,
sc.module_sp = m_obj_file->GetModule();
lldbassert(sc.module_sp.get());
- sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get();
+ sc.comp_unit = ParseCompileUnitForUID(GetCompilandId(*pdb_data)).get();
// FIXME: We are not able to determine the compile unit.
if (sc.comp_unit == nullptr)
continue;
@@ -1033,7 +1122,7 @@ bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func,
if (!sc.comp_unit)
return false;
sc.module_sp = sc.comp_unit->GetModule();
- sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc);
+ sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, *sc.comp_unit);
if (!sc.function)
return false;
@@ -1075,22 +1164,11 @@ void SymbolFilePDB::CacheFunctionNames() {
// Class. We won't bother to check if the parent is UDT or Enum here.
m_func_method_names.Append(ConstString(name), uid);
- ConstString cstr_name(name);
-
// To search a method name, like NS::Class:MemberFunc, LLDB searches
// its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does
// not have inforamtion of this, we extract base names and cache them
// by our own effort.
- llvm::StringRef basename;
- CPlusPlusLanguage::MethodName cpp_method(cstr_name);
- if (cpp_method.IsValid()) {
- llvm::StringRef context;
- basename = cpp_method.GetBasename();
- if (basename.empty())
- CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(),
- context, basename);
- }
-
+ llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name);
if (!basename.empty())
m_func_base_names.Append(ConstString(basename), uid);
else {
@@ -1103,11 +1181,12 @@ void SymbolFilePDB::CacheFunctionNames() {
} else {
// Handle not-method symbols.
- // The function name might contain namespace, or its lexical scope. It
- // is not safe to get its base name by applying same scheme as we deal
- // with the method names.
- // FIXME: Remove namespace if function is static in a scope.
- m_func_base_names.Append(ConstString(name), uid);
+ // The function name might contain namespace, or its lexical scope.
+ llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(name);
+ if (!basename.empty())
+ m_func_base_names.Append(ConstString(basename), uid);
+ else
+ m_func_base_names.Append(ConstString(name), uid);
if (name == "main") {
m_func_full_names.Append(ConstString(name), uid);
@@ -1157,7 +1236,7 @@ void SymbolFilePDB::CacheFunctionNames() {
uint32_t SymbolFilePDB::FindFunctions(
const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines, bool append,
+ FunctionNameType name_type_mask, bool include_inlines, bool append,
lldb_private::SymbolContextList &sc_list) {
if (!append)
sc_list.Clear();
@@ -1177,20 +1256,28 @@ uint32_t SymbolFilePDB::FindFunctions(
CacheFunctionNames();
std::set<uint32_t> resolved_ids;
- auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids,
- this](UniqueCStringMap<uint32_t> &Names) {
+ auto ResolveFn = [this, &name, parent_decl_ctx, include_inlines, &sc_list,
+ &resolved_ids](UniqueCStringMap<uint32_t> &Names) {
std::vector<uint32_t> ids;
- if (Names.GetValues(name, ids)) {
- for (auto id : ids) {
- if (resolved_ids.find(id) == resolved_ids.end()) {
- if (ResolveFunction(id, include_inlines, sc_list))
- resolved_ids.insert(id);
- }
- }
+ if (!Names.GetValues(name, ids))
+ return;
+
+ for (uint32_t id : ids) {
+ if (resolved_ids.find(id) != resolved_ids.end())
+ continue;
+
+ if (parent_decl_ctx &&
+ GetDeclContextContainingUID(id) != *parent_decl_ctx)
+ continue;
+
+ if (ResolveFunction(id, include_inlines, sc_list))
+ resolved_ids.insert(id);
}
};
if (name_type_mask & eFunctionNameTypeFull) {
ResolveFn(m_func_full_names);
+ ResolveFn(m_func_base_names);
+ ResolveFn(m_func_method_names);
}
if (name_type_mask & eFunctionNameTypeBase) {
ResolveFn(m_func_base_names);
@@ -1236,8 +1323,59 @@ void SymbolFilePDB::GetMangledNamesForFunction(
const std::string &scope_qualified_name,
std::vector<lldb_private::ConstString> &mangled_names) {}
+void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) {
+ std::set<lldb::addr_t> sym_addresses;
+ for (size_t i = 0; i < symtab.GetNumSymbols(); i++)
+ sym_addresses.insert(symtab.SymbolAtIndex(i)->GetFileAddress());
+
+ auto results = m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>();
+ if (!results)
+ return;
+
+ auto section_list = m_obj_file->GetSectionList();
+ if (!section_list)
+ return;
+
+ while (auto pub_symbol = results->getNext()) {
+ auto section_idx = pub_symbol->getAddressSection() - 1;
+ if (section_idx >= section_list->GetSize())
+ continue;
+
+ auto section = section_list->GetSectionAtIndex(section_idx);
+ if (!section)
+ continue;
+
+ auto offset = pub_symbol->getAddressOffset();
+
+ auto file_addr = section->GetFileAddress() + offset;
+ if (sym_addresses.find(file_addr) != sym_addresses.end())
+ continue;
+ sym_addresses.insert(file_addr);
+
+ auto size = pub_symbol->getLength();
+ symtab.AddSymbol(
+ Symbol(pub_symbol->getSymIndexId(), // symID
+ pub_symbol->getName().c_str(), // name
+ true, // name_is_mangled
+ pub_symbol->isCode() ? eSymbolTypeCode : eSymbolTypeData, // type
+ true, // external
+ false, // is_debug
+ false, // is_trampoline
+ false, // is_artificial
+ section, // section_sp
+ offset, // value
+ size, // size
+ size != 0, // size_is_valid
+ false, // contains_linker_annotations
+ 0 // flags
+ ));
+ }
+
+ symtab.CalculateSymbolSizes();
+ symtab.Finalize();
+}
+
uint32_t SymbolFilePDB::FindTypes(
- const lldb_private::SymbolContext &sc,
const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append,
uint32_t max_matches,
@@ -1253,14 +1391,20 @@ uint32_t SymbolFilePDB::FindTypes(
searched_symbol_files.clear();
searched_symbol_files.insert(this);
- std::string name_str = name.AsCString();
-
// There is an assumption 'name' is not a regex
- FindTypesByName(name_str, max_matches, types);
+ FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types);
return types.GetSize();
}
+void SymbolFilePDB::DumpClangAST(Stream &s) {
+ auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ auto clang = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ if (!clang)
+ return;
+ clang->Dump(s);
+}
+
void SymbolFilePDB::FindTypesByRegex(
const lldb_private::RegularExpression &regex, uint32_t max_matches,
lldb_private::TypeMap &types) {
@@ -1316,14 +1460,14 @@ void SymbolFilePDB::FindTypesByRegex(
}
}
-void SymbolFilePDB::FindTypesByName(const std::string &name,
- uint32_t max_matches,
- lldb_private::TypeMap &types) {
+void SymbolFilePDB::FindTypesByName(
+ llvm::StringRef name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ uint32_t max_matches, lldb_private::TypeMap &types) {
std::unique_ptr<IPDBEnumSymbols> results;
if (name.empty())
return;
- results = m_global_scope_up->findChildren(PDB_SymType::None, name,
- PDB_NameSearchFlags::NS_Default);
+ results = m_global_scope_up->findAllChildren(PDB_SymType::None);
if (!results)
return;
@@ -1332,6 +1476,11 @@ void SymbolFilePDB::FindTypesByName(const std::string &name,
while (auto result = results->getNext()) {
if (max_matches > 0 && matches >= max_matches)
break;
+
+ if (MSVCUndecoratedNameParser::DropScope(
+ result->getRawSymbol().getName()) != name)
+ continue;
+
switch (result->getSymTag()) {
case PDB_SymType::Enum:
case PDB_SymType::UDT:
@@ -1348,6 +1497,10 @@ void SymbolFilePDB::FindTypesByName(const std::string &name,
if (!ResolveTypeUID(result->getSymIndexId()))
continue;
+ if (parent_decl_ctx && GetDeclContextContainingUID(
+ result->getSymIndexId()) != *parent_decl_ctx)
+ continue;
+
auto iter = m_types.find(result->getSymIndexId());
if (iter == m_types.end())
continue;
@@ -1417,7 +1570,7 @@ void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol,
}
size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ TypeClass type_mask,
lldb_private::TypeList &type_list) {
TypeCollection type_collection;
uint32_t old_size = type_list.GetSize();
@@ -1454,11 +1607,40 @@ SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
return type_system;
}
+PDBASTParser *SymbolFilePDB::GetPDBAstParser() {
+ auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ if (!clang_type_system)
+ return nullptr;
+
+ return clang_type_system->GetPDBParser();
+}
+
+
lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace(
- const lldb_private::SymbolContext &sc,
const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx) {
- return lldb_private::CompilerDeclContext();
+ auto type_system = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus);
+ auto clang_type_system = llvm::dyn_cast_or_null<ClangASTContext>(type_system);
+ if (!clang_type_system)
+ return CompilerDeclContext();
+
+ PDBASTParser *pdb = clang_type_system->GetPDBParser();
+ if (!pdb)
+ return CompilerDeclContext();
+
+ clang::DeclContext *decl_context = nullptr;
+ if (parent_decl_ctx)
+ decl_context = static_cast<clang::DeclContext *>(
+ parent_decl_ctx->GetOpaqueDeclContext());
+
+ auto namespace_decl =
+ pdb->FindNamespaceDecl(decl_context, name.GetStringRef());
+ if (!namespace_decl)
+ return CompilerDeclContext();
+
+ return CompilerDeclContext(type_system,
+ static_cast<clang::DeclContext *>(namespace_decl));
}
lldb_private::ConstString SymbolFilePDB::GetPluginName() {
@@ -1516,11 +1698,9 @@ lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id,
return cu_sp;
}
-bool SymbolFilePDB::ParseCompileUnitLineTable(
- const lldb_private::SymbolContext &sc, uint32_t match_line) {
- lldbassert(sc.comp_unit);
-
- auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID());
+bool SymbolFilePDB::ParseCompileUnitLineTable(CompileUnit &comp_unit,
+ uint32_t match_line) {
+ auto compiland_up = GetPDBCompilandByUID(comp_unit.GetID());
if (!compiland_up)
return false;
@@ -1530,10 +1710,10 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
// to do a mapping so that we can hand out indices.
llvm::DenseMap<uint32_t, uint32_t> index_map;
BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map);
- auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
+ auto line_table = llvm::make_unique<LineTable>(&comp_unit);
// Find contributions to `compiland` from all source and header files.
- std::string path = sc.comp_unit->GetPath();
+ std::string path = comp_unit.GetPath();
auto files = m_session_up->getSourceFilesForCompiland(*compiland_up);
if (!files)
return false;
@@ -1617,7 +1797,7 @@ bool SymbolFilePDB::ParseCompileUnitLineTable(
}
if (line_table->GetSize()) {
- sc.comp_unit->SetLineTable(line_table.release());
+ comp_unit.SetLineTable(line_table.release());
return true;
}
return false;
@@ -1747,3 +1927,68 @@ bool SymbolFilePDB::DeclContextMatchesThisSymbolFile(
return false;
}
+
+uint32_t SymbolFilePDB::GetCompilandId(const llvm::pdb::PDBSymbolData &data) {
+ static const auto pred_upper = [](uint32_t lhs, SecContribInfo rhs) {
+ return lhs < rhs.Offset;
+ };
+
+ // Cache section contributions
+ if (m_sec_contribs.empty()) {
+ if (auto SecContribs = m_session_up->getSectionContribs()) {
+ while (auto SectionContrib = SecContribs->getNext()) {
+ auto comp_id = SectionContrib->getCompilandId();
+ if (!comp_id)
+ continue;
+
+ auto sec = SectionContrib->getAddressSection();
+ auto &sec_cs = m_sec_contribs[sec];
+
+ auto offset = SectionContrib->getAddressOffset();
+ auto it =
+ std::upper_bound(sec_cs.begin(), sec_cs.end(), offset, pred_upper);
+
+ auto size = SectionContrib->getLength();
+ sec_cs.insert(it, {offset, size, comp_id});
+ }
+ }
+ }
+
+ // Check by line number
+ if (auto Lines = data.getLineNumbers()) {
+ if (auto FirstLine = Lines->getNext())
+ return FirstLine->getCompilandId();
+ }
+
+ // Retrieve section + offset
+ uint32_t DataSection = data.getAddressSection();
+ uint32_t DataOffset = data.getAddressOffset();
+ if (DataSection == 0) {
+ if (auto RVA = data.getRelativeVirtualAddress())
+ m_session_up->addressForRVA(RVA, DataSection, DataOffset);
+ }
+
+ if (DataSection) {
+ // Search by section contributions
+ auto &sec_cs = m_sec_contribs[DataSection];
+ auto it =
+ std::upper_bound(sec_cs.begin(), sec_cs.end(), DataOffset, pred_upper);
+ if (it != sec_cs.begin()) {
+ --it;
+ if (DataOffset < it->Offset + it->Size)
+ return it->CompilandId;
+ }
+ } else {
+ // Search in lexical tree
+ auto LexParentId = data.getLexicalParentId();
+ while (auto LexParent = m_session_up->getSymbolById(LexParentId)) {
+ if (LexParent->getSymTag() == PDB_SymType::Exe)
+ break;
+ if (LexParent->getSymTag() == PDB_SymType::Compiland)
+ return LexParentId;
+ LexParentId = LexParent->getRawSymbol().getLexicalParentId();
+ }
+ }
+
+ return 0;
+}
diff --git a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
index 96b62d68a6c2..81288093b7d8 100644
--- a/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
+++ b/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h
@@ -20,6 +20,8 @@
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+class PDBASTParser;
+
class SymbolFilePDB : public lldb_private::SymbolFile {
public:
//------------------------------------------------------------------
@@ -58,33 +60,32 @@ public:
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
lldb::LanguageType
- ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override;
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
- size_t
- ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override;
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
- bool
- ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override;
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
- bool
- ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override;
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- bool ParseCompileUnitSupportFiles(
- const lldb_private::SymbolContext &sc,
- lldb_private::FileSpecList &support_files) override;
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ lldb_private::FileSpecList &support_files) override;
+
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
bool ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) override;
- size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override;
-
- size_t ParseTypes(const lldb_private::SymbolContext &sc) override;
+ size_t ParseBlocksRecursive(lldb_private::Function &func) override;
size_t
ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
bool CompleteType(lldb_private::CompilerType &compiler_type) override;
@@ -100,12 +101,13 @@ public:
ParseDeclsForContext(lldb_private::CompilerDeclContext decl_ctx) override;
uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
uint32_t
ResolveSymbolContext(const lldb_private::FileSpec &file_spec, uint32_t line,
- bool check_inlines, uint32_t resolve_scope,
+ bool check_inlines,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContextList &sc_list) override;
uint32_t
@@ -121,8 +123,8 @@ public:
uint32_t
FindFunctions(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask, bool include_inlines, bool append,
- lldb_private::SymbolContextList &sc_list) override;
+ lldb::FunctionNameType name_type_mask, bool include_inlines,
+ bool append, lldb_private::SymbolContextList &sc_list) override;
uint32_t FindFunctions(const lldb_private::RegularExpression &regex,
bool include_inlines, bool append,
@@ -132,9 +134,10 @@ public:
const std::string &scope_qualified_name,
std::vector<lldb_private::ConstString> &mangled_names) override;
+ void AddSymbols(lldb_private::Symtab &symtab) override;
+
uint32_t
- FindTypes(const lldb_private::SymbolContext &sc,
- const lldb_private::ConstString &name,
+ FindTypes(const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx,
bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
@@ -149,14 +152,13 @@ public:
lldb_private::TypeList *GetTypeList() override;
size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override;
lldb_private::TypeSystem *
GetTypeSystemForLanguage(lldb::LanguageType language) override;
lldb_private::CompilerDeclContext FindNamespace(
- const lldb_private::SymbolContext &sc,
const lldb_private::ConstString &name,
const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
@@ -168,19 +170,29 @@ public:
const llvm::pdb::IPDBSession &GetPDBSession() const;
+ void DumpClangAST(lldb_private::Stream &s) override;
+
private:
+ struct SecContribInfo {
+ uint32_t Offset;
+ uint32_t Size;
+ uint32_t CompilandId;
+ };
+ using SecContribsMap = std::map<uint32_t, std::vector<SecContribInfo>>;
+
lldb::CompUnitSP ParseCompileUnitForUID(uint32_t id,
uint32_t index = UINT32_MAX);
- bool ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc,
+ bool ParseCompileUnitLineTable(lldb_private::CompileUnit &comp_unit,
uint32_t match_line);
void BuildSupportFileIdToSupportFileIndexMap(
const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
llvm::DenseMap<uint32_t, uint32_t> &index_map) const;
- void FindTypesByName(const std::string &name, uint32_t max_matches,
- lldb_private::TypeMap &types);
+ void FindTypesByName(llvm::StringRef name,
+ const lldb_private::CompilerDeclContext *parent_decl_ctx,
+ uint32_t max_matches, lldb_private::TypeMap &types);
std::string GetMangledForPDBData(const llvm::pdb::PDBSymbolData &pdb_data);
@@ -203,11 +215,13 @@ private:
lldb_private::Function *
ParseCompileUnitFunctionForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func,
- const lldb_private::SymbolContext &sc);
+ lldb_private::CompileUnit &comp_unit);
void GetCompileUnitIndex(const llvm::pdb::PDBSymbolCompiland &pdb_compiland,
uint32_t &index);
+ PDBASTParser *GetPDBAstParser();
+
std::unique_ptr<llvm::pdb::PDBSymbolCompiland>
GetPDBCompilandByUID(uint32_t uid);
@@ -226,9 +240,14 @@ private:
bool DeclContextMatchesThisSymbolFile(
const lldb_private::CompilerDeclContext *decl_ctx);
+ uint32_t GetCompilandId(const llvm::pdb::PDBSymbolData &data);
+
llvm::DenseMap<uint32_t, lldb::CompUnitSP> m_comp_units;
llvm::DenseMap<uint32_t, lldb::TypeSP> m_types;
llvm::DenseMap<uint32_t, lldb::VariableSP> m_variables;
+ llvm::DenseMap<uint64_t, std::string> m_public_names;
+
+ SecContribsMap m_sec_contribs;
std::vector<lldb::TypeSP> m_builtin_types;
std::unique_ptr<llvm::pdb::IPDBSession> m_session_up;
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
index 64e2daf60ee5..08778bd1ba70 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -46,7 +46,7 @@ SymbolFile *SymbolFileSymtab::CreateInstance(ObjectFile *obj_file) {
}
size_t SymbolFileSymtab::GetTypes(SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ TypeClass type_mask,
lldb_private::TypeList &type_list) {
return 0;
}
@@ -131,15 +131,13 @@ CompUnitSP SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) {
return cu_sp;
}
-lldb::LanguageType
-SymbolFileSymtab::ParseCompileUnitLanguage(const SymbolContext &sc) {
+lldb::LanguageType SymbolFileSymtab::ParseLanguage(CompileUnit &comp_unit) {
return eLanguageTypeUnknown;
}
-size_t SymbolFileSymtab::ParseCompileUnitFunctions(const SymbolContext &sc) {
+size_t SymbolFileSymtab::ParseFunctions(CompileUnit &comp_unit) {
size_t num_added = 0;
// We must at least have a valid compile unit
- assert(sc.comp_unit != NULL);
const Symtab *symtab = m_obj_file->GetSymtab();
const Symbol *curr_symbol = NULL;
const Symbol *next_symbol = NULL;
@@ -185,7 +183,7 @@ size_t SymbolFileSymtab::ParseCompileUnitFunctions(const SymbolContext &sc) {
}
FunctionSP func_sp(
- new Function(sc.comp_unit,
+ new Function(&comp_unit,
symbol_idx, // UserID is the DIE offset
LLDB_INVALID_UID, // We don't have any type info
// for this function
@@ -194,7 +192,7 @@ size_t SymbolFileSymtab::ParseCompileUnitFunctions(const SymbolContext &sc) {
func_range)); // first address range
if (func_sp.get() != NULL) {
- sc.comp_unit->AddFunction(func_sp);
+ comp_unit.AddFunction(func_sp);
++num_added;
}
}
@@ -207,16 +205,16 @@ size_t SymbolFileSymtab::ParseCompileUnitFunctions(const SymbolContext &sc) {
return num_added;
}
-bool SymbolFileSymtab::ParseCompileUnitLineTable(const SymbolContext &sc) {
- return false;
-}
+size_t SymbolFileSymtab::ParseTypes(CompileUnit &comp_unit) { return 0; }
-bool SymbolFileSymtab::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
+bool SymbolFileSymtab::ParseLineTable(CompileUnit &comp_unit) { return false; }
+
+bool SymbolFileSymtab::ParseDebugMacros(CompileUnit &comp_unit) {
return false;
}
-bool SymbolFileSymtab::ParseCompileUnitSupportFiles(
- const SymbolContext &sc, FileSpecList &support_files) {
+bool SymbolFileSymtab::ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) {
return false;
}
@@ -225,11 +223,7 @@ bool SymbolFileSymtab::ParseImportedModules(
return false;
}
-size_t SymbolFileSymtab::ParseFunctionBlocks(const SymbolContext &sc) {
- return 0;
-}
-
-size_t SymbolFileSymtab::ParseTypes(const SymbolContext &sc) { return 0; }
+size_t SymbolFileSymtab::ParseBlocksRecursive(Function &func) { return 0; }
size_t SymbolFileSymtab::ParseVariablesForContext(const SymbolContext &sc) {
return 0;
@@ -239,12 +233,18 @@ Type *SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid) {
return NULL;
}
+llvm::Optional<SymbolFile::ArrayInfo>
+SymbolFileSymtab::GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) {
+ return llvm::None;
+}
+
bool SymbolFileSymtab::CompleteType(lldb_private::CompilerType &compiler_type) {
return false;
}
uint32_t SymbolFileSymtab::ResolveSymbolContext(const Address &so_addr,
- uint32_t resolve_scope,
+ SymbolContextItem resolve_scope,
SymbolContext &sc) {
if (m_obj_file->GetSymtab() == NULL)
return 0;
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
index d1887a707ea6..e4ec7a181333 100644
--- a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -10,13 +10,9 @@
#ifndef liblldb_SymbolFileSymtab_h_
#define liblldb_SymbolFileSymtab_h_
-// C Includes
-// C++ Includes
#include <map>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Symtab.h"
@@ -53,42 +49,41 @@ public:
lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
lldb::LanguageType
- ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override;
+ ParseLanguage(lldb_private::CompileUnit &comp_unit) override;
- size_t
- ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override;
+ size_t ParseFunctions(lldb_private::CompileUnit &comp_unit) override;
- bool
- ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override;
+ bool ParseLineTable(lldb_private::CompileUnit &comp_unit) override;
- bool
- ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override;
+ bool ParseDebugMacros(lldb_private::CompileUnit &comp_unit) override;
- bool ParseCompileUnitSupportFiles(
- const lldb_private::SymbolContext &sc,
- lldb_private::FileSpecList &support_files) override;
+ bool ParseSupportFiles(lldb_private::CompileUnit &comp_unit,
+ lldb_private::FileSpecList &support_files) override;
+
+ size_t ParseTypes(lldb_private::CompileUnit &comp_unit) override;
bool ParseImportedModules(
const lldb_private::SymbolContext &sc,
std::vector<lldb_private::ConstString> &imported_modules) override;
- size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override;
-
- size_t ParseTypes(const lldb_private::SymbolContext &sc) override;
+ size_t ParseBlocksRecursive(lldb_private::Function &func) override;
size_t
ParseVariablesForContext(const lldb_private::SymbolContext &sc) override;
lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override;
+ llvm::Optional<ArrayInfo> GetDynamicArrayInfoForUID(
+ lldb::user_id_t type_uid,
+ const lldb_private::ExecutionContext *exe_ctx) override;
bool CompleteType(lldb_private::CompilerType &compiler_type) override;
uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
lldb_private::SymbolContext &sc) override;
size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
- uint32_t type_mask,
+ lldb::TypeClass type_mask,
lldb_private::TypeList &type_list) override;
//------------------------------------------------------------------
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index d24510966878..425b612d786f 100644
--- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -101,16 +101,17 @@ SymbolVendorELF::CreateInstance(const lldb::ModuleSP &module_sp,
const FileSpec fspec = file_spec_list.GetFileSpecAtIndex(idx);
module_spec.GetFileSpec() = obj_file->GetFileSpec();
- module_spec.GetFileSpec().ResolvePath();
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
module_spec.GetSymbolFileSpec() = fspec;
module_spec.GetUUID() = uuid;
FileSpec dsym_fspec = Symbols::LocateExecutableSymbolFile(module_spec);
if (dsym_fspec) {
DataBufferSP dsym_file_data_sp;
lldb::offset_t dsym_file_data_offset = 0;
- ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(
- module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(),
- dsym_file_data_sp, dsym_file_data_offset);
+ ObjectFileSP dsym_objfile_sp =
+ ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0,
+ FileSystem::Instance().GetByteSize(dsym_fspec),
+ dsym_file_data_sp, dsym_file_data_offset);
if (dsym_objfile_sp) {
// This objfile is for debugging purposes. Sadly, ObjectFileELF won't
// be able to figure this out consistently as the symbol file may not
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
index e7aeebc96b94..b0d956e31dc9 100644
--- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
@@ -10,10 +10,6 @@
#ifndef liblldb_SymbolVendorELF_h_
#define liblldb_SymbolVendorELF_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
index c69eb7fd51c7..169eed817566 100644
--- a/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
+++ b/source/Plugins/SymbolVendor/MacOSX/SymbolVendorMacOSX.cpp
@@ -153,9 +153,10 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
if (dsym_fspec) {
DataBufferSP dsym_file_data_sp;
lldb::offset_t dsym_file_data_offset = 0;
- dsym_objfile_sp = ObjectFile::FindPlugin(
- module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(),
- dsym_file_data_sp, dsym_file_data_offset);
+ dsym_objfile_sp =
+ ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0,
+ FileSystem::Instance().GetByteSize(dsym_fspec),
+ dsym_file_data_sp, dsym_file_data_offset);
if (UUIDsMatch(module_sp.get(), dsym_objfile_sp.get(), feedback_strm)) {
// We need a XML parser if we hope to parse a plist...
if (XMLDocument::XMLEnabled()) {
@@ -172,8 +173,8 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
resources[strlen("/Contents/Resources/")] = '\0';
snprintf(dsym_uuid_plist_path, sizeof(dsym_uuid_plist_path),
"%s%s.plist", dsym_path, uuid_str.c_str());
- FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path, false);
- if (dsym_uuid_plist_spec.Exists()) {
+ FileSpec dsym_uuid_plist_spec(dsym_uuid_plist_path);
+ if (FileSystem::Instance().Exists(dsym_uuid_plist_spec)) {
ApplePropertyList plist(dsym_uuid_plist_path);
if (plist) {
std::string DBGBuildSourcePath;
@@ -236,14 +237,15 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
// object is DBGSourcePath
std::string DBGSourcePath =
object->GetStringValue();
- if (new_style_source_remapping_dictionary ==
- false &&
+ if (!new_style_source_remapping_dictionary &&
!original_DBGSourcePath_value.empty()) {
DBGSourcePath = original_DBGSourcePath_value;
}
if (DBGSourcePath[0] == '~') {
FileSpec resolved_source_path(
- DBGSourcePath.c_str(), true);
+ DBGSourcePath.c_str());
+ FileSystem::Instance().Resolve(
+ resolved_source_path);
DBGSourcePath =
resolved_source_path.GetPath();
}
@@ -256,8 +258,8 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
// Add this as another option in addition to
// the full source path remap.
if (do_truncate_remapping_names) {
- FileSpec build_path(key.AsCString(), false);
- FileSpec source_path(DBGSourcePath.c_str(), false);
+ FileSpec build_path(key.AsCString());
+ FileSpec source_path(DBGSourcePath.c_str());
build_path.RemoveLastPathComponent();
build_path.RemoveLastPathComponent();
source_path.RemoveLastPathComponent();
@@ -280,8 +282,8 @@ SymbolVendorMacOSX::CreateInstance(const lldb::ModuleSP &module_sp,
if (!DBGBuildSourcePath.empty() &&
!DBGSourcePath.empty()) {
if (DBGSourcePath[0] == '~') {
- FileSpec resolved_source_path(DBGSourcePath.c_str(),
- true);
+ FileSpec resolved_source_path(DBGSourcePath.c_str());
+ FileSystem::Instance().Resolve(resolved_source_path);
DBGSourcePath = resolved_source_path.GetPath();
}
module_sp->GetSourceMappingList().Append(
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
index 007a59378fc5..43e401330c5c 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
@@ -10,10 +10,6 @@
#include "AppleGetItemInfoHandler.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
@@ -242,7 +238,7 @@ AppleGetItemInfoHandler::GetItemInfo(Thread &thread, uint64_t item,
error.Clear();
- if (thread.SafeToCallFunctions() == false) {
+ if (!thread.SafeToCallFunctions()) {
if (log)
log->Printf("Not safe to call functions on thread 0x%" PRIx64,
thread.GetID());
@@ -340,6 +336,7 @@ AppleGetItemInfoHandler::GetItemInfo(Thread &thread, uint64_t item,
options.SetStopOthers(true);
options.SetTimeout(std::chrono::milliseconds(500));
options.SetTryAllThreads(false);
+ options.SetIsForUtilityExpr(true);
thread.CalculateExecutionContext(exe_ctx);
if (!m_get_item_info_impl_code) {
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
index 373808e0f7e8..ac3711ead878 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
@@ -10,14 +10,10 @@
#ifndef lldb_AppleGetItemInfoHandler_h_
#define lldb_AppleGetItemInfoHandler_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/Status.h"
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
index 0de32bf11416..78e50e673af0 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
@@ -10,10 +10,6 @@
#include "AppleGetPendingItemsHandler.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
@@ -245,7 +241,7 @@ AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue,
error.Clear();
- if (thread.SafeToCallFunctions() == false) {
+ if (!thread.SafeToCallFunctions()) {
if (log)
log->Printf("Not safe to call functions on thread 0x%" PRIx64,
thread.GetID());
@@ -349,6 +345,7 @@ AppleGetPendingItemsHandler::GetPendingItems(Thread &thread, addr_t queue,
options.SetStopOthers(true);
options.SetTimeout(std::chrono::milliseconds(500));
options.SetTryAllThreads(false);
+ options.SetIsForUtilityExpr(true);
thread.CalculateExecutionContext(exe_ctx);
if (get_pending_items_caller == NULL) {
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
index 139e05b1b6c9..d35a72c2ff43 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
@@ -11,14 +11,10 @@
#ifndef lldb_AppleGetPendingItemsHandler_h_
#define lldb_AppleGetPendingItemsHandler_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-public.h"
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
index 7855b3603a3a..245ff6742b43 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
@@ -9,10 +9,6 @@
#include "AppleGetQueuesHandler.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DiagnosticManager.h"
@@ -247,7 +243,7 @@ AppleGetQueuesHandler::GetCurrentQueues(Thread &thread, addr_t page_to_free,
error.Clear();
- if (thread.SafeToCallFunctions() == false) {
+ if (!thread.SafeToCallFunctions()) {
if (log)
log->Printf("Not safe to call functions on thread 0x%" PRIx64,
thread.GetID());
@@ -354,6 +350,7 @@ AppleGetQueuesHandler::GetCurrentQueues(Thread &thread, addr_t page_to_free,
options.SetStopOthers(true);
options.SetTimeout(std::chrono::milliseconds(500));
options.SetTryAllThreads(false);
+ options.SetIsForUtilityExpr(true);
thread.CalculateExecutionContext(exe_ctx);
ExpressionResults func_call_ret;
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
index f1c79044496f..0d8e4dc64a68 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
@@ -10,14 +10,10 @@
#ifndef lldb_AppleGetQueuesHandler_h_
#define lldb_AppleGetQueuesHandler_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-public.h"
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
index 09ab6600a9f0..ede81333a3e6 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
@@ -10,10 +10,6 @@
#include "AppleGetThreadItemInfoHandler.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
@@ -252,7 +248,7 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread,
error.Clear();
- if (thread.SafeToCallFunctions() == false) {
+ if (!thread.SafeToCallFunctions()) {
if (log)
log->Printf("Not safe to call functions on thread 0x%" PRIx64,
thread.GetID());
@@ -351,6 +347,7 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo(Thread &thread,
options.SetStopOthers(true);
options.SetTimeout(std::chrono::milliseconds(500));
options.SetTryAllThreads(false);
+ options.SetIsForUtilityExpr(true);
thread.CalculateExecutionContext(exe_ctx);
if (!m_get_thread_item_info_impl_code) {
diff --git a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
index 62730809e0d1..47e196102362 100644
--- a/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
+++ b/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
@@ -11,14 +11,10 @@
#ifndef lldb_AppleGetThreadItemInfoHandler_h_
#define lldb_AppleGetThreadItemInfoHandler_h_
-// C Includes
-// C++ Includes
#include <map>
#include <mutex>
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Utility/Status.h"
#include "lldb/lldb-public.h"
diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
index 4748d5e8622e..e61f04e489e8 100644
--- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
@@ -59,6 +59,7 @@ SystemRuntime *SystemRuntimeMacOSX::CreateInstance(Process *process) {
case llvm::Triple::IOS:
case llvm::Triple::TvOS:
case llvm::Triple::WatchOS:
+ // NEED_BRIDGEOS_TRIPLE case llvm::Triple::BridgeOS:
create = triple_ref.getVendor() == llvm::Triple::Apple;
break;
default:
@@ -276,7 +277,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {
// libdispatch symbols were in libSystem.B.dylib up through Mac OS X 10.6
// ("Snow Leopard")
- ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib", false));
+ ModuleSpec libSystem_module_spec(FileSpec("libSystem.B.dylib"));
ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
libSystem_module_spec));
if (module_sp)
@@ -286,7 +287,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchOffsetsAddress() {
// libdispatch symbols are in their own dylib as of Mac OS X 10.7 ("Lion")
// and later
if (dispatch_queue_offsets_symbol == NULL) {
- ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib", false));
+ ModuleSpec libdispatch_module_spec(FileSpec("libdispatch.dylib"));
module_sp = m_process->GetTarget().GetImages().FindFirstModule(
libdispatch_module_spec);
if (module_sp)
@@ -330,7 +331,7 @@ void SystemRuntimeMacOSX::ReadLibpthreadOffsetsAddress() {
"pthread_layout_offsets");
const Symbol *libpthread_layout_offsets_symbol = NULL;
- ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib", false));
+ ModuleSpec libpthread_module_spec(FileSpec("libsystem_pthread.dylib"));
ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
libpthread_module_spec));
if (module_sp) {
@@ -378,7 +379,7 @@ void SystemRuntimeMacOSX::ReadLibdispatchTSDIndexesAddress() {
"dispatch_tsd_indexes");
const Symbol *libdispatch_tsd_indexes_symbol = NULL;
- ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib", false));
+ ModuleSpec libpthread_module_spec(FileSpec("libdispatch.dylib"));
ModuleSP module_sp(m_process->GetTarget().GetImages().FindFirstModule(
libpthread_module_spec));
if (module_sp) {
diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
index 2dc5740da9b6..5fa78cee4640 100644
--- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
+++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
@@ -10,14 +10,11 @@
#ifndef liblldb_SystemRuntimeMacOSX_h_
#define liblldb_SystemRuntimeMacOSX_h_
-// C Includes
-// C++ Includes
#include <mutex>
#include <string>
#include <vector>
// Other libraries and framework include
-// Project includes
#include "lldb/Core/ModuleList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/QueueItem.h"
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
index 54e182b30b6f..b70c2c44d3e6 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -606,7 +606,7 @@ bool UnwindAssemblyInstEmulation::WriteRegister(
assert(
(generic_regnum == LLDB_REGNUM_GENERIC_PC ||
generic_regnum == LLDB_REGNUM_GENERIC_FLAGS) &&
- "eInfoTypeISA used for poping a register other the the PC/FLAGS");
+ "eInfoTypeISA used for popping a register other the PC/FLAGS");
if (generic_regnum != LLDB_REGNUM_GENERIC_FLAGS) {
m_curr_row->SetRegisterLocationToSame(reg_num,
false /*must_replace*/);
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
index e587c93b427c..5539b5217e9e 100644
--- a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -10,14 +10,10 @@
#ifndef liblldb_UnwindAssemblyInstEmulation_h_
#define liblldb_UnwindAssemblyInstEmulation_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/EmulateInstruction.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/UnwindAssembly.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/lldb-private.h"
class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly {
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 327d0b0e4f71..04f9cbbf03ae 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -92,7 +92,7 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
// assembly parsing instead.
if (first_row->GetCFAValue().GetValueType() !=
- UnwindPlan::Row::CFAValue::isRegisterPlusOffset ||
+ UnwindPlan::Row::FAValue::isRegisterPlusOffset ||
RegisterNumber(thread, unwind_plan.GetRegisterKind(),
first_row->GetCFAValue().GetRegisterNumber()) !=
sp_regnum ||
@@ -100,10 +100,10 @@ bool UnwindAssembly_x86::AugmentUnwindPlanFromCallSite(
return false;
}
UnwindPlan::Row::RegisterLocation first_row_pc_loc;
- if (first_row->GetRegisterInfo(
+ if (!first_row->GetRegisterInfo(
pc_regnum.GetAsKind(unwind_plan.GetRegisterKind()),
- first_row_pc_loc) == false ||
- first_row_pc_loc.IsAtCFAPlusOffset() == false ||
+ first_row_pc_loc) ||
+ !first_row_pc_loc.IsAtCFAPlusOffset() ||
first_row_pc_loc.GetOffset() != -wordsize) {
return false;
}
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
index 2beaa4a6510a..c4052a8489da 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
@@ -10,12 +10,8 @@
#ifndef liblldb_UnwindAssembly_x86_h_
#define liblldb_UnwindAssembly_x86_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "x86AssemblyInspectionEngine.h"
-// Project includes
#include "lldb/Target/UnwindAssembly.h"
#include "lldb/lldb-private.h"
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
index 10a56980594f..f8e70204e509 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp
@@ -59,6 +59,7 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
m_machine_ip_regnum = k_machine_eip;
m_machine_sp_regnum = k_machine_esp;
m_machine_fp_regnum = k_machine_ebp;
+ m_machine_alt_fp_regnum = k_machine_ebx;
m_wordsize = 4;
struct lldb_reg_info reginfo;
@@ -84,6 +85,7 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
m_machine_ip_regnum = k_machine_rip;
m_machine_sp_regnum = k_machine_rsp;
m_machine_fp_regnum = k_machine_rbp;
+ m_machine_alt_fp_regnum = k_machine_rbx;
m_wordsize = 8;
struct lldb_reg_info reginfo;
@@ -135,6 +137,8 @@ void x86AssemblyInspectionEngine::Initialize(RegisterContextSP &reg_ctx) {
m_lldb_sp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
m_lldb_fp_regnum = lldb_regno;
+ if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
+ m_lldb_alt_fp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
m_lldb_ip_regnum = lldb_regno;
@@ -160,6 +164,7 @@ void x86AssemblyInspectionEngine::Initialize(
m_machine_ip_regnum = k_machine_eip;
m_machine_sp_regnum = k_machine_esp;
m_machine_fp_regnum = k_machine_ebp;
+ m_machine_alt_fp_regnum = k_machine_ebx;
m_wordsize = 4;
struct lldb_reg_info reginfo;
@@ -185,6 +190,7 @@ void x86AssemblyInspectionEngine::Initialize(
m_machine_ip_regnum = k_machine_rip;
m_machine_sp_regnum = k_machine_rsp;
m_machine_fp_regnum = k_machine_rbp;
+ m_machine_alt_fp_regnum = k_machine_rbx;
m_wordsize = 8;
struct lldb_reg_info reginfo;
@@ -239,6 +245,8 @@ void x86AssemblyInspectionEngine::Initialize(
m_lldb_sp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_fp_regnum, lldb_regno))
m_lldb_fp_regnum = lldb_regno;
+ if (machine_regno_to_lldb_regno(m_machine_alt_fp_regnum, lldb_regno))
+ m_lldb_alt_fp_regnum = lldb_regno;
if (machine_regno_to_lldb_regno(m_machine_ip_regnum, lldb_regno))
m_lldb_ip_regnum = lldb_regno;
@@ -296,26 +304,20 @@ bool x86AssemblyInspectionEngine::nonvolatile_reg_p(int machine_regno) {
// pushq %rbp [0x55]
bool x86AssemblyInspectionEngine::push_rbp_pattern_p() {
uint8_t *p = m_cur_insn;
- if (*p == 0x55)
- return true;
- return false;
+ return *p == 0x55;
}
// pushq $0 ; the first instruction in start() [0x6a 0x00]
bool x86AssemblyInspectionEngine::push_0_pattern_p() {
uint8_t *p = m_cur_insn;
- if (*p == 0x6a && *(p + 1) == 0x0)
- return true;
- return false;
+ return *p == 0x6a && *(p + 1) == 0x0;
}
// pushq $0
// pushl $0
bool x86AssemblyInspectionEngine::push_imm_pattern_p() {
uint8_t *p = m_cur_insn;
- if (*p == 0x68 || *p == 0x6a)
- return true;
- return false;
+ return *p == 0x68 || *p == 0x6a;
}
// pushl imm8(%esp)
@@ -387,6 +389,45 @@ bool x86AssemblyInspectionEngine::mov_rsp_rbp_pattern_p() {
return false;
}
+// movq %rsp, %rbx [0x48 0x8b 0xdc] or [0x48 0x89 0xe3]
+// movl %esp, %ebx [0x8b 0xdc] or [0x89 0xe3]
+bool x86AssemblyInspectionEngine::mov_rsp_rbx_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ if (*(p) == 0x8b && *(p + 1) == 0xdc)
+ return true;
+ if (*(p) == 0x89 && *(p + 1) == 0xe3)
+ return true;
+ return false;
+}
+
+// movq %rbp, %rsp [0x48 0x8b 0xe5] or [0x48 0x89 0xec]
+// movl %ebp, %esp [0x8b 0xe5] or [0x89 0xec]
+bool x86AssemblyInspectionEngine::mov_rbp_rsp_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ if (*(p) == 0x8b && *(p + 1) == 0xe5)
+ return true;
+ if (*(p) == 0x89 && *(p + 1) == 0xec)
+ return true;
+ return false;
+}
+
+// movq %rbx, %rsp [0x48 0x8b 0xe3] or [0x48 0x89 0xdc]
+// movl %ebx, %esp [0x8b 0xe3] or [0x89 0xdc]
+bool x86AssemblyInspectionEngine::mov_rbx_rsp_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+ if (*(p) == 0x8b && *(p + 1) == 0xe3)
+ return true;
+ if (*(p) == 0x89 && *(p + 1) == 0xdc)
+ return true;
+ return false;
+}
+
// subq $0x20, %rsp
bool x86AssemblyInspectionEngine::sub_rsp_pattern_p(int &amount) {
uint8_t *p = m_cur_insn;
@@ -476,6 +517,46 @@ bool x86AssemblyInspectionEngine::lea_rbp_rsp_pattern_p(int &amount) {
return false;
}
+// lea -0x28(%ebx), %esp
+// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
+bool x86AssemblyInspectionEngine::lea_rbx_rsp_pattern_p(int &amount) {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+
+ // Check opcode
+ if (*p != 0x8d)
+ return false;
+ ++p;
+
+ // 8 bit displacement
+ if (*p == 0x63) {
+ amount = (int8_t)p[1];
+ return true;
+ }
+
+ // 32 bit displacement
+ if (*p == 0xa3) {
+ amount = (int32_t)extract_4(p + 1);
+ return true;
+ }
+
+ return false;
+}
+
+// and -0xfffffff0, %esp
+// (32-bit and 64-bit variants, 8-bit and 32-bit displacement)
+bool x86AssemblyInspectionEngine::and_rsp_pattern_p() {
+ uint8_t *p = m_cur_insn;
+ if (m_wordsize == 8 && *p == 0x48)
+ p++;
+
+ if (*p != 0x81 && *p != 0x83)
+ return false;
+
+ return *++p == 0xe4;
+}
+
// popq %rbx
// popl %ebx
bool x86AssemblyInspectionEngine::pop_reg_p(int &regno) {
@@ -588,9 +669,7 @@ bool x86AssemblyInspectionEngine::mov_reg_to_local_stack_frame_p(
// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
bool x86AssemblyInspectionEngine::ret_pattern_p() {
uint8_t *p = m_cur_insn;
- if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
- return true;
- return false;
+ return *p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3;
}
uint32_t x86AssemblyInspectionEngine::extract_4(uint8_t *b) {
@@ -636,11 +715,12 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
if (data == nullptr || size == 0)
return false;
- if (m_register_map_initialized == false)
+ if (!m_register_map_initialized)
return false;
addr_t current_func_text_offset = 0;
- int current_sp_bytes_offset_from_cfa = 0;
+ int current_sp_bytes_offset_from_fa = 0;
+ bool is_aligned = false;
UnwindPlan::Row::RegisterLocation initial_regloc;
UnwindPlan::RowSP row(new UnwindPlan::Row);
@@ -657,8 +737,8 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
row->SetRegisterInfo(m_lldb_sp_regnum, initial_regloc);
// saved instruction pointer can be found at CFA - wordsize.
- current_sp_bytes_offset_from_cfa = m_wordsize;
- initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa = m_wordsize;
+ initial_regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
row->SetRegisterInfo(m_lldb_ip_regnum, initial_regloc);
unwind_plan.AppendRow(row);
@@ -682,6 +762,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI
int prologue_completed_sp_bytes_offset_from_cfa; // The sp value before the
// epilogue started executed
+ bool prologue_completed_is_aligned;
std::vector<bool> prologue_completed_saved_registers;
while (current_func_text_offset < size) {
@@ -701,22 +782,59 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
break;
}
- if (push_rbp_pattern_p()) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
- UnwindPlan::Row::RegisterLocation regloc;
- regloc.SetAtCFAPlusOffset(-row->GetCFAValue().GetOffset());
- row->SetRegisterInfo(m_lldb_fp_regnum, regloc);
- saved_registers[m_machine_fp_regnum] = true;
- row_updated = true;
+ auto &cfa_value = row->GetCFAValue();
+ auto &afa_value = row->GetAFAValue();
+ auto fa_value_ptr = is_aligned ? &afa_value : &cfa_value;
+
+ if (mov_rsp_rbp_pattern_p()) {
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_fp_regnum, fa_value_ptr->GetOffset());
+ row_updated = true;
+ }
+ }
+
+ else if (mov_rsp_rbx_pattern_p()) {
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_alt_fp_regnum, fa_value_ptr->GetOffset());
+ row_updated = true;
+ }
}
- else if (mov_rsp_rbp_pattern_p()) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_fp_regnum, row->GetCFAValue().GetOffset());
+ else if (and_rsp_pattern_p()) {
+ current_sp_bytes_offset_from_fa = 0;
+ afa_value.SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
+ fa_value_ptr = &afa_value;
+ is_aligned = true;
row_updated = true;
}
+ else if (mov_rbp_rsp_pattern_p()) {
+ if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
+ {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+ }
+
+ else if (mov_rbx_rsp_pattern_p()) {
+ if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum)
+ {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum)
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+ }
+
// This is the start() function (or a pthread equivalent), it starts with a
// pushl $0x0 which puts the saved pc value of 0 on the stack. In this
// case we want to pretend we didn't see a stack movement at all --
@@ -726,21 +844,24 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (push_reg_p(machine_regno)) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- // the PUSH instruction has moved the stack pointer - if the CFA is set
+ current_sp_bytes_offset_from_fa += m_wordsize;
+ // the PUSH instruction has moved the stack pointer - if the FA is set
// in terms of the stack pointer, we need to add a new row of
// instructions.
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
// record where non-volatile (callee-saved, spilled) registers are saved
// on the stack
if (nonvolatile_reg_p(machine_regno) &&
machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
- saved_registers[machine_regno] == false) {
+ !saved_registers[machine_regno]) {
UnwindPlan::Row::RegisterLocation regloc;
- regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_cfa);
+ if (is_aligned)
+ regloc.SetAtAFAPlusOffset(-current_sp_bytes_offset_from_fa);
+ else
+ regloc.SetAtCFAPlusOffset(-current_sp_bytes_offset_from_fa);
row->SetRegisterInfo(lldb_regno, regloc);
saved_registers[machine_regno] = true;
row_updated = true;
@@ -748,37 +869,37 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (pop_reg_p(machine_regno)) {
- current_sp_bytes_offset_from_cfa -= m_wordsize;
+ current_sp_bytes_offset_from_fa -= m_wordsize;
if (nonvolatile_reg_p(machine_regno) &&
machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
- saved_registers[machine_regno] == true) {
+ saved_registers[machine_regno]) {
saved_registers[machine_regno] = false;
row->RemoveRegisterInfo(lldb_regno);
- if (machine_regno == (int)m_machine_fp_regnum) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
+ if (lldb_regno == fa_value_ptr->GetRegisterNumber()) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, fa_value_ptr->GetOffset());
}
in_epilogue = true;
row_updated = true;
}
- // the POP instruction has moved the stack pointer - if the CFA is set in
+ // the POP instruction has moved the stack pointer - if the FA is set in
// terms of the stack pointer, we need to add a new row of instructions.
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
else if (pop_misc_reg_p()) {
- current_sp_bytes_offset_from_cfa -= m_wordsize;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa -= m_wordsize;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
@@ -787,41 +908,57 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
// off the stack into rbp (restoring the caller's rbp value). It is the
// opposite of ENTER, or 'push rbp, mov rsp rbp'.
else if (leave_pattern_p()) {
- // We're going to copy the value in rbp into rsp, so re-set the sp offset
- // based on the CFAValue. Also, adjust it to recognize that we're
- // popping the saved rbp value off the stack.
- current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
- current_sp_bytes_offset_from_cfa -= m_wordsize;
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
-
- // rbp is restored to the caller's value
- saved_registers[m_machine_fp_regnum] = false;
- row->RemoveRegisterInfo(m_lldb_fp_regnum);
-
- // cfa is now in terms of rsp again.
- row->GetCFAValue().SetIsRegisterPlusOffset(
- m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ if (saved_registers[m_machine_fp_regnum]) {
+ saved_registers[m_machine_fp_regnum] = false;
+ row->RemoveRegisterInfo(m_lldb_fp_regnum);
+
+ row_updated = true;
+ }
+
+ if (is_aligned && cfa_value.GetRegisterNumber() == m_lldb_fp_regnum)
+ {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum)
+ {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, fa_value_ptr->GetOffset());
+
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset();
+ }
+
+ current_sp_bytes_offset_from_fa -= m_wordsize;
+
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetIsRegisterPlusOffset(
+ m_lldb_sp_regnum, current_sp_bytes_offset_from_fa);
+ row_updated = true;
+ }
in_epilogue = true;
- row_updated = true;
}
else if (mov_reg_to_local_stack_frame_p(machine_regno, stack_offset) &&
nonvolatile_reg_p(machine_regno) &&
machine_regno_to_lldb_regno(machine_regno, lldb_regno) &&
- saved_registers[machine_regno] == false) {
+ !saved_registers[machine_regno]) {
saved_registers[machine_regno] = true;
UnwindPlan::Row::RegisterLocation regloc;
// stack_offset for 'movq %r15, -80(%rbp)' will be 80. In the Row, we
- // want to express this as the offset from the CFA. If the frame base is
- // rbp (like the above instruction), the CFA offset for rbp is probably
- // 16. So we want to say that the value is stored at the CFA address -
+ // want to express this as the offset from the FA. If the frame base is
+ // rbp (like the above instruction), the FA offset for rbp is probably
+ // 16. So we want to say that the value is stored at the FA address -
// 96.
- regloc.SetAtCFAPlusOffset(
- -(stack_offset + row->GetCFAValue().GetOffset()));
+ if (is_aligned)
+ regloc.SetAtAFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
+ else
+ regloc.SetAtCFAPlusOffset(-(stack_offset + fa_value_ptr->GetOffset()));
row->SetRegisterInfo(lldb_regno, regloc);
@@ -829,17 +966,17 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
else if (sub_rsp_pattern_p(stack_offset)) {
- current_sp_bytes_offset_from_cfa += stack_offset;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa += stack_offset;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
else if (add_rsp_pattern_p(stack_offset)) {
- current_sp_bytes_offset_from_cfa -= stack_offset;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa -= stack_offset;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
in_epilogue = true;
@@ -847,27 +984,48 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
else if (push_extended_pattern_p() || push_imm_pattern_p() ||
push_misc_reg_p()) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa += m_wordsize;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
else if (lea_rsp_pattern_p(stack_offset)) {
- current_sp_bytes_offset_from_cfa -= stack_offset;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa -= stack_offset;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
if (stack_offset > 0)
in_epilogue = true;
}
- else if (lea_rbp_rsp_pattern_p(stack_offset) &&
- row->GetCFAValue().GetRegisterNumber() == m_lldb_fp_regnum) {
- current_sp_bytes_offset_from_cfa =
- row->GetCFAValue().GetOffset() - stack_offset;
+ else if (lea_rbp_rsp_pattern_p(stack_offset)) {
+ if (is_aligned &&
+ cfa_value.GetRegisterNumber() == m_lldb_fp_regnum) {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_fp_regnum) {
+ current_sp_bytes_offset_from_fa =
+ fa_value_ptr->GetOffset() - stack_offset;
+ }
+ }
+
+ else if (lea_rbx_rsp_pattern_p(stack_offset)) {
+ if (is_aligned &&
+ cfa_value.GetRegisterNumber() == m_lldb_alt_fp_regnum) {
+ is_aligned = false;
+ fa_value_ptr = &cfa_value;
+ afa_value.SetUnspecified();
+ row_updated = true;
+ }
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_alt_fp_regnum) {
+ current_sp_bytes_offset_from_fa = fa_value_ptr->GetOffset() - stack_offset;
+ }
}
else if (ret_pattern_p() && prologue_completed_row.get()) {
@@ -877,8 +1035,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *prologue_completed_row.get();
row.reset(newrow);
- current_sp_bytes_offset_from_cfa =
+ current_sp_bytes_offset_from_fa =
prologue_completed_sp_bytes_offset_from_cfa;
+ is_aligned = prologue_completed_is_aligned;
saved_registers.clear();
saved_registers.resize(prologue_completed_saved_registers.size(), false);
@@ -896,9 +1055,9 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
// This is used in i386 programs to get the PIC base address for finding
// global data
else if (call_next_insn_pattern_p()) {
- current_sp_bytes_offset_from_cfa += m_wordsize;
- if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum) {
- row->GetCFAValue().SetOffset(current_sp_bytes_offset_from_cfa);
+ current_sp_bytes_offset_from_fa += m_wordsize;
+ if (fa_value_ptr->GetRegisterNumber() == m_lldb_sp_regnum) {
+ fa_value_ptr->SetOffset(current_sp_bytes_offset_from_fa);
row_updated = true;
}
}
@@ -914,7 +1073,7 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
}
}
- if (in_epilogue == false && row_updated) {
+ if (!in_epilogue && row_updated) {
// If we're not in an epilogue sequence, save the updated Row
UnwindPlan::Row *newrow = new UnwindPlan::Row;
*newrow = *row.get();
@@ -929,9 +1088,10 @@ bool x86AssemblyInspectionEngine::GetNonCallSiteUnwindPlanFromAssembly(
// We may change the sp value without adding a new Row necessarily -- keep
// track of it either way.
- if (in_epilogue == false) {
+ if (!in_epilogue) {
prologue_completed_sp_bytes_offset_from_cfa =
- current_sp_bytes_offset_from_cfa;
+ current_sp_bytes_offset_from_fa;
+ prologue_completed_is_aligned = is_aligned;
}
m_cur_insn = m_cur_insn + insn_len;
@@ -1194,7 +1354,7 @@ bool x86AssemblyInspectionEngine::FindFirstNonPrologueInstruction(
uint8_t *data, size_t size, size_t &offset) {
offset = 0;
- if (m_register_map_initialized == false)
+ if (!m_register_map_initialized)
return false;
while (offset < size) {
diff --git a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
index cec9803c8a49..e02b510ba1f9 100644
--- a/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
+++ b/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.h
@@ -98,10 +98,15 @@ private:
bool push_extended_pattern_p();
bool push_misc_reg_p();
bool mov_rsp_rbp_pattern_p();
+ bool mov_rsp_rbx_pattern_p();
+ bool mov_rbp_rsp_pattern_p();
+ bool mov_rbx_rsp_pattern_p();
bool sub_rsp_pattern_p(int &amount);
bool add_rsp_pattern_p(int &amount);
bool lea_rsp_pattern_p(int &amount);
bool lea_rbp_rsp_pattern_p(int &amount);
+ bool lea_rbx_rsp_pattern_p(int &amount);
+ bool and_rsp_pattern_p();
bool push_reg_p(int &regno);
bool pop_reg_p(int &regno);
bool pop_rbp_pattern_p();
@@ -157,9 +162,11 @@ private:
uint32_t m_machine_ip_regnum;
uint32_t m_machine_sp_regnum;
uint32_t m_machine_fp_regnum;
+ uint32_t m_machine_alt_fp_regnum;
uint32_t m_lldb_ip_regnum;
uint32_t m_lldb_sp_regnum;
uint32_t m_lldb_fp_regnum;
+ uint32_t m_lldb_alt_fp_regnum;
typedef std::map<uint32_t, lldb_reg_info> MachineRegnumToNameAndLLDBRegnum;
diff --git a/source/Symbol/ArmUnwindInfo.cpp b/source/Symbol/ArmUnwindInfo.cpp
index 6dcad62f2f9d..08f28073be21 100644
--- a/source/Symbol/ArmUnwindInfo.cpp
+++ b/source/Symbol/ArmUnwindInfo.cpp
@@ -66,7 +66,7 @@ ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx,
// Sort the entries in the exidx section. The entries should be sorted inside
// the section but some old compiler isn't sorted them.
- std::sort(m_exidx_entries.begin(), m_exidx_entries.end());
+ llvm::sort(m_exidx_entries.begin(), m_exidx_entries.end());
}
ArmUnwindInfo::~ArmUnwindInfo() {}
diff --git a/source/Symbol/Block.cpp b/source/Symbol/Block.cpp
index 46f875fca776..d0342355911c 100644
--- a/source/Symbol/Block.cpp
+++ b/source/Symbol/Block.cpp
@@ -83,7 +83,7 @@ void Block::Dump(Stream *s, addr_t base_addr, int32_t depth,
size_t num_ranges = m_ranges.GetSize();
for (size_t i = 0; i < num_ranges; ++i) {
const Range &range = m_ranges.GetEntryRef(i);
- if (parent_block != nullptr && parent_block->Contains(range) == false)
+ if (parent_block != nullptr && !parent_block->Contains(range))
*s << '!';
else
*s << ' ';
@@ -369,7 +369,7 @@ void Block::SetInlinedFunctionInfo(const char *name, const char *mangled,
}
VariableListSP Block::GetBlockVariableList(bool can_create) {
- if (m_parsed_block_variables == false) {
+ if (!m_parsed_block_variables) {
if (m_variable_list_sp.get() == nullptr && can_create) {
m_parsed_block_variables = true;
SymbolContext sc;
@@ -402,7 +402,7 @@ Block::AppendBlockVariables(bool can_create, bool get_child_block_variables,
collection::const_iterator pos, end = m_children.end();
for (pos = m_children.begin(); pos != end; ++pos) {
Block *child_block = pos->get();
- if (stop_if_child_block_is_inlined_function == false ||
+ if (!stop_if_child_block_is_inlined_function ||
child_block->GetInlinedFunctionInfo() == nullptr) {
num_variables_added += child_block->AppendBlockVariables(
can_create, get_child_block_variables,
@@ -444,19 +444,16 @@ uint32_t Block::AppendVariables(bool can_create, bool get_parent_variables,
return num_variables_added;
}
-CompilerDeclContext Block::GetDeclContext() {
- ModuleSP module_sp = CalculateSymbolContextModule();
-
- if (module_sp) {
- SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
-
- if (sym_vendor) {
- SymbolFile *sym_file = sym_vendor->GetSymbolFile();
+SymbolFile *Block::GetSymbolFile() {
+ if (ModuleSP module_sp = CalculateSymbolContextModule())
+ if (SymbolVendor *sym_vendor = module_sp->GetSymbolVendor())
+ return sym_vendor->GetSymbolFile();
+ return nullptr;
+}
- if (sym_file)
- return sym_file->GetDeclContextForUID(GetID());
- }
- }
+CompilerDeclContext Block::GetDeclContext() {
+ if (SymbolFile *sym_file = GetSymbolFile())
+ return sym_file->GetDeclContextForUID(GetID());
return CompilerDeclContext();
}
diff --git a/source/Symbol/CMakeLists.txt b/source/Symbol/CMakeLists.txt
index 6f8a8cb9f9f2..56562d322485 100644
--- a/source/Symbol/CMakeLists.txt
+++ b/source/Symbol/CMakeLists.txt
@@ -16,12 +16,9 @@ add_lldb_library(lldbSymbol
DWARFCallFrameInfo.cpp
Function.cpp
FuncUnwinders.cpp
- GoASTContext.cpp
- JavaASTContext.cpp
LineEntry.cpp
LineTable.cpp
ObjectFile.cpp
- OCamlASTContext.cpp
Symbol.cpp
SymbolContext.cpp
SymbolFile.cpp
@@ -29,7 +26,7 @@ add_lldb_library(lldbSymbol
Symtab.cpp
Type.cpp
TypeList.cpp
- TypeMap.cpp
+ TypeMap.cpp
TypeSystem.cpp
UnwindPlan.cpp
UnwindTable.cpp
@@ -47,7 +44,6 @@ add_lldb_library(lldbSymbol
lldbTarget
lldbUtility
lldbPluginExpressionParserClang
- lldbPluginExpressionParserGo
lldbPluginSymbolFileDWARF
lldbPluginSymbolFilePDB
lldbPluginCPlusPlusLanguage
diff --git a/source/Symbol/ClangASTContext.cpp b/source/Symbol/ClangASTContext.cpp
index 95e7f8a68d44..85436b630b7d 100644
--- a/source/Symbol/ClangASTContext.cpp
+++ b/source/Symbol/ClangASTContext.cpp
@@ -12,13 +12,10 @@
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/FormatVariadic.h"
-// C Includes
-// C++ Includes
#include <mutex>
#include <string>
#include <vector>
-// Other libraries and framework includes
// Clang headers like to use NDEBUG inside of them to enable/disable debug
// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
@@ -76,7 +73,6 @@
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/ThreadSafeDenseMap.h"
#include "lldb/Core/UniqueCStringMap.h"
@@ -97,6 +93,7 @@
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/Scalar.h"
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
#include "Plugins/SymbolFile/PDB/PDBASTParser.h"
@@ -122,8 +119,204 @@ ClangASTContextSupportsLanguage(lldb::LanguageType language) {
language == eLanguageTypeRust ||
language == eLanguageTypeExtRenderScript ||
// Use Clang for D until there is a proper language plugin for it
- language == eLanguageTypeD;
-}
+ language == eLanguageTypeD ||
+ // Open Dylan compiler debug info is designed to be Clang-compatible
+ language == eLanguageTypeDylan;
+}
+
+// Checks whether m1 is an overload of m2 (as opposed to an override). This is
+// called by addOverridesForMethod to distinguish overrides (which share a
+// vtable entry) from overloads (which require distinct entries).
+bool isOverload(clang::CXXMethodDecl *m1, clang::CXXMethodDecl *m2) {
+ // FIXME: This should detect covariant return types, but currently doesn't.
+ lldbassert(&m1->getASTContext() == &m2->getASTContext() &&
+ "Methods should have the same AST context");
+ clang::ASTContext &context = m1->getASTContext();
+
+ const auto *m1Type = llvm::cast<clang::FunctionProtoType>(
+ context.getCanonicalType(m1->getType()));
+
+ const auto *m2Type = llvm::cast<clang::FunctionProtoType>(
+ context.getCanonicalType(m2->getType()));
+
+ auto compareArgTypes = [&context](const clang::QualType &m1p,
+ const clang::QualType &m2p) {
+ return context.hasSameType(m1p.getUnqualifiedType(),
+ m2p.getUnqualifiedType());
+ };
+
+ // FIXME: In C++14 and later, we can just pass m2Type->param_type_end()
+ // as a fourth parameter to std::equal().
+ return (m1->getNumParams() != m2->getNumParams()) ||
+ !std::equal(m1Type->param_type_begin(), m1Type->param_type_end(),
+ m2Type->param_type_begin(), compareArgTypes);
+}
+
+// If decl is a virtual method, walk the base classes looking for methods that
+// decl overrides. This table of overridden methods is used by IRGen to
+// determine the vtable layout for decl's parent class.
+void addOverridesForMethod(clang::CXXMethodDecl *decl) {
+ if (!decl->isVirtual())
+ return;
+
+ clang::CXXBasePaths paths;
+
+ auto find_overridden_methods =
+ [decl](const clang::CXXBaseSpecifier *specifier,
+ clang::CXXBasePath &path) {
+ if (auto *base_record = llvm::dyn_cast<clang::CXXRecordDecl>(
+ specifier->getType()->getAs<clang::RecordType>()->getDecl())) {
+
+ clang::DeclarationName name = decl->getDeclName();
+
+ // If this is a destructor, check whether the base class destructor is
+ // virtual.
+ if (name.getNameKind() == clang::DeclarationName::CXXDestructorName)
+ if (auto *baseDtorDecl = base_record->getDestructor()) {
+ if (baseDtorDecl->isVirtual()) {
+ path.Decls = baseDtorDecl;
+ return true;
+ } else
+ return false;
+ }
+
+ // Otherwise, search for name in the base class.
+ for (path.Decls = base_record->lookup(name); !path.Decls.empty();
+ path.Decls = path.Decls.slice(1)) {
+ if (auto *method_decl =
+ llvm::dyn_cast<clang::CXXMethodDecl>(path.Decls.front()))
+ if (method_decl->isVirtual() && !isOverload(decl, method_decl)) {
+ path.Decls = method_decl;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ };
+
+ if (decl->getParent()->lookupInBases(find_overridden_methods, paths)) {
+ for (auto *overridden_decl : paths.found_decls())
+ decl->addOverriddenMethod(
+ llvm::cast<clang::CXXMethodDecl>(overridden_decl));
+ }
+}
+}
+
+static lldb::addr_t GetVTableAddress(Process &process,
+ VTableContextBase &vtable_ctx,
+ ValueObject &valobj,
+ const ASTRecordLayout &record_layout) {
+ // Retrieve type info
+ CompilerType pointee_type;
+ CompilerType this_type(valobj.GetCompilerType());
+ uint32_t type_info = this_type.GetTypeInfo(&pointee_type);
+ if (!type_info)
+ return LLDB_INVALID_ADDRESS;
+
+ // Check if it's a pointer or reference
+ bool ptr_or_ref = false;
+ if (type_info & (eTypeIsPointer | eTypeIsReference)) {
+ ptr_or_ref = true;
+ type_info = pointee_type.GetTypeInfo();
+ }
+
+ // We process only C++ classes
+ const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus;
+ if ((type_info & cpp_class) != cpp_class)
+ return LLDB_INVALID_ADDRESS;
+
+ // Calculate offset to VTable pointer
+ lldb::offset_t vbtable_ptr_offset =
+ vtable_ctx.isMicrosoft() ? record_layout.getVBPtrOffset().getQuantity()
+ : 0;
+
+ if (ptr_or_ref) {
+ // We have a pointer / ref to object, so read
+ // VTable pointer from process memory
+
+ if (valobj.GetAddressTypeOfChildren() != eAddressTypeLoad)
+ return LLDB_INVALID_ADDRESS;
+
+ auto vbtable_ptr_addr = valobj.GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+ if (vbtable_ptr_addr == LLDB_INVALID_ADDRESS)
+ return LLDB_INVALID_ADDRESS;
+
+ vbtable_ptr_addr += vbtable_ptr_offset;
+
+ Status err;
+ return process.ReadPointerFromMemory(vbtable_ptr_addr, err);
+ }
+
+ // We have an object already read from process memory,
+ // so just extract VTable pointer from it
+
+ DataExtractor data;
+ Status err;
+ auto size = valobj.GetData(data, err);
+ if (err.Fail() || vbtable_ptr_offset + data.GetAddressByteSize() > size)
+ return LLDB_INVALID_ADDRESS;
+
+ return data.GetPointer(&vbtable_ptr_offset);
+}
+
+static int64_t ReadVBaseOffsetFromVTable(Process &process,
+ VTableContextBase &vtable_ctx,
+ lldb::addr_t vtable_ptr,
+ const CXXRecordDecl *cxx_record_decl,
+ const CXXRecordDecl *base_class_decl) {
+ if (vtable_ctx.isMicrosoft()) {
+ clang::MicrosoftVTableContext &msoft_vtable_ctx =
+ static_cast<clang::MicrosoftVTableContext &>(vtable_ctx);
+
+ // Get the index into the virtual base table. The
+ // index is the index in uint32_t from vbtable_ptr
+ const unsigned vbtable_index =
+ msoft_vtable_ctx.getVBTableIndex(cxx_record_decl, base_class_decl);
+ const lldb::addr_t base_offset_addr = vtable_ptr + vbtable_index * 4;
+ Status err;
+ return process.ReadSignedIntegerFromMemory(base_offset_addr, 4, INT64_MAX,
+ err);
+ }
+
+ clang::ItaniumVTableContext &itanium_vtable_ctx =
+ static_cast<clang::ItaniumVTableContext &>(vtable_ctx);
+
+ clang::CharUnits base_offset_offset =
+ itanium_vtable_ctx.getVirtualBaseOffsetOffset(cxx_record_decl,
+ base_class_decl);
+ const lldb::addr_t base_offset_addr =
+ vtable_ptr + base_offset_offset.getQuantity();
+ const uint32_t base_offset_size = process.GetAddressByteSize();
+ Status err;
+ return process.ReadSignedIntegerFromMemory(base_offset_addr, base_offset_size,
+ INT64_MAX, err);
+}
+
+static bool GetVBaseBitOffset(VTableContextBase &vtable_ctx,
+ ValueObject &valobj,
+ const ASTRecordLayout &record_layout,
+ const CXXRecordDecl *cxx_record_decl,
+ const CXXRecordDecl *base_class_decl,
+ int32_t &bit_offset) {
+ ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+ if (!process)
+ return false;
+
+ lldb::addr_t vtable_ptr =
+ GetVTableAddress(*process, vtable_ctx, valobj, record_layout);
+ if (vtable_ptr == LLDB_INVALID_ADDRESS)
+ return false;
+
+ auto base_offset = ReadVBaseOffsetFromVTable(
+ *process, vtable_ctx, vtable_ptr, cxx_record_decl, base_class_decl);
+ if (base_offset == INT64_MAX)
+ return false;
+
+ bit_offset = base_offset * 8;
+
+ return true;
}
typedef lldb_private::ThreadSafeDenseMap<clang::ASTContext *, ClangASTContext *>
@@ -381,7 +574,7 @@ static void ParseLangArgs(LangOptions &Opts, InputKind IK, const char *triple) {
if (IK.getLanguage() == InputKind::Asm) {
Opts.AsmPreprocessor = 1;
} else if (IK.isObjectiveC()) {
- Opts.ObjC1 = Opts.ObjC2 = 1;
+ Opts.ObjC = 1;
}
LangStandard::Kind LangStd = LangStandard::lang_unspecified;
@@ -628,7 +821,6 @@ void ClangASTContext::SetExternalSource(
if (ast) {
ast->setExternalSource(ast_source_ap);
ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(true);
- // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(true);
}
}
@@ -639,7 +831,6 @@ void ClangASTContext::RemoveExternalSource() {
llvm::IntrusiveRefCntPtr<ExternalASTSource> empty_ast_source_ap;
ast->setExternalSource(empty_ast_source_ap);
ast->getTranslationUnitDecl()->setHasExternalLexicalStorage(false);
- // ast->getTranslationUnitDecl()->setHasExternalVisibleStorage(false);
}
}
@@ -801,9 +992,7 @@ TargetInfo *ClangASTContext::getTargetInfo() {
static inline bool QualTypeMatchesBitSize(const uint64_t bit_size,
ASTContext *ast, QualType qual_type) {
uint64_t qual_type_bit_size = ast->getTypeSize(qual_type);
- if (qual_type_bit_size == bit_size)
- return true;
- return false;
+ return qual_type_bit_size == bit_size;
}
CompilerType
@@ -952,9 +1141,10 @@ CompilerType ClangASTContext::GetBasicType(ASTContext *ast,
uint32_t ClangASTContext::GetPointerByteSize() {
if (m_pointer_byte_size == 0)
- m_pointer_byte_size = GetBasicType(lldb::eBasicTypeVoid)
- .GetPointerType()
- .GetByteSize(nullptr);
+ if (auto size = GetBasicType(lldb::eBasicTypeVoid)
+ .GetPointerType()
+ .GetByteSize(nullptr))
+ m_pointer_byte_size = *size;
return m_pointer_byte_size;
}
@@ -1675,8 +1865,7 @@ CompilerType ClangASTContext::CreateObjCClass(const char *name,
}
static inline bool BaseSpecifierIsEmpty(const CXXBaseSpecifier *b) {
- return ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl()) ==
- false;
+ return !ClangASTContext::RecordHasFields(b->getType()->getAsCXXRecordDecl());
}
uint32_t
@@ -1982,7 +2171,8 @@ FunctionDecl *ClangASTContext::CreateFunctionDeclaration(
CompilerType ClangASTContext::CreateFunctionType(
ASTContext *ast, const CompilerType &result_type, const CompilerType *args,
- unsigned num_args, bool is_variadic, unsigned type_quals) {
+ unsigned num_args, bool is_variadic, unsigned type_quals,
+ clang::CallingConv cc) {
if (ast == nullptr)
return CompilerType(); // invalid AST
@@ -2010,9 +2200,10 @@ CompilerType ClangASTContext::CreateFunctionType(
// TODO: Detect calling convention in DWARF?
FunctionProtoType::ExtProtoInfo proto_info;
+ proto_info.ExtInfo = cc;
proto_info.Variadic = is_variadic;
proto_info.ExceptionSpec = EST_None;
- proto_info.TypeQuals = type_quals;
+ proto_info.TypeQuals = clang::Qualifiers::fromFastMask(type_quals);
proto_info.RefQualifier = RQ_None;
return CompilerType(ast,
@@ -2021,14 +2212,17 @@ CompilerType ClangASTContext::CreateFunctionType(
}
ParmVarDecl *ClangASTContext::CreateParameterDeclaration(
- const char *name, const CompilerType &param_type, int storage) {
+ clang::DeclContext *decl_ctx, const char *name,
+ const CompilerType &param_type, int storage) {
ASTContext *ast = getASTContext();
assert(ast != nullptr);
- return ParmVarDecl::Create(*ast, ast->getTranslationUnitDecl(),
- SourceLocation(), SourceLocation(),
- name && name[0] ? &ast->Idents.get(name) : nullptr,
- ClangUtil::GetQualType(param_type), nullptr,
- (clang::StorageClass)storage, nullptr);
+ auto *decl =
+ ParmVarDecl::Create(*ast, decl_ctx, SourceLocation(), SourceLocation(),
+ name && name[0] ? &ast->Idents.get(name) : nullptr,
+ ClangUtil::GetQualType(param_type), nullptr,
+ (clang::StorageClass)storage, nullptr);
+ decl_ctx->addDecl(decl);
+ return decl;
}
void ClangASTContext::SetFunctionParameters(FunctionDecl *function_decl,
@@ -2136,6 +2330,9 @@ ClangASTContext::CreateEnumerationType(const char *name, DeclContext *decl_ctx,
false); // IsFixed
if (enum_decl) {
+ if (decl_ctx)
+ decl_ctx->addDecl(enum_decl);
+
// TODO: check if we should be setting the promotion type too?
enum_decl->setIntegerType(ClangUtil::GetQualType(integer_clang_type));
@@ -3737,9 +3934,7 @@ bool ClangASTContext::IsCXXClassType(const CompilerType &type) {
return false;
clang::QualType qual_type(ClangUtil::GetCanonicalQualType(type));
- if (!qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr)
- return true;
- return false;
+ return !qual_type.isNull() && qual_type->getAsCXXRecordDecl() != nullptr;
}
bool ClangASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
@@ -4311,7 +4506,8 @@ ClangASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
// TODO: the real stride will be >= this value.. find the real one!
if (stride)
- *stride = element_type.GetByteSize(nullptr);
+ if (Optional<uint64_t> size = element_type.GetByteSize(nullptr))
+ *stride = *size;
return element_type;
}
@@ -4663,6 +4859,8 @@ CompilerType ClangASTContext::CreateTypedefType(
decl->setAccess(clang::AS_public); // TODO respect proper access specifier
+ decl_ctx->addDecl(decl);
+
// Get a uniqued clang::QualType for the typedef decl type
return CompilerType(clang_ast, clang_ast->getTypedefType(decl));
}
@@ -5030,6 +5228,20 @@ lldb::Encoding ClangASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
case clang::BuiltinType::Kind::PseudoObject:
case clang::BuiltinType::Kind::UnknownAny:
break;
+
+ case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
+ break;
}
break;
// All pointer types are represented as unsigned integer encodings. We may
@@ -5317,8 +5529,20 @@ static bool ObjCDeclHasIVars(clang::ObjCInterfaceDecl *class_interface_decl,
return false;
}
+static Optional<SymbolFile::ArrayInfo>
+GetDynamicArrayInfo(ClangASTContext &ast, SymbolFile *sym_file,
+ clang::QualType qual_type,
+ const ExecutionContext *exe_ctx) {
+ if (qual_type->isIncompleteArrayType())
+ if (auto *metadata = ast.GetMetadata(qual_type.getAsOpaquePtr()))
+ return sym_file->GetDynamicArrayInfoForUID(metadata->GetUserID(),
+ exe_ctx);
+ return llvm::None;
+}
+
uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) {
+ bool omit_empty_base_classes,
+ const ExecutionContext *exe_ctx) {
if (!type)
return 0;
@@ -5340,7 +5564,6 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
case clang::Type::Complex:
return 0;
-
case clang::Type::Record:
if (GetCompleteQualType(getASTContext(), qual_type)) {
const clang::RecordType *record_type =
@@ -5366,7 +5589,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
->getDecl());
// Skip empty base classes
- if (ClangASTContext::RecordHasFields(base_class_decl) == false)
+ if (!ClangASTContext::RecordHasFields(base_class_decl))
continue;
num_children++;
@@ -5418,7 +5641,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
clang::QualType pointee_type = pointer_type->getPointeeType();
uint32_t num_pointee_children =
CompilerType(getASTContext(), pointee_type)
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
// If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
num_children = 1;
@@ -5437,6 +5660,14 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
->getSize()
.getLimitedValue();
break;
+ case clang::Type::IncompleteArray:
+ if (auto array_info =
+ GetDynamicArrayInfo(*this, GetSymbolFile(), qual_type, exe_ctx))
+ // Only 1-dimensional arrays are supported.
+ num_children = array_info->element_orders.size()
+ ? array_info->element_orders.back()
+ : 0;
+ break;
case clang::Type::Pointer: {
const clang::PointerType *pointer_type =
@@ -5444,7 +5675,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
clang::QualType pointee_type(pointer_type->getPointeeType());
uint32_t num_pointee_children =
CompilerType(getASTContext(), pointee_type)
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
if (num_pointee_children == 0) {
// We have a pointer to a pointee type that claims it has no children. We
// will want to look at
@@ -5460,7 +5691,7 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
clang::QualType pointee_type = reference_type->getPointeeType();
uint32_t num_pointee_children =
CompilerType(getASTContext(), pointee_type)
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
// If this type points to a simple type, then it has 1 child
if (num_pointee_children == 0)
num_children = 1;
@@ -5473,14 +5704,14 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
CompilerType(getASTContext(), llvm::cast<clang::TypedefType>(qual_type)
->getDecl()
->getUnderlyingType())
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
break;
case clang::Type::Auto:
num_children =
CompilerType(getASTContext(),
llvm::cast<clang::AutoType>(qual_type)->getDeducedType())
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
break;
case clang::Type::Elaborated:
@@ -5488,14 +5719,14 @@ uint32_t ClangASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
CompilerType(
getASTContext(),
llvm::cast<clang::ElaboratedType>(qual_type)->getNamedType())
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
break;
case clang::Type::Paren:
num_children =
CompilerType(getASTContext(),
llvm::cast<clang::ParenType>(qual_type)->desugar())
- .GetNumChildren(omit_empty_base_classes);
+ .GetNumChildren(omit_empty_base_classes, exe_ctx);
break;
default:
break;
@@ -5733,10 +5964,10 @@ GetObjCFieldAtIndex(clang::ASTContext *ast,
if (is_bitfield && ast) {
clang::Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth();
- llvm::APSInt bitfield_apsint;
+ clang::Expr::EvalResult result;
if (bitfield_bit_size_expr &&
- bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint,
- *ast)) {
+ bitfield_bit_size_expr->EvaluateAsInt(result, *ast)) {
+ llvm::APSInt bitfield_apsint = result.Val.getInt();
*bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
}
}
@@ -5793,10 +6024,11 @@ CompilerType ClangASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
if (is_bitfield) {
clang::Expr *bitfield_bit_size_expr = field->getBitWidth();
- llvm::APSInt bitfield_apsint;
+ clang::Expr::EvalResult result;
if (bitfield_bit_size_expr &&
- bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint,
+ bitfield_bit_size_expr->EvaluateAsInt(result,
*getASTContext())) {
+ llvm::APSInt bitfield_apsint = result.Val.getInt();
*bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue();
}
}
@@ -6364,6 +6596,10 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (!type)
return CompilerType();
+ auto get_exe_scope = [&exe_ctx]() {
+ return exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
+ };
+
clang::QualType parent_qual_type(GetCanonicalQualType(type));
const clang::Type::TypeClass parent_type_class =
parent_qual_type->getTypeClass();
@@ -6372,8 +6608,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
child_is_base_class = false;
language_flags = 0;
- const bool idx_is_valid = idx < GetNumChildren(type, omit_empty_base_classes);
- uint32_t bit_offset;
+ const bool idx_is_valid =
+ idx < GetNumChildren(type, omit_empty_base_classes, exe_ctx);
+ int32_t bit_offset;
switch (parent_type_class) {
case clang::Type::Builtin:
if (idx_is_valid) {
@@ -6418,7 +6655,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (omit_empty_base_classes) {
base_class_decl = llvm::cast<clang::CXXRecordDecl>(
base_class->getType()->getAs<clang::RecordType>()->getDecl());
- if (ClangASTContext::RecordHasFields(base_class_decl) == false)
+ if (!ClangASTContext::RecordHasFields(base_class_decl))
continue;
}
@@ -6430,80 +6667,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (base_class->isVirtual()) {
bool handled = false;
if (valobj) {
- Status err;
- AddressType addr_type = eAddressTypeInvalid;
- lldb::addr_t vtable_ptr_addr =
- valobj->GetCPPVTableAddress(addr_type);
-
- if (vtable_ptr_addr != LLDB_INVALID_ADDRESS &&
- addr_type == eAddressTypeLoad) {
-
- ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
- Process *process = exe_ctx.GetProcessPtr();
- if (process) {
- clang::VTableContextBase *vtable_ctx =
- getASTContext()->getVTableContext();
- if (vtable_ctx) {
- if (vtable_ctx->isMicrosoft()) {
- clang::MicrosoftVTableContext *msoft_vtable_ctx =
- static_cast<clang::MicrosoftVTableContext *>(
- vtable_ctx);
-
- if (vtable_ptr_addr) {
- const lldb::addr_t vbtable_ptr_addr =
- vtable_ptr_addr +
- record_layout.getVBPtrOffset().getQuantity();
-
- const lldb::addr_t vbtable_ptr =
- process->ReadPointerFromMemory(vbtable_ptr_addr,
- err);
- if (vbtable_ptr != LLDB_INVALID_ADDRESS) {
- // Get the index into the virtual base table. The
- // index is the index in uint32_t from vbtable_ptr
- const unsigned vbtable_index =
- msoft_vtable_ctx->getVBTableIndex(
- cxx_record_decl, base_class_decl);
- const lldb::addr_t base_offset_addr =
- vbtable_ptr + vbtable_index * 4;
- const uint32_t base_offset =
- process->ReadUnsignedIntegerFromMemory(
- base_offset_addr, 4, UINT32_MAX, err);
- if (base_offset != UINT32_MAX) {
- handled = true;
- bit_offset = base_offset * 8;
- }
- }
- }
- } else {
- clang::ItaniumVTableContext *itanium_vtable_ctx =
- static_cast<clang::ItaniumVTableContext *>(
- vtable_ctx);
- if (vtable_ptr_addr) {
- const lldb::addr_t vtable_ptr =
- process->ReadPointerFromMemory(vtable_ptr_addr,
- err);
- if (vtable_ptr != LLDB_INVALID_ADDRESS) {
- clang::CharUnits base_offset_offset =
- itanium_vtable_ctx->getVirtualBaseOffsetOffset(
- cxx_record_decl, base_class_decl);
- const lldb::addr_t base_offset_addr =
- vtable_ptr + base_offset_offset.getQuantity();
- const uint32_t base_offset_size =
- process->GetAddressByteSize();
- const uint64_t base_offset =
- process->ReadUnsignedIntegerFromMemory(
- base_offset_addr, base_offset_size,
- UINT32_MAX, err);
- if (base_offset < UINT32_MAX) {
- handled = true;
- bit_offset = base_offset * 8;
- }
- }
- }
- }
- }
- }
- }
+ clang::VTableContextBase *vtable_ctx =
+ getASTContext()->getVTableContext();
+ if (vtable_ctx)
+ handled = GetVBaseBitOffset(*vtable_ctx, *valobj,
+ record_layout, cxx_record_decl,
+ base_class_decl, bit_offset);
}
if (!handled)
bit_offset = record_layout.getVBaseClassOffset(base_class_decl)
@@ -6519,9 +6688,11 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
CompilerType base_class_clang_type(getASTContext(),
base_class->getType());
child_name = base_class_clang_type.GetTypeName().AsCString("");
- uint64_t base_class_clang_type_bit_size =
- base_class_clang_type.GetBitSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ Optional<uint64_t> size =
+ base_class_clang_type.GetBitSize(get_exe_scope());
+ if (!size)
+ return {};
+ uint64_t base_class_clang_type_bit_size = *size;
// Base classes bit sizes should be a multiple of 8 bits in size
assert(base_class_clang_type_bit_size % 8 == 0);
@@ -6549,8 +6720,11 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// alignment (field_type_info.second) from the AST context.
CompilerType field_clang_type(getASTContext(), field->getType());
assert(field_idx < record_layout.getFieldCount());
- child_byte_size = field_clang_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ Optional<uint64_t> size =
+ field_clang_type.GetByteSize(get_exe_scope());
+ if (!size)
+ return {};
+ child_byte_size = *size;
const uint32_t child_bit_size = child_byte_size * 8;
// Figure out the field offset within the current struct/union/class
@@ -6594,8 +6768,8 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
CompilerType base_class_clang_type(
getASTContext(), getASTContext()->getObjCInterfaceType(
superclass_interface_decl));
- if (base_class_clang_type.GetNumChildren(
- omit_empty_base_classes) > 0) {
+ if (base_class_clang_type.GetNumChildren(omit_empty_base_classes,
+ exe_ctx) > 0) {
if (idx == 0) {
clang::QualType ivar_qual_type(
getASTContext()->getObjCInterfaceType(
@@ -6662,9 +6836,9 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
}
}
- // Setting this to UINT32_MAX to make sure we don't compute it
+ // Setting this to INT32_MAX to make sure we don't compute it
// twice...
- bit_offset = UINT32_MAX;
+ bit_offset = INT32_MAX;
if (child_byte_offset ==
static_cast<int32_t>(LLDB_INVALID_IVAR_OFFSET)) {
@@ -6681,7 +6855,7 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
if (ClangASTContext::FieldIsBitfield(getASTContext(), ivar_decl,
child_bitfield_bit_size)) {
- if (bit_offset == UINT32_MAX)
+ if (bit_offset == INT32_MAX)
bit_offset = interface_layout.getFieldOffset(
child_idx - superclass_idx);
@@ -6721,10 +6895,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// We have a pointer to an simple type
if (idx == 0 && pointee_clang_type.GetCompleteType()) {
- child_byte_size = pointee_clang_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee_clang_type;
+ if (Optional<uint64_t> size =
+ pointee_clang_type.GetByteSize(get_exe_scope())) {
+ child_byte_size = *size;
+ child_byte_offset = 0;
+ return pointee_clang_type;
+ }
}
}
}
@@ -6742,10 +6918,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
::snprintf(element_name, sizeof(element_name), "[%" PRIu64 "]",
static_cast<uint64_t>(idx));
child_name.assign(element_name);
- child_byte_size = element_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
+ if (Optional<uint64_t> size =
+ element_type.GetByteSize(get_exe_scope())) {
+ child_byte_size = *size;
+ child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+ return element_type;
+ }
}
}
}
@@ -6759,10 +6937,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
CompilerType element_type(getASTContext(), array->getElementType());
if (element_type.GetCompleteType()) {
child_name = llvm::formatv("[{0}]", idx);
- child_byte_size = element_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
+ if (Optional<uint64_t> size =
+ element_type.GetByteSize(get_exe_scope())) {
+ child_byte_size = *size;
+ child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
+ return element_type;
+ }
}
}
}
@@ -6796,10 +6976,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// We have a pointer to an simple type
if (idx == 0) {
- child_byte_size = pointee_clang_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee_clang_type;
+ if (Optional<uint64_t> size =
+ pointee_clang_type.GetByteSize(get_exe_scope())) {
+ child_byte_size = *size;
+ child_byte_offset = 0;
+ return pointee_clang_type;
+ }
}
}
break;
@@ -6831,10 +7013,12 @@ CompilerType ClangASTContext::GetChildCompilerTypeAtIndex(
// We have a pointer to an simple type
if (idx == 0) {
- child_byte_size = pointee_clang_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee_clang_type;
+ if (Optional<uint64_t> size =
+ pointee_clang_type.GetByteSize(get_exe_scope())) {
+ child_byte_size = *size;
+ child_byte_offset = 0;
+ return pointee_clang_type;
+ }
}
}
}
@@ -7281,14 +7465,14 @@ ClangASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
->getAs<clang::RecordType>()
->getDecl());
if (omit_empty_base_classes &&
- ClangASTContext::RecordHasFields(base_class_decl) == false)
+ !ClangASTContext::RecordHasFields(base_class_decl))
continue;
CompilerType base_class_clang_type(getASTContext(),
base_class->getType());
std::string base_class_type_name(
base_class_clang_type.GetTypeName().AsCString(""));
- if (base_class_type_name.compare(name) == 0)
+ if (base_class_type_name == name)
return child_idx;
++child_idx;
}
@@ -7623,7 +7807,7 @@ ClangASTContext::GetTypeTemplateArgument(lldb::opaque_compiler_type_t type,
return CompilerType(getASTContext(), template_arg.getAsType());
}
-llvm::Optional<CompilerType::IntegralTemplateArgument>
+Optional<CompilerType::IntegralTemplateArgument>
ClangASTContext::GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type,
size_t idx) {
const clang::ClassTemplateSpecializationDecl *template_decl =
@@ -7663,11 +7847,16 @@ clang::RecordDecl *ClangASTContext::GetAsRecordDecl(const CompilerType &type) {
}
clang::TagDecl *ClangASTContext::GetAsTagDecl(const CompilerType &type) {
- clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type);
- if (qual_type.isNull())
- return nullptr;
- else
- return qual_type->getAsTagDecl();
+ return ClangUtil::GetAsTagDecl(type);
+}
+
+clang::TypedefNameDecl *
+ClangASTContext::GetAsTypedefDecl(const CompilerType &type) {
+ const clang::TypedefType *typedef_type =
+ llvm::dyn_cast<clang::TypedefType>(ClangUtil::GetQualType(type));
+ if (typedef_type)
+ return typedef_type->getDecl();
+ return nullptr;
}
clang::CXXRecordDecl *
@@ -7686,7 +7875,7 @@ ClangASTContext::GetAsObjCInterfaceDecl(const CompilerType &type) {
}
clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
- const CompilerType &type, const char *name,
+ const CompilerType &type, llvm::StringRef name,
const CompilerType &field_clang_type, AccessType access,
uint32_t bitfield_bit_size) {
if (!type.IsValid() || !field_clang_type.IsValid())
@@ -7696,6 +7885,9 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
if (!ast)
return nullptr;
clang::ASTContext *clang_ast = ast->getASTContext();
+ clang::IdentifierInfo *ident = nullptr;
+ if (!name.empty())
+ ident = &clang_ast->Idents.get(name);
clang::FieldDecl *field = nullptr;
@@ -7713,14 +7905,14 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
field = clang::FieldDecl::Create(
*clang_ast, record_decl, clang::SourceLocation(),
clang::SourceLocation(),
- name ? &clang_ast->Idents.get(name) : nullptr, // Identifier
- ClangUtil::GetQualType(field_clang_type), // Field type
- nullptr, // TInfo *
- bit_width, // BitWidth
- false, // Mutable
- clang::ICIS_NoInit); // HasInit
-
- if (!name) {
+ ident, // Identifier
+ ClangUtil::GetQualType(field_clang_type), // Field type
+ nullptr, // TInfo *
+ bit_width, // BitWidth
+ false, // Mutable
+ clang::ICIS_NoInit); // HasInit
+
+ if (name.empty()) {
// Determine whether this field corresponds to an anonymous struct or
// union.
if (const clang::TagType *TagT =
@@ -7756,9 +7948,9 @@ clang::FieldDecl *ClangASTContext::AddFieldToRecordType(
field = clang::ObjCIvarDecl::Create(
*clang_ast, class_interface_decl, clang::SourceLocation(),
clang::SourceLocation(),
- name ? &clang_ast->Idents.get(name) : nullptr, // Identifier
- ClangUtil::GetQualType(field_clang_type), // Field type
- nullptr, // TypeSourceInfo *
+ ident, // Identifier
+ ClangUtil::GetQualType(field_clang_type), // Field type
+ nullptr, // TypeSourceInfo *
ConvertAccessTypeToObjCIvarAccessControl(access), bit_width,
is_synthesized);
@@ -7897,38 +8089,44 @@ void ClangASTContext::SetIsPacked(const CompilerType &type) {
}
clang::VarDecl *ClangASTContext::AddVariableToRecordType(
- const CompilerType &type, const char *name, const CompilerType &var_type,
- AccessType access) {
- clang::VarDecl *var_decl = nullptr;
-
+ const CompilerType &type, llvm::StringRef name,
+ const CompilerType &var_type, AccessType access) {
if (!type.IsValid() || !var_type.IsValid())
return nullptr;
+
ClangASTContext *ast = llvm::dyn_cast<ClangASTContext>(type.GetTypeSystem());
if (!ast)
return nullptr;
clang::RecordDecl *record_decl = ast->GetAsRecordDecl(type);
- if (record_decl) {
- var_decl = clang::VarDecl::Create(
- *ast->getASTContext(), // ASTContext &
- record_decl, // DeclContext *
- clang::SourceLocation(), // clang::SourceLocation StartLoc
- clang::SourceLocation(), // clang::SourceLocation IdLoc
- name ? &ast->getASTContext()->Idents.get(name)
- : nullptr, // clang::IdentifierInfo *
- ClangUtil::GetQualType(var_type), // Variable clang::QualType
- nullptr, // TypeSourceInfo *
- clang::SC_Static); // StorageClass
- if (var_decl) {
- var_decl->setAccess(
- ClangASTContext::ConvertAccessTypeToAccessSpecifier(access));
- record_decl->addDecl(var_decl);
+ if (!record_decl)
+ return nullptr;
+
+ clang::VarDecl *var_decl = nullptr;
+ clang::IdentifierInfo *ident = nullptr;
+ if (!name.empty())
+ ident = &ast->getASTContext()->Idents.get(name);
+
+ var_decl = clang::VarDecl::Create(
+ *ast->getASTContext(), // ASTContext &
+ record_decl, // DeclContext *
+ clang::SourceLocation(), // clang::SourceLocation StartLoc
+ clang::SourceLocation(), // clang::SourceLocation IdLoc
+ ident, // clang::IdentifierInfo *
+ ClangUtil::GetQualType(var_type), // Variable clang::QualType
+ nullptr, // TypeSourceInfo *
+ clang::SC_Static); // StorageClass
+ if (!var_decl)
+ return nullptr;
+
+ var_decl->setAccess(
+ ClangASTContext::ConvertAccessTypeToAccessSpecifier(access));
+ record_decl->addDecl(var_decl);
#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(var_decl);
+ VerifyDecl(var_decl);
#endif
- }
- }
+
return var_decl;
}
@@ -8129,41 +8327,46 @@ clang::CXXMethodDecl *ClangASTContext::AddMethodToCXXRecordType(
return cxx_method_decl;
}
+void ClangASTContext::AddMethodOverridesForCXXRecordType(
+ lldb::opaque_compiler_type_t type) {
+ if (auto *record = GetAsCXXRecordDecl(type))
+ for (auto *method : record->methods())
+ addOverridesForMethod(method);
+}
+
#pragma mark C++ Base Classes
-clang::CXXBaseSpecifier *
+std::unique_ptr<clang::CXXBaseSpecifier>
ClangASTContext::CreateBaseClassSpecifier(lldb::opaque_compiler_type_t type,
AccessType access, bool is_virtual,
bool base_of_class) {
- if (type)
- return new clang::CXXBaseSpecifier(
- clang::SourceRange(), is_virtual, base_of_class,
- ClangASTContext::ConvertAccessTypeToAccessSpecifier(access),
- getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)),
- clang::SourceLocation());
- return nullptr;
-}
+ if (!type)
+ return nullptr;
-void ClangASTContext::DeleteBaseClassSpecifiers(
- clang::CXXBaseSpecifier **base_classes, unsigned num_base_classes) {
- for (unsigned i = 0; i < num_base_classes; ++i) {
- delete base_classes[i];
- base_classes[i] = nullptr;
- }
+ return llvm::make_unique<clang::CXXBaseSpecifier>(
+ clang::SourceRange(), is_virtual, base_of_class,
+ ClangASTContext::ConvertAccessTypeToAccessSpecifier(access),
+ getASTContext()->getTrivialTypeSourceInfo(GetQualType(type)),
+ clang::SourceLocation());
}
-bool ClangASTContext::SetBaseClassesForClassType(
+bool ClangASTContext::TransferBaseClasses(
lldb::opaque_compiler_type_t type,
- clang::CXXBaseSpecifier const *const *base_classes,
- unsigned num_base_classes) {
- if (type) {
- clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type);
- if (cxx_record_decl) {
- cxx_record_decl->setBases(base_classes, num_base_classes);
- return true;
- }
- }
- return false;
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases) {
+ if (!type)
+ return false;
+ clang::CXXRecordDecl *cxx_record_decl = GetAsCXXRecordDecl(type);
+ if (!cxx_record_decl)
+ return false;
+ std::vector<clang::CXXBaseSpecifier *> raw_bases;
+ raw_bases.reserve(bases.size());
+
+ // Clang will make a copy of them, so it's ok that we pass pointers that we're
+ // about to destroy.
+ for (auto &b : bases)
+ raw_bases.push_back(b.get());
+ cxx_record_decl->setBases(raw_bases.data(), raw_bases.size());
+ return true;
}
bool ClangASTContext::SetObjCSuperClass(
@@ -8748,44 +8951,63 @@ bool ClangASTContext::CompleteTagDeclarationDefinition(
return false;
}
-bool ClangASTContext::AddEnumerationValueToEnumerationType(
- lldb::opaque_compiler_type_t type,
- const CompilerType &enumerator_clang_type, const Declaration &decl,
- const char *name, int64_t enum_value, uint32_t enum_value_bit_size) {
- if (type && enumerator_clang_type.IsValid() && name && name[0]) {
- clang::QualType enum_qual_type(GetCanonicalQualType(type));
-
- bool is_signed = false;
- enumerator_clang_type.IsIntegerType(is_signed);
- const clang::Type *clang_type = enum_qual_type.getTypePtr();
- if (clang_type) {
- const clang::EnumType *enutype =
- llvm::dyn_cast<clang::EnumType>(clang_type);
-
- if (enutype) {
- llvm::APSInt enum_llvm_apsint(enum_value_bit_size, is_signed);
- enum_llvm_apsint = enum_value;
- clang::EnumConstantDecl *enumerator_decl =
- clang::EnumConstantDecl::Create(
- *getASTContext(), enutype->getDecl(), clang::SourceLocation(),
- name ? &getASTContext()->Idents.get(name)
- : nullptr, // Identifier
- ClangUtil::GetQualType(enumerator_clang_type),
- nullptr, enum_llvm_apsint);
-
- if (enumerator_decl) {
- enutype->getDecl()->addDecl(enumerator_decl);
+clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
+ const CompilerType &enum_type, const Declaration &decl, const char *name,
+ const llvm::APSInt &value) {
+
+ if (!enum_type || ConstString(name).IsEmpty())
+ return nullptr;
+
+ lldbassert(enum_type.GetTypeSystem() == static_cast<TypeSystem *>(this));
+
+ lldb::opaque_compiler_type_t enum_opaque_compiler_type =
+ enum_type.GetOpaqueQualType();
+
+ if (!enum_opaque_compiler_type)
+ return nullptr;
+
+ clang::QualType enum_qual_type(
+ GetCanonicalQualType(enum_opaque_compiler_type));
+
+ const clang::Type *clang_type = enum_qual_type.getTypePtr();
+
+ if (!clang_type)
+ return nullptr;
+
+ const clang::EnumType *enutype = llvm::dyn_cast<clang::EnumType>(clang_type);
+
+ if (!enutype)
+ return nullptr;
+
+ clang::EnumConstantDecl *enumerator_decl = clang::EnumConstantDecl::Create(
+ *getASTContext(), enutype->getDecl(), clang::SourceLocation(),
+ name ? &getASTContext()->Idents.get(name) : nullptr, // Identifier
+ clang::QualType(enutype, 0), nullptr, value);
+
+ if (!enumerator_decl)
+ return nullptr;
+
+ enutype->getDecl()->addDecl(enumerator_decl);
#ifdef LLDB_CONFIGURATION_DEBUG
- VerifyDecl(enumerator_decl);
+ VerifyDecl(enumerator_decl);
#endif
- return true;
- }
- }
- }
- }
- return false;
+ return enumerator_decl;
+}
+
+clang::EnumConstantDecl *ClangASTContext::AddEnumerationValueToEnumerationType(
+ const CompilerType &enum_type, const Declaration &decl, const char *name,
+ int64_t enum_value, uint32_t enum_value_bit_size) {
+ CompilerType underlying_type =
+ GetEnumerationIntegerType(enum_type.GetOpaqueQualType());
+ bool is_signed = false;
+ underlying_type.IsIntegerType(is_signed);
+
+ llvm::APSInt value(enum_value_bit_size, is_signed);
+ value = enum_value;
+
+ return AddEnumerationValueToEnumerationType(enum_type, decl, name, value);
}
CompilerType
@@ -8859,6 +9081,11 @@ ClangASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
//----------------------------------------------------------------------
#define DEPTH_INCREMENT 2
+void ClangASTContext::Dump(Stream &s) {
+ Decl *tu = Decl::castFromDeclContext(GetTranslationUnitDecl());
+ tu->dump(s.AsRawOstream());
+}
+
void ClangASTContext::DumpValue(
lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
lldb::Format format, const DataExtractor &data,
@@ -8896,8 +9123,7 @@ void ClangASTContext::DumpValue(
base_class->getType()->getAs<clang::RecordType>()->getDecl());
// Skip empty base classes
- if (verbose == false &&
- ClangASTContext::RecordHasFields(base_class_decl) == false)
+ if (!verbose && !ClangASTContext::RecordHasFields(base_class_decl))
continue;
if (base_class->isVirtual())
@@ -9668,11 +9894,16 @@ bool ClangASTContext::LayoutRecordType(
llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits>
&vbase_offsets) {
ClangASTContext *ast = (ClangASTContext *)baton;
- DWARFASTParserClang *dwarf_ast_parser =
- (DWARFASTParserClang *)ast->GetDWARFParser();
- return dwarf_ast_parser->GetClangASTImporter().LayoutRecordType(
- record_decl, bit_size, alignment, field_offsets, base_offsets,
- vbase_offsets);
+ lldb_private::ClangASTImporter *importer = nullptr;
+ if (ast->m_dwarf_ast_parser_ap)
+ importer = &ast->m_dwarf_ast_parser_ap->GetClangASTImporter();
+ if (!importer && ast->m_pdb_ast_parser_ap)
+ importer = &ast->m_pdb_ast_parser_ap->GetClangASTImporter();
+ if (!importer)
+ return false;
+
+ return importer->LayoutRecordType(record_decl, bit_size, alignment,
+ field_offsets, base_offsets, vbase_offsets);
}
//----------------------------------------------------------------------
diff --git a/source/Symbol/ClangASTImporter.cpp b/source/Symbol/ClangASTImporter.cpp
index ea3b141c9e74..621441449c20 100644
--- a/source/Symbol/ClangASTImporter.cpp
+++ b/source/Symbol/ClangASTImporter.cpp
@@ -1002,7 +1002,7 @@ clang::Decl *ClangASTImporter::Minion::Imported(clang::Decl *from,
if (isa<TagDecl>(to) || isa<ObjCInterfaceDecl>(to)) {
RecordDecl *from_record_decl = dyn_cast<RecordDecl>(from);
if (from_record_decl == nullptr ||
- from_record_decl->isInjectedClassName() == false) {
+ !from_record_decl->isInjectedClassName()) {
NamedDecl *to_named_decl = dyn_cast<NamedDecl>(to);
if (!m_decls_already_deported->count(to_named_decl))
@@ -1050,7 +1050,7 @@ clang::Decl *ClangASTImporter::Minion::Imported(clang::Decl *from,
TagDecl *to_tag_decl = dyn_cast<TagDecl>(to);
to_tag_decl->setHasExternalLexicalStorage();
- to_tag_decl->setMustBuildLookupTable();
+ to_tag_decl->getPrimaryContext()->setMustBuildLookupTable();
if (log)
log->Printf(
diff --git a/source/Symbol/ClangExternalASTSourceCallbacks.cpp b/source/Symbol/ClangExternalASTSourceCallbacks.cpp
index c88119bc9a4c..a96ef19b02f5 100644
--- a/source/Symbol/ClangExternalASTSourceCallbacks.cpp
+++ b/source/Symbol/ClangExternalASTSourceCallbacks.cpp
@@ -9,9 +9,6 @@
#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
// Clang headers like to use NDEBUG inside of them to enable/disable debug
// related features using "#ifndef NDEBUG" preprocessor blocks to do one thing
diff --git a/source/Symbol/ClangUtil.cpp b/source/Symbol/ClangUtil.cpp
index 7a67df48ee6a..687fba7c7c33 100644
--- a/source/Symbol/ClangUtil.cpp
+++ b/source/Symbol/ClangUtil.cpp
@@ -48,3 +48,11 @@ CompilerType ClangUtil::RemoveFastQualifiers(const CompilerType &ct) {
qual_type.removeLocalFastQualifiers();
return CompilerType(ct.GetTypeSystem(), qual_type.getAsOpaquePtr());
}
+
+clang::TagDecl *ClangUtil::GetAsTagDecl(const CompilerType &type) {
+ clang::QualType qual_type = ClangUtil::GetCanonicalQualType(type);
+ if (qual_type.isNull())
+ return nullptr;
+
+ return qual_type->getAsTagDecl();
+}
diff --git a/source/Symbol/CompactUnwindInfo.cpp b/source/Symbol/CompactUnwindInfo.cpp
index 7dda877582cc..6f0f35f278c4 100644
--- a/source/Symbol/CompactUnwindInfo.cpp
+++ b/source/Symbol/CompactUnwindInfo.cpp
@@ -183,8 +183,7 @@ bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr,
if (function_info.encoding == 0)
return false;
- ArchSpec arch;
- if (m_objfile.GetArchitecture(arch)) {
+ if (ArchSpec arch = m_objfile.GetArchitecture()) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
if (log && log->GetVerbose()) {
@@ -204,7 +203,7 @@ bool CompactUnwindInfo::GetUnwindPlan(Target &target, Address addr,
if (sl) {
addr_t func_range_start_file_addr =
function_info.valid_range_offset_start +
- m_objfile.GetHeaderAddress().GetFileAddress();
+ m_objfile.GetBaseAddress().GetFileAddress();
AddressRange func_range(func_range_start_file_addr,
function_info.valid_range_offset_end -
function_info.valid_range_offset_start,
@@ -259,7 +258,7 @@ void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
m_objfile.GetModule()->LogMessage(
log, "Reading compact unwind first-level indexes");
- if (m_unwindinfo_data_computed == false) {
+ if (!m_unwindinfo_data_computed) {
if (m_section_sp->IsEncrypted()) {
// Can't get section contents of a protected/encrypted section until we
// have a live process and can read them out of memory.
@@ -338,8 +337,7 @@ void CompactUnwindInfo::ScanIndex(const ProcessSP &process_sp) {
// };
bool clear_address_zeroth_bit = false;
- ArchSpec arch;
- if (m_objfile.GetArchitecture(arch)) {
+ if (ArchSpec arch = m_objfile.GetArchitecture()) {
if (arch.GetTriple().getArch() == llvm::Triple::arm ||
arch.GetTriple().getArch() == llvm::Triple::thumb)
clear_address_zeroth_bit = true;
@@ -513,7 +511,7 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
return false;
addr_t function_offset =
- address.GetFileAddress() - m_objfile.GetHeaderAddress().GetFileAddress();
+ address.GetFileAddress() - m_objfile.GetBaseAddress().GetFileAddress();
UnwindIndex key;
key.function_offset = function_offset;
@@ -529,7 +527,7 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
--it;
}
- if (it->sentinal_entry == true) {
+ if (it->sentinal_entry) {
return false;
}
@@ -578,10 +576,10 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
if (sl) {
uint32_t lsda_offset = GetLSDAForFunctionOffset(
lsda_array_start, lsda_array_count, function_offset);
- addr_t objfile_header_file_address =
- m_objfile.GetHeaderAddress().GetFileAddress();
+ addr_t objfile_base_address =
+ m_objfile.GetBaseAddress().GetFileAddress();
unwind_info.lsda_address.ResolveAddressUsingFileSections(
- objfile_header_file_address + lsda_offset, sl);
+ objfile_base_address + lsda_offset, sl);
}
}
if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) {
@@ -596,10 +594,10 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
SectionList *sl = m_objfile.GetSectionList();
if (sl) {
uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
- addr_t objfile_header_file_address =
- m_objfile.GetHeaderAddress().GetFileAddress();
+ addr_t objfile_base_address =
+ m_objfile.GetBaseAddress().GetFileAddress();
unwind_info.personality_ptr_address.ResolveAddressUsingFileSections(
- objfile_header_file_address + personality_offset, sl);
+ objfile_base_address + personality_offset, sl);
}
}
}
@@ -662,10 +660,10 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
if (sl) {
uint32_t lsda_offset = GetLSDAForFunctionOffset(
lsda_array_start, lsda_array_count, function_offset);
- addr_t objfile_header_file_address =
- m_objfile.GetHeaderAddress().GetFileAddress();
+ addr_t objfile_base_address =
+ m_objfile.GetBaseAddress().GetFileAddress();
unwind_info.lsda_address.ResolveAddressUsingFileSections(
- objfile_header_file_address + lsda_offset, sl);
+ objfile_base_address + lsda_offset, sl);
}
}
if (unwind_info.encoding & UNWIND_PERSONALITY_MASK) {
@@ -680,10 +678,10 @@ bool CompactUnwindInfo::GetCompactUnwindInfoForFunction(
SectionList *sl = m_objfile.GetSectionList();
if (sl) {
uint32_t personality_offset = m_unwindinfo_data.GetU32(&offset);
- addr_t objfile_header_file_address =
- m_objfile.GetHeaderAddress().GetFileAddress();
+ addr_t objfile_base_address =
+ m_objfile.GetBaseAddress().GetFileAddress();
unwind_info.personality_ptr_address.ResolveAddressUsingFileSections(
- objfile_header_file_address + personality_offset, sl);
+ objfile_base_address + personality_offset, sl);
}
}
}
@@ -925,7 +923,7 @@ bool CompactUnwindInfo::CreateUnwindPlan_x86_64(Target &target,
for (uint32_t i = 0; i < register_count; i++) {
int renum = 0;
for (int j = 1; j < 7; j++) {
- if (used[j] == false) {
+ if (!used[j]) {
if (renum == permunreg[i]) {
registers[i] = j;
used[j] = true;
@@ -1187,7 +1185,7 @@ bool CompactUnwindInfo::CreateUnwindPlan_i386(Target &target,
for (uint32_t i = 0; i < register_count; i++) {
int renum = 0;
for (int j = 1; j < 7; j++) {
- if (used[j] == false) {
+ if (!used[j]) {
if (renum == permunreg[i]) {
registers[i] = j;
used[j] = true;
diff --git a/source/Symbol/CompileUnit.cpp b/source/Symbol/CompileUnit.cpp
index a4f0d4231e2f..74512c891440 100644
--- a/source/Symbol/CompileUnit.cpp
+++ b/source/Symbol/CompileUnit.cpp
@@ -21,8 +21,8 @@ CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
const char *pathname, const lldb::user_id_t cu_sym_id,
lldb::LanguageType language,
lldb_private::LazyBool is_optimized)
- : ModuleChild(module_sp), FileSpec(pathname, false), UserID(cu_sym_id),
- m_user_data(user_data), m_language(language), m_flags(0), m_functions(),
+ : ModuleChild(module_sp), FileSpec(pathname), UserID(cu_sym_id),
+ m_user_data(user_data), m_language(language), m_flags(0),
m_support_files(), m_line_table_ap(), m_variables(),
m_is_optimized(is_optimized) {
if (language != eLanguageTypeUnknown)
@@ -35,7 +35,7 @@ CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
lldb::LanguageType language,
lldb_private::LazyBool is_optimized)
: ModuleChild(module_sp), FileSpec(fspec), UserID(cu_sym_id),
- m_user_data(user_data), m_language(language), m_flags(0), m_functions(),
+ m_user_data(user_data), m_language(language), m_flags(0),
m_support_files(), m_line_table_ap(), m_variables(),
m_is_optimized(is_optimized) {
if (language != eLanguageTypeUnknown)
@@ -66,6 +66,22 @@ void CompileUnit::GetDescription(Stream *s,
<< (const FileSpec &)*this << "\", language = \"" << language << '"';
}
+void CompileUnit::ForeachFunction(
+ llvm::function_ref<bool(const FunctionSP &)> lambda) const {
+ std::vector<lldb::FunctionSP> sorted_functions;
+ sorted_functions.reserve(m_functions_by_uid.size());
+ for (auto &p : m_functions_by_uid)
+ sorted_functions.push_back(p.second);
+ llvm::sort(sorted_functions.begin(), sorted_functions.end(),
+ [](const lldb::FunctionSP &a, const lldb::FunctionSP &b) {
+ return a->GetID() < b->GetID();
+ });
+
+ for (auto &f : sorted_functions)
+ if (lambda(f))
+ return;
+}
+
//----------------------------------------------------------------------
// Dump the current contents of this object. No functions that cause on demand
// parsing of functions, globals, statics are called, so this is a good
@@ -89,13 +105,12 @@ void CompileUnit::Dump(Stream *s, bool show_context) const {
s->IndentLess();
}
- if (!m_functions.empty()) {
+ if (!m_functions_by_uid.empty()) {
s->IndentMore();
- std::vector<FunctionSP>::const_iterator pos;
- std::vector<FunctionSP>::const_iterator end = m_functions.end();
- for (pos = m_functions.begin(); pos != end; ++pos) {
- (*pos)->Dump(s, show_context);
- }
+ ForeachFunction([&s, show_context](const FunctionSP &f) {
+ f->Dump(s, show_context);
+ return false;
+ });
s->IndentLess();
s->EOL();
@@ -106,15 +121,7 @@ void CompileUnit::Dump(Stream *s, bool show_context) const {
// Add a function to this compile unit
//----------------------------------------------------------------------
void CompileUnit::AddFunction(FunctionSP &funcSP) {
- // TODO: order these by address
- m_functions.push_back(funcSP);
-}
-
-FunctionSP CompileUnit::GetFunctionAtIndex(size_t idx) {
- FunctionSP funcSP;
- if (idx < m_functions.size())
- funcSP = m_functions[idx];
- return funcSP;
+ m_functions_by_uid[funcSP->GetID()] = funcSP;
}
//----------------------------------------------------------------------
@@ -163,18 +170,10 @@ FunctionSP CompileUnit::GetFunctionAtIndex(size_t idx) {
//}
FunctionSP CompileUnit::FindFunctionByUID(lldb::user_id_t func_uid) {
- FunctionSP funcSP;
- if (!m_functions.empty()) {
- std::vector<FunctionSP>::const_iterator pos;
- std::vector<FunctionSP>::const_iterator end = m_functions.end();
- for (pos = m_functions.begin(); pos != end; ++pos) {
- if ((*pos)->GetID() == func_uid) {
- funcSP = *pos;
- break;
- }
- }
- }
- return funcSP;
+ auto it = m_functions_by_uid.find(func_uid);
+ if (it == m_functions_by_uid.end())
+ return FunctionSP();
+ return it->second;
}
lldb::LanguageType CompileUnit::GetLanguage() {
@@ -183,9 +182,7 @@ lldb::LanguageType CompileUnit::GetLanguage() {
m_flags.Set(flagsParsedLanguage);
SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor();
if (symbol_vendor) {
- SymbolContext sc;
- CalculateSymbolContext(&sc);
- m_language = symbol_vendor->ParseCompileUnitLanguage(sc);
+ m_language = symbol_vendor->ParseLanguage(*this);
}
}
}
@@ -197,11 +194,8 @@ LineTable *CompileUnit::GetLineTable() {
if (m_flags.IsClear(flagsParsedLineTable)) {
m_flags.Set(flagsParsedLineTable);
SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor();
- if (symbol_vendor) {
- SymbolContext sc;
- CalculateSymbolContext(&sc);
- symbol_vendor->ParseCompileUnitLineTable(sc);
- }
+ if (symbol_vendor)
+ symbol_vendor->ParseLineTable(*this);
}
}
return m_line_table_ap.get();
@@ -221,9 +215,7 @@ DebugMacros *CompileUnit::GetDebugMacros() {
m_flags.Set(flagsParsedDebugMacros);
SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor();
if (symbol_vendor) {
- SymbolContext sc;
- CalculateSymbolContext(&sc);
- symbol_vendor->ParseCompileUnitDebugMacros(sc);
+ symbol_vendor->ParseDebugMacros(*this);
}
}
}
@@ -279,7 +271,8 @@ uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,
uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line, bool check_inlines,
- bool exact, uint32_t resolve_scope,
+ bool exact,
+ SymbolContextItem resolve_scope,
SymbolContextList &sc_list) {
// First find all of the file indexes that match our "file_spec". If
// "file_spec" has an empty directory, then only compare the basenames when
@@ -291,7 +284,7 @@ uint32_t CompileUnit::ResolveSymbolContext(const FileSpec &file_spec,
// If we are not looking for inlined functions and our file spec doesn't
// match then we are done...
- if (file_spec_matches_cu_file_spec == false && check_inlines == false)
+ if (!file_spec_matches_cu_file_spec && !check_inlines)
return 0;
uint32_t file_idx =
@@ -387,9 +380,7 @@ bool CompileUnit::GetIsOptimized() {
if (m_is_optimized == eLazyBoolCalculate) {
m_is_optimized = eLazyBoolNo;
if (SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor()) {
- SymbolContext sc;
- CalculateSymbolContext(&sc);
- if (symbol_vendor->ParseCompileUnitIsOptimized(sc))
+ if (symbol_vendor->ParseIsOptimized(*this))
m_is_optimized = eLazyBoolYes;
}
}
@@ -419,9 +410,7 @@ FileSpecList &CompileUnit::GetSupportFiles() {
m_flags.Set(flagsParsedSupportFiles);
SymbolVendor *symbol_vendor = GetModule()->GetSymbolVendor();
if (symbol_vendor) {
- SymbolContext sc;
- CalculateSymbolContext(&sc);
- symbol_vendor->ParseCompileUnitSupportFiles(sc, m_support_files);
+ symbol_vendor->ParseSupportFiles(*this, m_support_files);
}
}
}
diff --git a/source/Symbol/CompilerType.cpp b/source/Symbol/CompilerType.cpp
index 2dd1d3ebd04b..7e381abd7d11 100644
--- a/source/Symbol/CompilerType.cpp
+++ b/source/Symbol/CompilerType.cpp
@@ -10,7 +10,6 @@
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
@@ -20,6 +19,7 @@
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
@@ -504,15 +504,18 @@ CompilerType::GetBasicTypeFromAST(lldb::BasicType basic_type) const {
// Exploring the type
//----------------------------------------------------------------------
-uint64_t CompilerType::GetBitSize(ExecutionContextScope *exe_scope) const {
- if (IsValid()) {
+llvm::Optional<uint64_t>
+CompilerType::GetBitSize(ExecutionContextScope *exe_scope) const {
+ if (IsValid())
return m_type_system->GetBitSize(m_type, exe_scope);
- }
- return 0;
+ return {};
}
-uint64_t CompilerType::GetByteSize(ExecutionContextScope *exe_scope) const {
- return (GetBitSize(exe_scope) + 7) / 8;
+llvm::Optional<uint64_t>
+CompilerType::GetByteSize(ExecutionContextScope *exe_scope) const {
+ if (llvm::Optional<uint64_t> bit_size = GetBitSize(exe_scope))
+ return (*bit_size + 7) / 8;
+ return {};
}
size_t CompilerType::GetTypeBitAlign() const {
@@ -535,10 +538,12 @@ lldb::Format CompilerType::GetFormat() const {
return m_type_system->GetFormat(m_type);
}
-uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes) const {
+uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes,
+ const ExecutionContext *exe_ctx) const {
if (!IsValid())
return 0;
- return m_type_system->GetNumChildren(m_type, omit_empty_base_classes);
+ return m_type_system->GetNumChildren(m_type, omit_empty_base_classes,
+ exe_ctx);
}
lldb::BasicType CompilerType::GetBasicTypeEnumeration() const {
@@ -814,7 +819,9 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
if (encoding == lldb::eEncodingInvalid || count != 1)
return false;
- const uint64_t byte_size = GetByteSize(nullptr);
+ llvm::Optional<uint64_t> byte_size = GetByteSize(nullptr);
+ if (!byte_size)
+ return false;
lldb::offset_t offset = data_byte_offset;
switch (encoding) {
case lldb::eEncodingInvalid:
@@ -822,15 +829,15 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
case lldb::eEncodingVector:
break;
case lldb::eEncodingUint:
- if (byte_size <= sizeof(unsigned long long)) {
- uint64_t uval64 = data.GetMaxU64(&offset, byte_size);
- if (byte_size <= sizeof(unsigned int)) {
+ if (*byte_size <= sizeof(unsigned long long)) {
+ uint64_t uval64 = data.GetMaxU64(&offset, *byte_size);
+ if (*byte_size <= sizeof(unsigned int)) {
value = (unsigned int)uval64;
return true;
- } else if (byte_size <= sizeof(unsigned long)) {
+ } else if (*byte_size <= sizeof(unsigned long)) {
value = (unsigned long)uval64;
return true;
- } else if (byte_size <= sizeof(unsigned long long)) {
+ } else if (*byte_size <= sizeof(unsigned long long)) {
value = (unsigned long long)uval64;
return true;
} else
@@ -839,15 +846,15 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
break;
case lldb::eEncodingSint:
- if (byte_size <= sizeof(long long)) {
- int64_t sval64 = data.GetMaxS64(&offset, byte_size);
- if (byte_size <= sizeof(int)) {
+ if (*byte_size <= sizeof(long long)) {
+ int64_t sval64 = data.GetMaxS64(&offset, *byte_size);
+ if (*byte_size <= sizeof(int)) {
value = (int)sval64;
return true;
- } else if (byte_size <= sizeof(long)) {
+ } else if (*byte_size <= sizeof(long)) {
value = (long)sval64;
return true;
- } else if (byte_size <= sizeof(long long)) {
+ } else if (*byte_size <= sizeof(long long)) {
value = (long long)sval64;
return true;
} else
@@ -856,10 +863,10 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
break;
case lldb::eEncodingIEEE754:
- if (byte_size <= sizeof(long double)) {
+ if (*byte_size <= sizeof(long double)) {
uint32_t u32;
uint64_t u64;
- if (byte_size == sizeof(float)) {
+ if (*byte_size == sizeof(float)) {
if (sizeof(float) == sizeof(uint32_t)) {
u32 = data.GetU32(&offset);
value = *((float *)&u32);
@@ -869,7 +876,7 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
value = *((float *)&u64);
return true;
}
- } else if (byte_size == sizeof(double)) {
+ } else if (*byte_size == sizeof(double)) {
if (sizeof(double) == sizeof(uint32_t)) {
u32 = data.GetU32(&offset);
value = *((double *)&u32);
@@ -879,7 +886,7 @@ bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data,
value = *((double *)&u64);
return true;
}
- } else if (byte_size == sizeof(long double)) {
+ } else if (*byte_size == sizeof(long double)) {
if (sizeof(long double) == sizeof(uint32_t)) {
u32 = data.GetU32(&offset);
value = *((long double *)&u32);
@@ -910,12 +917,15 @@ bool CompilerType::SetValueFromScalar(const Scalar &value, Stream &strm) {
if (encoding == lldb::eEncodingInvalid || count != 1)
return false;
- const uint64_t bit_width = GetBitSize(nullptr);
+ llvm::Optional<uint64_t> bit_width = GetBitSize(nullptr);
+ if (!bit_width)
+ return false;
+
// This function doesn't currently handle non-byte aligned assignments
- if ((bit_width % 8) != 0)
+ if ((*bit_width % 8) != 0)
return false;
- const uint64_t byte_size = (bit_width + 7) / 8;
+ const uint64_t byte_size = (*bit_width + 7) / 8;
switch (encoding) {
case lldb::eEncodingInvalid:
break;
@@ -992,20 +1002,23 @@ bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx,
if (!GetCompleteType())
return false;
- const uint64_t byte_size =
+ auto byte_size =
GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- if (data.GetByteSize() < byte_size) {
- lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0'));
+ if (!byte_size)
+ return false;
+
+ if (data.GetByteSize() < *byte_size) {
+ lldb::DataBufferSP data_sp(new DataBufferHeap(*byte_size, '\0'));
data.SetData(data_sp);
}
- uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size));
+ uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, *byte_size));
if (dst != nullptr) {
if (address_type == eAddressTypeHost) {
if (addr == 0)
return false;
// The address is an address in this process, so just copy it
- memcpy(dst, reinterpret_cast<uint8_t *>(addr), byte_size);
+ memcpy(dst, reinterpret_cast<uint8_t *>(addr), *byte_size);
return true;
} else {
Process *process = nullptr;
@@ -1013,7 +1026,7 @@ bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx,
process = exe_ctx->GetProcessPtr();
if (process) {
Status error;
- return process->ReadMemory(addr, dst, byte_size, error) == byte_size;
+ return process->ReadMemory(addr, dst, *byte_size, error) == *byte_size;
}
}
}
@@ -1034,13 +1047,15 @@ bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx,
if (!GetCompleteType())
return false;
- const uint64_t byte_size =
+ auto byte_size =
GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
+ if (!byte_size)
+ return false;
- if (byte_size > 0) {
+ if (*byte_size > 0) {
if (address_type == eAddressTypeHost) {
// The address is an address in this process, so just copy it
- memcpy((void *)addr, new_value.GetData(), byte_size);
+ memcpy((void *)addr, new_value.GetData(), *byte_size);
return true;
} else {
Process *process = nullptr;
@@ -1048,24 +1063,14 @@ bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx,
process = exe_ctx->GetProcessPtr();
if (process) {
Status error;
- return process->WriteMemory(addr, new_value.GetData(), byte_size,
- error) == byte_size;
+ return process->WriteMemory(addr, new_value.GetData(), *byte_size,
+ error) == *byte_size;
}
}
}
return false;
}
-// clang::CXXRecordDecl *
-// CompilerType::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t
-// opaque_compiler_qual_type)
-//{
-// if (opaque_compiler_qual_type)
-// return
-// clang::QualType::getFromOpaquePtr(opaque_compiler_qual_type)->getAsCXXRecordDecl();
-// return NULL;
-//}
-
bool lldb_private::operator==(const lldb_private::CompilerType &lhs,
const lldb_private::CompilerType &rhs) {
return lhs.GetTypeSystem() == rhs.GetTypeSystem() &&
@@ -1074,6 +1079,5 @@ bool lldb_private::operator==(const lldb_private::CompilerType &lhs,
bool lldb_private::operator!=(const lldb_private::CompilerType &lhs,
const lldb_private::CompilerType &rhs) {
- return lhs.GetTypeSystem() != rhs.GetTypeSystem() ||
- lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType();
+ return !(lhs == rhs);
}
diff --git a/source/Symbol/DWARFCallFrameInfo.cpp b/source/Symbol/DWARFCallFrameInfo.cpp
index 1bf9ff99e015..c8c3a10026a2 100644
--- a/source/Symbol/DWARFCallFrameInfo.cpp
+++ b/source/Symbol/DWARFCallFrameInfo.cpp
@@ -161,7 +161,7 @@ bool DWARFCallFrameInfo::GetUnwindPlan(Address addr, UnwindPlan &unwind_plan) {
module_sp->GetObjectFile() != &m_objfile)
return false;
- if (GetFDEEntryByFileAddress(addr.GetFileAddress(), fde_entry) == false)
+ if (!GetFDEEntryByFileAddress(addr.GetFileAddress(), fde_entry))
return false;
return FDEToUnwindPlan(fde_entry.data, addr, unwind_plan);
}
@@ -243,7 +243,7 @@ DWARFCallFrameInfo::CIESP
DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
CIESP cie_sp(new CIE(cie_offset));
lldb::offset_t offset = cie_offset;
- if (m_cfi_data_initialized == false)
+ if (!m_cfi_data_initialized)
GetCFIData();
uint32_t length = m_cfi_data.GetU32(&offset);
dw_offset_t cie_id, end_offset;
@@ -394,7 +394,7 @@ DWARFCallFrameInfo::ParseCIE(const dw_offset_t cie_offset) {
}
void DWARFCallFrameInfo::GetCFIData() {
- if (m_cfi_data_initialized == false) {
+ if (!m_cfi_data_initialized) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
if (log)
m_objfile.GetModule()->LogMessage(log, "Reading EH frame info");
@@ -423,15 +423,14 @@ void DWARFCallFrameInfo::GetFDEIndex() {
m_objfile.GetFileSpec().GetFilename().AsCString(""));
bool clear_address_zeroth_bit = false;
- ArchSpec arch;
- if (m_objfile.GetArchitecture(arch)) {
+ if (ArchSpec arch = m_objfile.GetArchitecture()) {
if (arch.GetTriple().getArch() == llvm::Triple::arm ||
arch.GetTriple().getArch() == llvm::Triple::thumb)
clear_address_zeroth_bit = true;
}
lldb::offset_t offset = 0;
- if (m_cfi_data_initialized == false)
+ if (!m_cfi_data_initialized)
GetCFIData();
while (m_cfi_data.ValidOffsetForDataOfSize(offset, 8)) {
const dw_offset_t current_entry = offset;
@@ -533,7 +532,7 @@ bool DWARFCallFrameInfo::FDEToUnwindPlan(dw_offset_t dwarf_offset,
if (m_section_sp.get() == nullptr || m_section_sp->IsEncrypted())
return false;
- if (m_cfi_data_initialized == false)
+ if (!m_cfi_data_initialized)
GetCFIData();
uint32_t length = m_cfi_data.GetU32(&offset);
diff --git a/source/Symbol/FuncUnwinders.cpp b/source/Symbol/FuncUnwinders.cpp
index 2384d35e3d36..35ce72f32b61 100644
--- a/source/Symbol/FuncUnwinders.cpp
+++ b/source/Symbol/FuncUnwinders.cpp
@@ -255,7 +255,7 @@ UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
int current_offset) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
if (m_unwind_plan_assembly_sp.get() || m_tried_unwind_plan_assembly ||
- m_unwind_table.GetAllowAssemblyEmulationUnwindPlans() == false) {
+ !m_unwind_table.GetAllowAssemblyEmulationUnwindPlans()) {
return m_unwind_plan_assembly_sp;
}
@@ -443,8 +443,7 @@ const Address &FuncUnwinders::GetFunctionStartAddress() const {
lldb::UnwindAssemblySP
FuncUnwinders::GetUnwindAssemblyProfiler(Target &target) {
UnwindAssemblySP assembly_profiler_sp;
- ArchSpec arch;
- if (m_unwind_table.GetArchitecture(arch)) {
+ if (ArchSpec arch = m_unwind_table.GetArchitecture()) {
arch.MergeFrom(target.GetArchitecture());
assembly_profiler_sp = UnwindAssembly::FindPlugin(arch);
}
diff --git a/source/Symbol/Function.cpp b/source/Symbol/Function.cpp
index f642c186a19f..f792a5c5213e 100644
--- a/source/Symbol/Function.cpp
+++ b/source/Symbol/Function.cpp
@@ -10,6 +10,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -18,6 +19,7 @@
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Language.h"
+#include "lldb/Utility/Log.h"
#include "llvm/Support/Casting.h"
using namespace lldb;
@@ -131,6 +133,59 @@ size_t InlineFunctionInfo::MemorySize() const {
//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
+CallEdge::CallEdge(const char *symbol_name, lldb::addr_t return_pc)
+ : return_pc(return_pc), resolved(false) {
+ lazy_callee.symbol_name = symbol_name;
+}
+
+void CallEdge::ParseSymbolFileAndResolve(ModuleList &images) {
+ if (resolved)
+ return;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ LLDB_LOG(log, "CallEdge: Lazily parsing the call graph for {0}",
+ lazy_callee.symbol_name);
+
+ auto resolve_lazy_callee = [&]() -> Function * {
+ ConstString callee_name{lazy_callee.symbol_name};
+ SymbolContextList sc_list;
+ size_t num_matches =
+ images.FindFunctionSymbols(callee_name, eFunctionNameTypeAuto, sc_list);
+ if (num_matches == 0 || !sc_list[0].symbol) {
+ LLDB_LOG(log, "CallEdge: Found no symbols for {0}, cannot resolve it",
+ callee_name);
+ return nullptr;
+ }
+ Address callee_addr = sc_list[0].symbol->GetAddress();
+ if (!callee_addr.IsValid()) {
+ LLDB_LOG(log, "CallEdge: Invalid symbol address");
+ return nullptr;
+ }
+ Function *f = callee_addr.CalculateSymbolContextFunction();
+ if (!f) {
+ LLDB_LOG(log, "CallEdge: Could not find complete function");
+ return nullptr;
+ }
+ return f;
+ };
+ lazy_callee.def = resolve_lazy_callee();
+ resolved = true;
+}
+
+Function *CallEdge::GetCallee(ModuleList &images) {
+ ParseSymbolFileAndResolve(images);
+ return lazy_callee.def;
+}
+
+lldb::addr_t CallEdge::GetReturnPCAddress(Function &caller,
+ Target &target) const {
+ const Address &base = caller.GetAddressRange().GetBaseAddress();
+ return base.GetLoadAddress(&target) + return_pc;
+}
+
+//----------------------------------------------------------------------
+//
+//----------------------------------------------------------------------
Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
lldb::user_id_t type_uid, const Mangled &mangled, Type *type,
const AddressRange &range)
@@ -141,17 +196,6 @@ Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
assert(comp_unit != nullptr);
}
-Function::Function(CompileUnit *comp_unit, lldb::user_id_t func_uid,
- lldb::user_id_t type_uid, const char *mangled, Type *type,
- const AddressRange &range)
- : UserID(func_uid), m_comp_unit(comp_unit), m_type_uid(type_uid),
- m_type(type), m_mangled(ConstString(mangled), true), m_block(func_uid),
- m_range(range), m_frame_base(nullptr), m_flags(),
- m_prologue_byte_size(0) {
- m_block.SetParentScope(this);
- assert(comp_unit != nullptr);
-}
-
Function::~Function() {}
void Function::GetStartLineSourceInfo(FileSpec &source_file,
@@ -203,16 +247,53 @@ void Function::GetEndLineSourceInfo(FileSpec &source_file, uint32_t &line_no) {
}
}
+llvm::MutableArrayRef<CallEdge> Function::GetCallEdges() {
+ if (m_call_edges_resolved)
+ return m_call_edges;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ LLDB_LOG(log, "GetCallEdges: Attempting to parse call site info for {0}",
+ GetDisplayName());
+
+ m_call_edges_resolved = true;
+
+ // Find the SymbolFile which provided this function's definition.
+ Block &block = GetBlock(/*can_create*/true);
+ SymbolFile *sym_file = block.GetSymbolFile();
+ if (!sym_file)
+ return llvm::None;
+
+ // Lazily read call site information from the SymbolFile.
+ m_call_edges = sym_file->ParseCallEdgesInFunction(GetID());
+
+ // Sort the call edges to speed up return_pc lookups.
+ llvm::sort(m_call_edges.begin(), m_call_edges.end(),
+ [](const CallEdge &LHS, const CallEdge &RHS) {
+ return LHS.GetUnresolvedReturnPCAddress() <
+ RHS.GetUnresolvedReturnPCAddress();
+ });
+
+ return m_call_edges;
+}
+
+llvm::MutableArrayRef<CallEdge> Function::GetTailCallingEdges() {
+ // Call edges are sorted by return PC, and tail calling edges have invalid
+ // return PCs. Find them at the end of the list.
+ return GetCallEdges().drop_until([](const CallEdge &edge) {
+ return edge.GetUnresolvedReturnPCAddress() == LLDB_INVALID_ADDRESS;
+ });
+}
+
Block &Function::GetBlock(bool can_create) {
if (!m_block.BlockInfoHasBeenParsed() && can_create) {
- SymbolContext sc;
- CalculateSymbolContext(&sc);
- if (sc.module_sp) {
- sc.module_sp->GetSymbolVendor()->ParseFunctionBlocks(sc);
+ ModuleSP module_sp = CalculateSymbolContextModule();
+ if (module_sp) {
+ module_sp->GetSymbolVendor()->ParseBlocksRecursive(*this);
} else {
- Host::SystemLog(Host::eSystemLogError, "error: unable to find module "
- "shared pointer for function '%s' "
- "in %s\n",
+ Host::SystemLog(Host::eSystemLogError,
+ "error: unable to find module "
+ "shared pointer for function '%s' "
+ "in %s\n",
GetName().GetCString(), m_comp_unit->GetPath().c_str());
}
m_block.SetBlockInfoHasBeenParsed(true, true);
diff --git a/source/Symbol/GoASTContext.cpp b/source/Symbol/GoASTContext.cpp
deleted file mode 100644
index da5c82b2cb55..000000000000
--- a/source/Symbol/GoASTContext.cpp
+++ /dev/null
@@ -1,1444 +0,0 @@
-//===-- GoASTContext.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <mutex>
-#include <utility>
-#include <vector>
-
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/UniqueCStringMap.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Target.h"
-
-#include "llvm/Support/Threading.h"
-
-#include "Plugins/ExpressionParser/Go/GoUserExpression.h"
-#include "Plugins/SymbolFile/DWARF/DWARFASTParserGo.h"
-
-using namespace lldb;
-
-namespace lldb_private {
-class GoArray;
-class GoFunction;
-class GoStruct;
-
-class GoType {
-public:
- enum {
- KIND_BOOL = 1,
- KIND_INT = 2,
- KIND_INT8 = 3,
- KIND_INT16 = 4,
- KIND_INT32 = 5,
- KIND_INT64 = 6,
- KIND_UINT = 7,
- KIND_UINT8 = 8,
- KIND_UINT16 = 9,
- KIND_UINT32 = 10,
- KIND_UINT64 = 11,
- KIND_UINTPTR = 12,
- KIND_FLOAT32 = 13,
- KIND_FLOAT64 = 14,
- KIND_COMPLEX64 = 15,
- KIND_COMPLEX128 = 16,
- KIND_ARRAY = 17,
- KIND_CHAN = 18,
- KIND_FUNC = 19,
- KIND_INTERFACE = 20,
- KIND_MAP = 21,
- KIND_PTR = 22,
- KIND_SLICE = 23,
- KIND_STRING = 24,
- KIND_STRUCT = 25,
- KIND_UNSAFEPOINTER = 26,
- KIND_LLDB_VOID, // Extension for LLDB, not used by go runtime.
- KIND_MASK = (1 << 5) - 1,
- KIND_DIRECT_IFACE = 1 << 5
- };
- GoType(int kind, const ConstString &name)
- : m_kind(kind & KIND_MASK), m_name(name) {
- if (m_kind == KIND_FUNC)
- m_kind = KIND_FUNC;
- }
- virtual ~GoType() {}
-
- int GetGoKind() const { return m_kind; }
- const ConstString &GetName() const { return m_name; }
- virtual CompilerType GetElementType() const { return CompilerType(); }
-
- bool IsTypedef() const {
- switch (m_kind) {
- case KIND_CHAN:
- case KIND_MAP:
- case KIND_INTERFACE:
- return true;
- default:
- return false;
- }
- }
-
- GoArray *GetArray();
- GoFunction *GetFunction();
- GoStruct *GetStruct();
-
-private:
- int m_kind;
- ConstString m_name;
- GoType(const GoType &) = delete;
- const GoType &operator=(const GoType &) = delete;
-};
-
-class GoElem : public GoType {
-public:
- GoElem(int kind, const ConstString &name, const CompilerType &elem)
- : GoType(kind, name), m_elem(elem) {}
- virtual CompilerType GetElementType() const { return m_elem; }
-
-private:
- // TODO: should we store this differently?
- CompilerType m_elem;
-
- GoElem(const GoElem &) = delete;
- const GoElem &operator=(const GoElem &) = delete;
-};
-
-class GoArray : public GoElem {
-public:
- GoArray(const ConstString &name, uint64_t length, const CompilerType &elem)
- : GoElem(KIND_ARRAY, name, elem), m_length(length) {}
-
- uint64_t GetLength() const { return m_length; }
-
-private:
- uint64_t m_length;
- GoArray(const GoArray &) = delete;
- const GoArray &operator=(const GoArray &) = delete;
-};
-
-class GoFunction : public GoType {
-public:
- GoFunction(const ConstString &name, bool is_variadic)
- : GoType(KIND_FUNC, name), m_is_variadic(is_variadic) {}
-
- bool IsVariadic() const { return m_is_variadic; }
-
-private:
- bool m_is_variadic;
- GoFunction(const GoFunction &) = delete;
- const GoFunction &operator=(const GoFunction &) = delete;
-};
-
-class GoStruct : public GoType {
-public:
- struct Field {
- Field(const ConstString &name, const CompilerType &type, uint64_t offset)
- : m_name(name), m_type(type), m_byte_offset(offset) {}
- ConstString m_name;
- CompilerType m_type;
- uint64_t m_byte_offset;
- };
-
- GoStruct(int kind, const ConstString &name, int64_t byte_size)
- : GoType(kind == 0 ? KIND_STRUCT : kind, name), m_is_complete(false),
- m_byte_size(byte_size) {}
-
- uint32_t GetNumFields() const { return m_fields.size(); }
-
- const Field *GetField(uint32_t i) const {
- if (i < m_fields.size())
- return &m_fields[i];
- return nullptr;
- }
-
- void AddField(const ConstString &name, const CompilerType &type,
- uint64_t offset) {
- m_fields.push_back(Field(name, type, offset));
- }
-
- bool IsComplete() const { return m_is_complete; }
-
- void SetComplete() { m_is_complete = true; }
-
- int64_t GetByteSize() const { return m_byte_size; }
-
-private:
- bool m_is_complete;
- int64_t m_byte_size;
- std::vector<Field> m_fields;
-
- GoStruct(const GoStruct &) = delete;
- const GoStruct &operator=(const GoStruct &) = delete;
-};
-
-GoArray *GoType::GetArray() {
- if (m_kind == KIND_ARRAY) {
- return static_cast<GoArray *>(this);
- }
- return nullptr;
-}
-
-GoFunction *GoType::GetFunction() {
- if (m_kind == KIND_FUNC) {
- return static_cast<GoFunction *>(this);
- }
- return nullptr;
-}
-
-GoStruct *GoType::GetStruct() {
- switch (m_kind) {
- case KIND_STRING:
- case KIND_STRUCT:
- case KIND_SLICE:
- return static_cast<GoStruct *>(this);
- }
- return nullptr;
-}
-} // namespace lldb_private
-using namespace lldb_private;
-
-GoASTContext::GoASTContext()
- : TypeSystem(eKindGo), m_pointer_byte_size(0), m_int_byte_size(0),
- m_types(new TypeMap) {}
-GoASTContext::~GoASTContext() {}
-
-//------------------------------------------------------------------
-// PluginInterface functions
-//------------------------------------------------------------------
-
-ConstString GoASTContext::GetPluginNameStatic() { return ConstString("go"); }
-
-ConstString GoASTContext::GetPluginName() {
- return GoASTContext::GetPluginNameStatic();
-}
-
-uint32_t GoASTContext::GetPluginVersion() { return 1; }
-
-lldb::TypeSystemSP GoASTContext::CreateInstance(lldb::LanguageType language,
- Module *module,
- Target *target) {
- if (language == eLanguageTypeGo) {
- ArchSpec arch;
- std::shared_ptr<GoASTContext> go_ast_sp;
- if (module) {
- arch = module->GetArchitecture();
- go_ast_sp = std::shared_ptr<GoASTContext>(new GoASTContext);
- } else if (target) {
- arch = target->GetArchitecture();
- go_ast_sp = std::shared_ptr<GoASTContextForExpr>(
- new GoASTContextForExpr(target->shared_from_this()));
- }
-
- if (arch.IsValid()) {
- go_ast_sp->SetAddressByteSize(arch.GetAddressByteSize());
- return go_ast_sp;
- }
- }
- return lldb::TypeSystemSP();
-}
-
-void GoASTContext::EnumerateSupportedLanguages(
- std::set<lldb::LanguageType> &languages_for_types,
- std::set<lldb::LanguageType> &languages_for_expressions) {
- static std::vector<lldb::LanguageType> s_supported_languages_for_types(
- {lldb::eLanguageTypeGo});
-
- static std::vector<lldb::LanguageType> s_supported_languages_for_expressions(
- {});
-
- languages_for_types.insert(s_supported_languages_for_types.begin(),
- s_supported_languages_for_types.end());
- languages_for_expressions.insert(
- s_supported_languages_for_expressions.begin(),
- s_supported_languages_for_expressions.end());
-}
-
-void GoASTContext::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in",
- CreateInstance, EnumerateSupportedLanguages);
-}
-
-void GoASTContext::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-//----------------------------------------------------------------------
-// Tests
-//----------------------------------------------------------------------
-
-bool GoASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size,
- bool *is_incomplete) {
- if (element_type)
- element_type->Clear();
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = false;
- GoArray *array = static_cast<GoType *>(type)->GetArray();
- if (array) {
- if (size)
- *size = array->GetLength();
- if (element_type)
- *element_type = array->GetElementType();
- return true;
- }
- return false;
-}
-
-bool GoASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) {
- if (element_type)
- element_type->Clear();
- if (size)
- *size = 0;
- return false;
-}
-
-bool GoASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
- int kind = static_cast<GoType *>(type)->GetGoKind();
- if (kind < GoType::KIND_ARRAY)
- return false;
- if (kind == GoType::KIND_PTR)
- return false;
- if (kind == GoType::KIND_CHAN)
- return false;
- if (kind == GoType::KIND_MAP)
- return false;
- if (kind == GoType::KIND_STRING)
- return false;
- if (kind == GoType::KIND_UNSAFEPOINTER)
- return false;
- return true;
-}
-
-bool GoASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool GoASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
- // Go's DWARF doesn't distinguish between rune and int32.
- return false;
-}
-
-bool GoASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- GoType *t = static_cast<GoType *>(type);
- if (GoStruct *s = t->GetStruct())
- return s->IsComplete();
- if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR)
- return t->GetElementType().IsCompleteType();
- return true;
-}
-
-bool GoASTContext::IsConst(lldb::opaque_compiler_type_t type) { return false; }
-
-bool GoASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) {
- return false;
-}
-
-bool GoASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
- return type != nullptr;
-}
-
-bool GoASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
- uint32_t &count, bool &is_complex) {
- int kind = static_cast<GoType *>(type)->GetGoKind();
- if (kind >= GoType::KIND_FLOAT32 && kind <= GoType::KIND_COMPLEX128) {
- if (kind >= GoType::KIND_COMPLEX64) {
- is_complex = true;
- count = 2;
- } else {
- is_complex = false;
- count = 1;
- }
- return true;
- }
- count = 0;
- is_complex = false;
- return false;
-}
-
-bool GoASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr) {
- GoFunction *func = static_cast<GoType *>(type)->GetFunction();
- if (func) {
- if (is_variadic_ptr)
- *is_variadic_ptr = func->IsVariadic();
- return true;
- }
- if (is_variadic_ptr)
- *is_variadic_ptr = false;
- return false;
-}
-
-uint32_t GoASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) {
- return false;
-}
-
-size_t
-GoASTContext::GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-CompilerType
-GoASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) {
- return CompilerType();
-}
-
-bool GoASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
- return IsFunctionType(type);
-}
-
-bool GoASTContext::IsBlockPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) {
- return false;
-}
-
-bool GoASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) {
- is_signed = false;
- // TODO: Is bool an integer?
- if (type) {
- int kind = static_cast<GoType *>(type)->GetGoKind();
- if (kind <= GoType::KIND_UINTPTR) {
- is_signed = (kind != GoType::KIND_BOOL) & (kind <= GoType::KIND_INT64);
- return true;
- }
- }
- return false;
-}
-
-bool GoASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool GoASTContext::IsPossibleDynamicType(
- lldb::opaque_compiler_type_t type,
- CompilerType *target_type, // Can pass NULL
- bool check_cplusplus, bool check_objc) {
- if (target_type)
- target_type->Clear();
- if (type)
- return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_INTERFACE;
- return false;
-}
-
-bool GoASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool GoASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type) {
- if (!type)
- return false;
- GoType *t = static_cast<GoType *>(type);
- if (pointee_type) {
- *pointee_type = t->GetElementType();
- }
- switch (t->GetGoKind()) {
- case GoType::KIND_PTR:
- case GoType::KIND_UNSAFEPOINTER:
- case GoType::KIND_CHAN:
- case GoType::KIND_MAP:
- // TODO: is function a pointer?
- return true;
- default:
- return false;
- }
-}
-
-bool GoASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type) {
- return IsPointerType(type, pointee_type);
-}
-
-bool GoASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type,
- bool *is_rvalue) {
- return false;
-}
-
-bool GoASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
- return !IsAggregateType(type);
-}
-
-bool GoASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
- if (type)
- return static_cast<GoType *>(type)->IsTypedef();
- return false;
-}
-
-bool GoASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- return static_cast<GoType *>(type)->GetGoKind() == GoType::KIND_LLDB_VOID;
-}
-
-bool GoASTContext::SupportsLanguage(lldb::LanguageType language) {
- return language == eLanguageTypeGo;
-}
-
-//----------------------------------------------------------------------
-// Type Completion
-//----------------------------------------------------------------------
-
-bool GoASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return false;
- GoType *t = static_cast<GoType *>(type);
- if (t->IsTypedef() || t->GetGoKind() == GoType::KIND_PTR || t->GetArray())
- return t->GetElementType().GetCompleteType();
- if (GoStruct *s = t->GetStruct()) {
- if (s->IsComplete())
- return true;
- CompilerType compiler_type(this, s);
- SymbolFile *symbols = GetSymbolFile();
- return symbols && symbols->CompleteType(compiler_type);
- }
- return true;
-}
-
-//----------------------------------------------------------------------
-// AST related queries
-//----------------------------------------------------------------------
-
-uint32_t GoASTContext::GetPointerByteSize() { return m_pointer_byte_size; }
-
-//----------------------------------------------------------------------
-// Accessors
-//----------------------------------------------------------------------
-
-ConstString GoASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
- if (type)
- return static_cast<GoType *>(type)->GetName();
- return ConstString();
-}
-
-uint32_t
-GoASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_compiler_type) {
- if (pointee_or_element_compiler_type)
- pointee_or_element_compiler_type->Clear();
- if (!type)
- return 0;
- GoType *t = static_cast<GoType *>(type);
- if (pointee_or_element_compiler_type)
- *pointee_or_element_compiler_type = t->GetElementType();
- int kind = t->GetGoKind();
- if (kind == GoType::KIND_ARRAY)
- return eTypeHasChildren | eTypeIsArray;
- if (kind < GoType::KIND_ARRAY) {
- uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue;
- if (kind < GoType::KIND_FLOAT32) {
- builtin_type_flags |= eTypeIsInteger | eTypeIsScalar;
- if (kind >= GoType::KIND_INT && kind <= GoType::KIND_INT64)
- builtin_type_flags |= eTypeIsSigned;
- } else {
- builtin_type_flags |= eTypeIsFloat;
- if (kind < GoType::KIND_COMPLEX64)
- builtin_type_flags |= eTypeIsComplex;
- else
- builtin_type_flags |= eTypeIsScalar;
- }
- return builtin_type_flags;
- }
- if (kind == GoType::KIND_STRING)
- return eTypeHasValue | eTypeIsBuiltIn;
- if (kind == GoType::KIND_FUNC)
- return eTypeIsFuncPrototype | eTypeHasValue;
- if (IsPointerType(type))
- return eTypeIsPointer | eTypeHasValue | eTypeHasChildren;
- if (kind == GoType::KIND_LLDB_VOID)
- return 0;
- return eTypeHasChildren | eTypeIsStructUnion;
-}
-
-lldb::TypeClass GoASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
- if (!type)
- return eTypeClassInvalid;
- int kind = static_cast<GoType *>(type)->GetGoKind();
- if (kind == GoType::KIND_FUNC)
- return eTypeClassFunction;
- if (IsPointerType(type))
- return eTypeClassPointer;
- if (kind < GoType::KIND_COMPLEX64)
- return eTypeClassBuiltin;
- if (kind <= GoType::KIND_COMPLEX128)
- return eTypeClassComplexFloat;
- if (kind == GoType::KIND_LLDB_VOID)
- return eTypeClassInvalid;
- return eTypeClassStruct;
-}
-
-lldb::BasicType
-GoASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
- ConstString name = GetTypeName(type);
- if (name) {
- typedef UniqueCStringMap<lldb::BasicType> TypeNameToBasicTypeMap;
- static TypeNameToBasicTypeMap g_type_map;
- static llvm::once_flag g_once_flag;
- llvm::call_once(g_once_flag, []() {
- // "void"
- g_type_map.Append(ConstString("void"), eBasicTypeVoid);
- // "int"
- g_type_map.Append(ConstString("int"), eBasicTypeInt);
- g_type_map.Append(ConstString("uint"), eBasicTypeUnsignedInt);
-
- // Miscellaneous
- g_type_map.Append(ConstString("bool"), eBasicTypeBool);
-
- // Others. Should these map to C types?
- g_type_map.Append(ConstString("byte"), eBasicTypeOther);
- g_type_map.Append(ConstString("uint8"), eBasicTypeOther);
- g_type_map.Append(ConstString("uint16"), eBasicTypeOther);
- g_type_map.Append(ConstString("uint32"), eBasicTypeOther);
- g_type_map.Append(ConstString("uint64"), eBasicTypeOther);
- g_type_map.Append(ConstString("int8"), eBasicTypeOther);
- g_type_map.Append(ConstString("int16"), eBasicTypeOther);
- g_type_map.Append(ConstString("int32"), eBasicTypeOther);
- g_type_map.Append(ConstString("int64"), eBasicTypeOther);
- g_type_map.Append(ConstString("float32"), eBasicTypeOther);
- g_type_map.Append(ConstString("float64"), eBasicTypeOther);
- g_type_map.Append(ConstString("uintptr"), eBasicTypeOther);
-
- g_type_map.Sort();
- });
-
- return g_type_map.Find(name, eBasicTypeInvalid);
- }
- return eBasicTypeInvalid;
-}
-
-lldb::LanguageType
-GoASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
- return lldb::eLanguageTypeGo;
-}
-
-unsigned GoASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-//----------------------------------------------------------------------
-// Creating related types
-//----------------------------------------------------------------------
-
-CompilerType
-GoASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride) {
- GoArray *array = static_cast<GoType *>(type)->GetArray();
- if (array) {
- if (stride) {
- *stride = array->GetElementType().GetByteSize(nullptr);
- }
- return array->GetElementType();
- }
- return CompilerType();
-}
-
-CompilerType GoASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
- GoType *t = static_cast<GoType *>(type);
- if (t->IsTypedef())
- return t->GetElementType();
- return CompilerType(this, type);
-}
-
-CompilerType
-GoASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-// Returns -1 if this isn't a function of if the function doesn't have a
-// prototype Returns a value >= 0 if there is a prototype.
-int GoASTContext::GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) {
- return GetNumberOfFunctionArguments(type);
-}
-
-CompilerType
-GoASTContext::GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) {
- return GetFunctionArgumentAtIndex(type, idx);
-}
-
-CompilerType
-GoASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
- CompilerType result;
- if (type) {
- GoType *t = static_cast<GoType *>(type);
- if (t->GetGoKind() == GoType::KIND_FUNC)
- result = t->GetElementType();
- }
- return result;
-}
-
-size_t GoASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-TypeMemberFunctionImpl
-GoASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) {
- return TypeMemberFunctionImpl();
-}
-
-CompilerType
-GoASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-CompilerType GoASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return CompilerType();
- return static_cast<GoType *>(type)->GetElementType();
-}
-
-CompilerType GoASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
- if (!type)
- return CompilerType();
- ConstString type_name = GetTypeName(type);
- ConstString pointer_name(std::string("*") + type_name.GetCString());
- GoType *pointer = (*m_types)[pointer_name].get();
- if (pointer == nullptr) {
- pointer =
- new GoElem(GoType::KIND_PTR, pointer_name, CompilerType(this, type));
- (*m_types)[pointer_name].reset(pointer);
- }
- return CompilerType(this, pointer);
-}
-
-// If the current object represents a typedef type, get the underlying type
-CompilerType GoASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
- if (IsTypedefType(type))
- return static_cast<GoType *>(type)->GetElementType();
- return CompilerType();
-}
-
-//----------------------------------------------------------------------
-// Create related types using the current type's AST
-//----------------------------------------------------------------------
-CompilerType GoASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
- return CompilerType();
-}
-
-CompilerType
-GoASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
- size_t bit_size) {
- return CompilerType();
-}
-
-//----------------------------------------------------------------------
-// Exploring the type
-//----------------------------------------------------------------------
-
-uint64_t GoASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) {
- if (!type)
- return 0;
- if (!GetCompleteType(type))
- return 0;
- GoType *t = static_cast<GoType *>(type);
- GoArray *array = nullptr;
- switch (t->GetGoKind()) {
- case GoType::KIND_BOOL:
- case GoType::KIND_INT8:
- case GoType::KIND_UINT8:
- return 8;
- case GoType::KIND_INT16:
- case GoType::KIND_UINT16:
- return 16;
- case GoType::KIND_INT32:
- case GoType::KIND_UINT32:
- case GoType::KIND_FLOAT32:
- return 32;
- case GoType::KIND_INT64:
- case GoType::KIND_UINT64:
- case GoType::KIND_FLOAT64:
- case GoType::KIND_COMPLEX64:
- return 64;
- case GoType::KIND_COMPLEX128:
- return 128;
- case GoType::KIND_INT:
- case GoType::KIND_UINT:
- return m_int_byte_size * 8;
- case GoType::KIND_UINTPTR:
- case GoType::KIND_FUNC: // I assume this is a pointer?
- case GoType::KIND_CHAN:
- case GoType::KIND_PTR:
- case GoType::KIND_UNSAFEPOINTER:
- case GoType::KIND_MAP:
- return m_pointer_byte_size * 8;
- case GoType::KIND_ARRAY:
- array = t->GetArray();
- return array->GetLength() * array->GetElementType().GetBitSize(exe_scope);
- case GoType::KIND_INTERFACE:
- return t->GetElementType().GetBitSize(exe_scope);
- case GoType::KIND_SLICE:
- case GoType::KIND_STRING:
- case GoType::KIND_STRUCT:
- return t->GetStruct()->GetByteSize() * 8;
- default:
- assert(false);
- }
- return 0;
-}
-
-lldb::Encoding GoASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) {
- count = 1;
- bool is_signed;
- if (IsIntegerType(type, is_signed))
- return is_signed ? lldb::eEncodingSint : eEncodingUint;
- bool is_complex;
- uint32_t complex_count;
- if (IsFloatingPointType(type, complex_count, is_complex)) {
- count = complex_count;
- return eEncodingIEEE754;
- }
- if (IsPointerType(type))
- return eEncodingUint;
- return eEncodingInvalid;
-}
-
-lldb::Format GoASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
- if (!type)
- return eFormatDefault;
- switch (static_cast<GoType *>(type)->GetGoKind()) {
- case GoType::KIND_BOOL:
- return eFormatBoolean;
- case GoType::KIND_INT:
- case GoType::KIND_INT8:
- case GoType::KIND_INT16:
- case GoType::KIND_INT32:
- case GoType::KIND_INT64:
- return eFormatDecimal;
- case GoType::KIND_UINT:
- case GoType::KIND_UINT8:
- case GoType::KIND_UINT16:
- case GoType::KIND_UINT32:
- case GoType::KIND_UINT64:
- return eFormatUnsigned;
- case GoType::KIND_FLOAT32:
- case GoType::KIND_FLOAT64:
- return eFormatFloat;
- case GoType::KIND_COMPLEX64:
- case GoType::KIND_COMPLEX128:
- return eFormatComplexFloat;
- case GoType::KIND_UINTPTR:
- case GoType::KIND_CHAN:
- case GoType::KIND_PTR:
- case GoType::KIND_MAP:
- case GoType::KIND_UNSAFEPOINTER:
- return eFormatHex;
- case GoType::KIND_STRING:
- return eFormatCString;
- case GoType::KIND_ARRAY:
- case GoType::KIND_INTERFACE:
- case GoType::KIND_SLICE:
- case GoType::KIND_STRUCT:
- default:
- // Don't know how to display this.
- return eFormatBytes;
- }
-}
-
-size_t GoASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-uint32_t GoASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) {
- if (!type || !GetCompleteType(type))
- return 0;
- GoType *t = static_cast<GoType *>(type);
- if (t->GetGoKind() == GoType::KIND_PTR) {
- CompilerType elem = t->GetElementType();
- if (elem.IsAggregateType())
- return elem.GetNumChildren(omit_empty_base_classes);
- return 1;
- } else if (GoArray *array = t->GetArray()) {
- return array->GetLength();
- } else if (t->IsTypedef()) {
- return t->GetElementType().GetNumChildren(omit_empty_base_classes);
- }
-
- return GetNumFields(type);
-}
-
-uint32_t GoASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
- if (!type || !GetCompleteType(type))
- return 0;
- GoType *t = static_cast<GoType *>(type);
- if (t->IsTypedef())
- return t->GetElementType().GetNumFields();
- GoStruct *s = t->GetStruct();
- if (s)
- return s->GetNumFields();
- return 0;
-}
-
-CompilerType GoASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx, std::string &name,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- if (bitfield_bit_size_ptr)
- *bitfield_bit_size_ptr = 0;
- if (is_bitfield_ptr)
- *is_bitfield_ptr = false;
-
- if (!type || !GetCompleteType(type))
- return CompilerType();
-
- GoType *t = static_cast<GoType *>(type);
- if (t->IsTypedef())
- return t->GetElementType().GetFieldAtIndex(
- idx, name, bit_offset_ptr, bitfield_bit_size_ptr, is_bitfield_ptr);
-
- GoStruct *s = t->GetStruct();
- if (s) {
- const auto *field = s->GetField(idx);
- if (field) {
- name = field->m_name.GetStringRef();
- if (bit_offset_ptr)
- *bit_offset_ptr = field->m_byte_offset * 8;
- return field->m_type;
- }
- }
- return CompilerType();
-}
-
-CompilerType GoASTContext::GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
- bool transparent_pointers, bool omit_empty_base_classes,
- bool ignore_array_bounds, std::string &child_name,
- uint32_t &child_byte_size, int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class, bool &child_is_deref_of_parent,
- ValueObject *valobj, uint64_t &language_flags) {
- child_name.clear();
- child_byte_size = 0;
- child_byte_offset = 0;
- child_bitfield_bit_size = 0;
- child_bitfield_bit_offset = 0;
- child_is_base_class = false;
- child_is_deref_of_parent = false;
- language_flags = 0;
-
- if (!type || !GetCompleteType(type))
- return CompilerType();
-
- GoType *t = static_cast<GoType *>(type);
- if (t->GetStruct()) {
- uint64_t bit_offset;
- CompilerType ret =
- GetFieldAtIndex(type, idx, child_name, &bit_offset, nullptr, nullptr);
- child_byte_size = ret.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
- child_byte_offset = bit_offset / 8;
- return ret;
- } else if (t->GetGoKind() == GoType::KIND_PTR) {
- CompilerType pointee = t->GetElementType();
- if (!pointee.IsValid() || pointee.IsVoidType())
- return CompilerType();
- if (transparent_pointers && pointee.IsAggregateType()) {
- bool tmp_child_is_deref_of_parent = false;
- return pointee.GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset,
- child_is_base_class, tmp_child_is_deref_of_parent, valobj,
- language_flags);
- } else {
- child_is_deref_of_parent = true;
- const char *parent_name = valobj ? valobj->GetName().GetCString() : NULL;
- if (parent_name) {
- child_name.assign(1, '*');
- child_name += parent_name;
- }
-
- // We have a pointer to an simple type
- if (idx == 0 && pointee.GetCompleteType()) {
- child_byte_size = pointee.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = 0;
- return pointee;
- }
- }
- } else if (GoArray *a = t->GetArray()) {
- if (ignore_array_bounds || idx < a->GetLength()) {
- CompilerType element_type = a->GetElementType();
- if (element_type.GetCompleteType()) {
- char element_name[64];
- ::snprintf(element_name, sizeof(element_name), "[%zu]", idx);
- child_name.assign(element_name);
- child_byte_size = element_type.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
- child_byte_offset = (int32_t)idx * (int32_t)child_byte_size;
- return element_type;
- }
- }
- } else if (t->IsTypedef()) {
- return t->GetElementType().GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
- child_is_deref_of_parent, valobj, language_flags);
- }
- return CompilerType();
-}
-
-// Lookup a child given a name. This function will match base class names and
-// member member names in "clang_type" only, not descendants.
-uint32_t
-GoASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) {
- if (!type || !GetCompleteType(type))
- return UINT_MAX;
-
- GoType *t = static_cast<GoType *>(type);
- GoStruct *s = t->GetStruct();
- if (s) {
- for (uint32_t i = 0; i < s->GetNumFields(); ++i) {
- const GoStruct::Field *f = s->GetField(i);
- if (f->m_name.GetStringRef() == name)
- return i;
- }
- } else if (t->GetGoKind() == GoType::KIND_PTR || t->IsTypedef()) {
- return t->GetElementType().GetIndexOfChildWithName(name,
- omit_empty_base_classes);
- }
- return UINT_MAX;
-}
-
-// Lookup a child member given a name. This function will match member names
-// only and will descend into "clang_type" children in search for the first
-// member in this class, or any base class that matches "name".
-// TODO: Return all matches for a given name by returning a
-// vector<vector<uint32_t>>
-// so we catch all names that match a given child name, not just the first.
-size_t GoASTContext::GetIndexOfChildMemberWithName(
- lldb::opaque_compiler_type_t type, const char *name,
- bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
- uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes);
- if (index == UINT_MAX)
- return 0;
- child_indexes.push_back(index);
- return 1;
-}
-
-// Converts "s" to a floating point value and place resulting floating point
-// bytes in the "dst" buffer.
-size_t
-GoASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
- const char *s, uint8_t *dst,
- size_t dst_size) {
- assert(false);
- return 0;
-}
-//----------------------------------------------------------------------
-// Dumping types
-//----------------------------------------------------------------------
-#define DEPTH_INCREMENT 2
-
-void GoASTContext::DumpValue(lldb::opaque_compiler_type_t type,
- ExecutionContext *exe_ctx, Stream *s,
- lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_byte_offset,
- size_t data_byte_size, uint32_t bitfield_bit_size,
- uint32_t bitfield_bit_offset, bool show_types,
- bool show_summary, bool verbose, uint32_t depth) {
- if (IsTypedefType(type))
- type = GetTypedefedType(type).GetOpaqueQualType();
- if (!type)
- return;
- GoType *t = static_cast<GoType *>(type);
-
- if (GoStruct *st = t->GetStruct()) {
- if (GetCompleteType(type)) {
- uint32_t field_idx = 0;
- for (auto *field = st->GetField(field_idx); field != nullptr;
- field_idx++) {
- // Print the starting squiggly bracket (if this is the first member) or
- // comma (for member 2 and beyond) for the struct/union/class member.
- if (field_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- // Indent
- s->Printf("\n%*s", depth + DEPTH_INCREMENT, "");
-
- // Print the member type if requested
- if (show_types) {
- ConstString field_type_name = field->m_type.GetTypeName();
- s->Printf("(%s) ", field_type_name.AsCString());
- }
- // Print the member name and equal sign
- s->Printf("%s = ", field->m_name.AsCString());
-
- // Dump the value of the member
- CompilerType field_type = field->m_type;
- field_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- field_type
- .GetFormat(), // The format with which to display the member
- data, // Data buffer containing all bytes for this type
- data_byte_offset + field->m_byte_offset, // Offset into "data" where
- // to grab value from
- field->m_type.GetByteSize(
- exe_ctx->GetBestExecutionContextScope()), // Size of this type
- // in bytes
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable
- // types
- show_summary, // Boolean indicating if we should show a summary for
- // the current type
- verbose, // Verbose output?
- depth + DEPTH_INCREMENT); // Scope depth for any types that have
- // children
- }
-
- // Indent the trailing squiggly bracket
- if (field_idx > 0)
- s->Printf("\n%*s}", depth, "");
- }
- }
-
- if (GoArray *a = t->GetArray()) {
- CompilerType element_clang_type = a->GetElementType();
- lldb::Format element_format = element_clang_type.GetFormat();
- uint32_t element_byte_size =
- element_clang_type.GetByteSize(exe_ctx->GetBestExecutionContextScope());
-
- uint64_t element_idx;
- for (element_idx = 0; element_idx < a->GetLength(); ++element_idx) {
- // Print the starting squiggly bracket (if this is the first member) or
- // comman (for member 2 and beyong) for the struct/union/class member.
- if (element_idx == 0)
- s->PutChar('{');
- else
- s->PutChar(',');
-
- // Indent and print the index
- s->Printf("\n%*s[%" PRIu64 "] ", depth + DEPTH_INCREMENT, "",
- element_idx);
-
- // Figure out the field offset within the current struct/union/class type
- uint64_t element_offset = element_idx * element_byte_size;
-
- // Dump the value of the member
- element_clang_type.DumpValue(
- exe_ctx,
- s, // Stream to dump to
- element_format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- data_byte_offset +
- element_offset, // Offset into "data" where to grab value from
- element_byte_size, // Size of this type in bytes
- 0, // Bitfield bit size
- 0, // Bitfield bit offset
- show_types, // Boolean indicating if we should show the variable types
- show_summary, // Boolean indicating if we should show a summary for
- // the current type
- verbose, // Verbose output?
- depth +
- DEPTH_INCREMENT); // Scope depth for any types that have children
- }
-
- // Indent the trailing squiggly bracket
- if (element_idx > 0)
- s->Printf("\n%*s}", depth, "");
- }
-
- if (show_summary)
- DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
-}
-
-bool GoASTContext::DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
- lldb::Format format, const DataExtractor &data,
- lldb::offset_t byte_offset, size_t byte_size,
- uint32_t bitfield_bit_size,
- uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope) {
- if (!type)
- return false;
- if (IsAggregateType(type)) {
- return false;
- } else {
- GoType *t = static_cast<GoType *>(type);
- if (t->IsTypedef()) {
- CompilerType typedef_compiler_type = t->GetElementType();
- if (format == eFormatDefault)
- format = typedef_compiler_type.GetFormat();
- uint64_t typedef_byte_size = typedef_compiler_type.GetByteSize(exe_scope);
-
- return typedef_compiler_type.DumpTypeValue(
- s,
- format, // The format with which to display the element
- data, // Data buffer containing all bytes for this type
- byte_offset, // Offset into "data" where to grab value from
- typedef_byte_size, // Size of this type in bytes
- bitfield_bit_size, // Size in bits of a bitfield value, if zero don't
- // treat as a bitfield
- bitfield_bit_offset, // Offset in bits of a bitfield value if
- // bitfield_bit_size != 0
- exe_scope);
- }
-
- uint32_t item_count = 1;
- // A few formats, we might need to modify our size and count for depending
- // on how we are trying to display the value...
- switch (format) {
- default:
- case eFormatBoolean:
- case eFormatBinary:
- case eFormatComplex:
- case eFormatCString: // NULL terminated C strings
- case eFormatDecimal:
- case eFormatEnum:
- case eFormatHex:
- case eFormatHexUppercase:
- case eFormatFloat:
- case eFormatOctal:
- case eFormatOSType:
- case eFormatUnsigned:
- case eFormatPointer:
- case eFormatVectorOfChar:
- case eFormatVectorOfSInt8:
- case eFormatVectorOfUInt8:
- case eFormatVectorOfSInt16:
- case eFormatVectorOfUInt16:
- case eFormatVectorOfSInt32:
- case eFormatVectorOfUInt32:
- case eFormatVectorOfSInt64:
- case eFormatVectorOfUInt64:
- case eFormatVectorOfFloat32:
- case eFormatVectorOfFloat64:
- case eFormatVectorOfUInt128:
- break;
-
- case eFormatChar:
- case eFormatCharPrintable:
- case eFormatCharArray:
- case eFormatBytes:
- case eFormatBytesWithASCII:
- item_count = byte_size;
- byte_size = 1;
- break;
-
- case eFormatUnicode16:
- item_count = byte_size / 2;
- byte_size = 2;
- break;
-
- case eFormatUnicode32:
- item_count = byte_size / 4;
- byte_size = 4;
- break;
- }
- return DumpDataExtractor(data, s, byte_offset, format, byte_size,
- item_count, UINT32_MAX, LLDB_INVALID_ADDRESS,
- bitfield_bit_size, bitfield_bit_offset, exe_scope);
- }
- return 0;
-}
-
-void GoASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
- ExecutionContext *exe_ctx, Stream *s,
- const DataExtractor &data,
- lldb::offset_t data_offset,
- size_t data_byte_size) {
- if (type && GoType::KIND_STRING == static_cast<GoType *>(type)->GetGoKind()) {
- // TODO(ribrdb): read length and data
- }
-}
-
-void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
- // Dump to stdout
- StreamFile s(stdout, false);
- DumpTypeDescription(type, &s);
-}
-
-void GoASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) {
- if (!type)
- return;
- ConstString name = GetTypeName(type);
- GoType *t = static_cast<GoType *>(type);
-
- if (GoStruct *st = t->GetStruct()) {
- if (GetCompleteType(type)) {
- if (NULL == strchr(name.AsCString(), '{'))
- s->Printf("type %s ", name.AsCString());
- s->PutCString("struct {");
- if (st->GetNumFields() == 0) {
- s->PutChar('}');
- return;
- }
- s->IndentMore();
- uint32_t field_idx = 0;
- for (auto *field = st->GetField(field_idx); field != nullptr;
- field_idx++) {
- s->PutChar('\n');
- s->Indent();
- s->Printf("%s %s", field->m_name.AsCString(),
- field->m_type.GetTypeName().AsCString());
- }
- s->IndentLess();
- s->PutChar('\n');
- s->Indent("}");
- return;
- }
- }
-
- s->PutCString(name.AsCString());
-}
-
-CompilerType GoASTContext::CreateArrayType(const ConstString &name,
- const CompilerType &element_type,
- uint64_t length) {
- GoType *type = new GoArray(name, length, element_type);
- (*m_types)[name].reset(type);
- return CompilerType(this, type);
-}
-
-CompilerType GoASTContext::CreateBaseType(int go_kind,
- const lldb_private::ConstString &name,
- uint64_t byte_size) {
- if (go_kind == GoType::KIND_UINT || go_kind == GoType::KIND_INT)
- m_int_byte_size = byte_size;
- GoType *type = new GoType(go_kind, name);
- (*m_types)[name].reset(type);
- return CompilerType(this, type);
-}
-
-CompilerType GoASTContext::CreateTypedefType(int kind, const ConstString &name,
- CompilerType impl) {
- GoType *type = new GoElem(kind, name, impl);
- (*m_types)[name].reset(type);
- return CompilerType(this, type);
-}
-
-CompilerType
-GoASTContext::CreateVoidType(const lldb_private::ConstString &name) {
- GoType *type = new GoType(GoType::KIND_LLDB_VOID, name);
- (*m_types)[name].reset(type);
- return CompilerType(this, type);
-}
-
-CompilerType
-GoASTContext::CreateStructType(int kind, const lldb_private::ConstString &name,
- uint32_t byte_size) {
- GoType *type = new GoStruct(kind, name, byte_size);
- (*m_types)[name].reset(type);
- return CompilerType(this, type);
-}
-
-void GoASTContext::AddFieldToStruct(
- const lldb_private::CompilerType &struct_type,
- const lldb_private::ConstString &name,
- const lldb_private::CompilerType &field_type, uint32_t byte_offset) {
- if (!struct_type)
- return;
- GoASTContext *ast =
- llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem());
- if (!ast)
- return;
- GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType());
- if (GoStruct *s = type->GetStruct())
- s->AddField(name, field_type, byte_offset);
-}
-
-void GoASTContext::CompleteStructType(
- const lldb_private::CompilerType &struct_type) {
- if (!struct_type)
- return;
- GoASTContext *ast =
- llvm::dyn_cast_or_null<GoASTContext>(struct_type.GetTypeSystem());
- if (!ast)
- return;
- GoType *type = static_cast<GoType *>(struct_type.GetOpaqueQualType());
- if (GoStruct *s = type->GetStruct())
- s->SetComplete();
-}
-
-CompilerType
-GoASTContext::CreateFunctionType(const lldb_private::ConstString &name,
- CompilerType *params, size_t params_count,
- bool is_variadic) {
- GoType *type = new GoFunction(name, is_variadic);
- (*m_types)[name].reset(type);
- return CompilerType(this, type);
-}
-
-bool GoASTContext::IsGoString(const lldb_private::CompilerType &type) {
- if (!type.IsValid() ||
- !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem()))
- return false;
- return GoType::KIND_STRING ==
- static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind();
-}
-
-bool GoASTContext::IsGoSlice(const lldb_private::CompilerType &type) {
- if (!type.IsValid() ||
- !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem()))
- return false;
- return GoType::KIND_SLICE ==
- static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind();
-}
-
-bool GoASTContext::IsGoInterface(const lldb_private::CompilerType &type) {
- if (!type.IsValid() ||
- !llvm::dyn_cast_or_null<GoASTContext>(type.GetTypeSystem()))
- return false;
- return GoType::KIND_INTERFACE ==
- static_cast<GoType *>(type.GetOpaqueQualType())->GetGoKind();
-}
-
-bool GoASTContext::IsPointerKind(uint8_t kind) {
- return (kind & GoType::KIND_MASK) == GoType::KIND_PTR;
-}
-
-bool GoASTContext::IsDirectIface(uint8_t kind) {
- return (kind & GoType::KIND_DIRECT_IFACE) == GoType::KIND_DIRECT_IFACE;
-}
-
-DWARFASTParser *GoASTContext::GetDWARFParser() {
- if (!m_dwarf_ast_parser_ap)
- m_dwarf_ast_parser_ap.reset(new DWARFASTParserGo(*this));
- return m_dwarf_ast_parser_ap.get();
-}
-
-UserExpression *GoASTContextForExpr::GetUserExpression(
- llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language,
- Expression::ResultType desired_type,
- const EvaluateExpressionOptions &options) {
- TargetSP target = m_target_wp.lock();
- if (target)
- return new GoUserExpression(*target, expr, prefix, language, desired_type,
- options);
- return nullptr;
-}
diff --git a/source/Symbol/JavaASTContext.cpp b/source/Symbol/JavaASTContext.cpp
deleted file mode 100644
index ff317eb19e97..000000000000
--- a/source/Symbol/JavaASTContext.cpp
+++ /dev/null
@@ -1,1324 +0,0 @@
-//===-- JavaASTContext.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/Symbol/JavaASTContext.h"
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/DWARFExpression.h"
-#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/Stream.h"
-#include <sstream>
-
-#include "Plugins/SymbolFile/DWARF/DWARFASTParserJava.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-namespace lldb_private {
-
-class JavaASTContext::JavaType {
-public:
- enum LLVMCastKind {
- eKindPrimitive,
- eKindObject,
- eKindReference,
- eKindArray,
- kNumKinds
- };
-
- JavaType(LLVMCastKind kind) : m_kind(kind) {}
-
- virtual ~JavaType() = default;
-
- virtual ConstString GetName() = 0;
-
- virtual void Dump(Stream *s) = 0;
-
- virtual bool IsCompleteType() = 0;
-
- LLVMCastKind getKind() const { return m_kind; }
-
-private:
- LLVMCastKind m_kind;
-};
-
-} // end of namespace lldb_private
-
-namespace {
-
-class JavaPrimitiveType : public JavaASTContext::JavaType {
-public:
- enum TypeKind {
- eTypeByte,
- eTypeShort,
- eTypeInt,
- eTypeLong,
- eTypeFloat,
- eTypeDouble,
- eTypeBoolean,
- eTypeChar,
- };
-
- JavaPrimitiveType(TypeKind type_kind)
- : JavaType(JavaType::eKindPrimitive), m_type_kind(type_kind) {}
-
- ConstString GetName() override {
- switch (m_type_kind) {
- case eTypeByte:
- return ConstString("byte");
- case eTypeShort:
- return ConstString("short");
- case eTypeInt:
- return ConstString("int");
- case eTypeLong:
- return ConstString("long");
- case eTypeFloat:
- return ConstString("float");
- case eTypeDouble:
- return ConstString("double");
- case eTypeBoolean:
- return ConstString("boolean");
- case eTypeChar:
- return ConstString("char");
- }
- return ConstString();
- }
-
- TypeKind GetTypeKind() { return m_type_kind; }
-
- void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
-
- bool IsCompleteType() override { return true; }
-
- static bool classof(const JavaType *jt) {
- return jt->getKind() == JavaType::eKindPrimitive;
- }
-
-private:
- const TypeKind m_type_kind;
-};
-
-class JavaDynamicType : public JavaASTContext::JavaType {
-public:
- JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name)
- : JavaType(kind), m_linkage_name(linkage_name),
- m_dynamic_type_id(nullptr) {}
-
- ConstString GetLinkageName() const { return m_linkage_name; }
-
- void SetDynamicTypeId(const DWARFExpression &type_id) {
- m_dynamic_type_id = type_id;
- }
-
- uint64_t CalculateDynamicTypeId(ExecutionContext *exe_ctx,
- ValueObject &value_obj) {
- if (!m_dynamic_type_id.IsValid())
- return UINT64_MAX;
-
- Value obj_load_address = value_obj.GetValue();
- obj_load_address.ResolveValue(exe_ctx);
- obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
-
- Value result;
- if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), 0,
- &obj_load_address, nullptr, result,
- nullptr)) {
- Status error;
-
- lldb::addr_t type_id_addr = result.GetScalar().UInt();
- lldb::ProcessSP process_sp = exe_ctx->GetProcessSP();
- if (process_sp)
- return process_sp->ReadUnsignedIntegerFromMemory(
- type_id_addr, process_sp->GetAddressByteSize(), UINT64_MAX, error);
- }
-
- return UINT64_MAX;
- }
-
-public:
- ConstString m_linkage_name;
- DWARFExpression m_dynamic_type_id;
-};
-
-class JavaObjectType : public JavaDynamicType {
-public:
- struct Field {
- ConstString m_name;
- CompilerType m_type;
- uint32_t m_offset;
- };
-
- JavaObjectType(const ConstString &name, const ConstString &linkage_name,
- uint32_t byte_size)
- : JavaDynamicType(JavaType::eKindObject, linkage_name), m_name(name),
- m_byte_size(byte_size), m_base_class_offset(0), m_is_complete(false) {}
-
- ConstString GetName() override { return m_name; }
-
- uint32_t GetByteSize() const { return m_byte_size; }
-
- uint32_t GetNumFields() { return m_fields.size(); }
-
- void Dump(Stream *s) override {
- if (m_base_class.IsValid())
- s->Printf("%s : %s\n", GetName().GetCString(),
- m_base_class.GetTypeName().GetCString());
- else
- s->Printf("%s\n", GetName().GetCString());
-
- s->IndentMore();
- for (const Field &f : m_fields)
- s->Printf("%s %s\n", f.m_type.GetTypeName().GetCString(),
- f.m_name.GetCString());
- s->IndentLess();
- }
-
- Field *GetFieldAtIndex(size_t idx) {
- if (idx < m_fields.size())
- return &m_fields[idx];
- return nullptr;
- }
-
- CompilerType GetBaseClass() { return m_base_class; }
-
- uint32_t GetBaseClassOffset() { return m_base_class_offset; }
-
- uint32_t GetNumInterfaces() { return m_interfaces.size(); }
-
- CompilerType GetInterfaceAtIndex(uint32_t idx) {
- if (m_interfaces.size() < idx)
- return m_interfaces[idx];
- return CompilerType();
- }
-
- bool IsCompleteType() override { return m_is_complete; }
-
- void SetCompleteType(bool is_complete) {
- m_is_complete = is_complete;
- if (m_byte_size == 0) {
- // Try to calcualte the size of the object based on it's values
- for (const Field &field : m_fields) {
- uint32_t field_end = field.m_offset + field.m_type.GetByteSize(nullptr);
- if (field_end > m_byte_size)
- m_byte_size = field_end;
- }
- }
- }
-
- void AddBaseClass(const CompilerType &type, uint32_t offset) {
- // TODO: Check if type is an interface and add it to the interface list in
- // that case
- m_base_class = type;
- m_base_class_offset = offset;
- }
-
- void AddField(const ConstString &name, const CompilerType &type,
- uint32_t offset) {
- m_fields.push_back({name, type, offset});
- }
-
- static bool classof(const JavaType *jt) {
- return jt->getKind() == JavaType::eKindObject;
- }
-
-private:
- ConstString m_name;
- uint32_t m_byte_size;
- CompilerType m_base_class;
- uint32_t m_base_class_offset;
- std::vector<CompilerType> m_interfaces;
- std::vector<Field> m_fields;
- bool m_is_complete;
-};
-
-class JavaReferenceType : public JavaASTContext::JavaType {
-public:
- JavaReferenceType(CompilerType pointee_type)
- : JavaType(JavaType::eKindReference), m_pointee_type(pointee_type) {}
-
- static bool classof(const JavaType *jt) {
- return jt->getKind() == JavaType::eKindReference;
- }
-
- CompilerType GetPointeeType() { return m_pointee_type; }
-
- ConstString GetName() override {
- ConstString pointee_type_name =
- static_cast<JavaType *>(GetPointeeType().GetOpaqueQualType())
- ->GetName();
- return ConstString(std::string(pointee_type_name.AsCString()) + "&");
- }
-
- void Dump(Stream *s) override {
- static_cast<JavaType *>(m_pointee_type.GetOpaqueQualType())->Dump(s);
- }
-
- bool IsCompleteType() override { return m_pointee_type.IsCompleteType(); }
-
-private:
- CompilerType m_pointee_type;
-};
-
-class JavaArrayType : public JavaDynamicType {
-public:
- JavaArrayType(const ConstString &linkage_name, CompilerType element_type,
- const DWARFExpression &length_expression,
- lldb::addr_t data_offset)
- : JavaDynamicType(JavaType::eKindArray, linkage_name),
- m_element_type(element_type), m_length_expression(length_expression),
- m_data_offset(data_offset) {}
-
- static bool classof(const JavaType *jt) {
- return jt->getKind() == JavaType::eKindArray;
- }
-
- CompilerType GetElementType() { return m_element_type; }
-
- ConstString GetName() override {
- ConstString element_type_name =
- static_cast<JavaType *>(GetElementType().GetOpaqueQualType())
- ->GetName();
- return ConstString(std::string(element_type_name.AsCString()) + "[]");
- }
-
- void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
-
- bool IsCompleteType() override { return m_length_expression.IsValid(); }
-
- uint32_t GetNumElements(ValueObject *value_obj) {
- if (!m_length_expression.IsValid())
- return UINT32_MAX;
-
- Status error;
- ValueObjectSP address_obj = value_obj->AddressOf(error);
- if (error.Fail())
- return UINT32_MAX;
-
- Value obj_load_address = address_obj->GetValue();
- obj_load_address.SetValueType(Value::eValueTypeLoadAddress);
-
- Value result;
- ExecutionContextScope *exec_ctx_scope = value_obj->GetExecutionContextRef()
- .Lock(true)
- .GetBestExecutionContextScope();
- if (m_length_expression.Evaluate(exec_ctx_scope, 0, nullptr,
- &obj_load_address, result, nullptr))
- return result.GetScalar().UInt();
-
- return UINT32_MAX;
- }
-
- uint64_t GetElementOffset(size_t idx) {
- return m_data_offset + idx * m_element_type.GetByteSize(nullptr);
- }
-
-private:
- CompilerType m_element_type;
- DWARFExpression m_length_expression;
- lldb::addr_t m_data_offset;
-};
-
-} // end of anonymous namespace
-
-ConstString JavaASTContext::GetPluginNameStatic() {
- return ConstString("java");
-}
-
-ConstString JavaASTContext::GetPluginName() {
- return JavaASTContext::GetPluginNameStatic();
-}
-
-uint32_t JavaASTContext::GetPluginVersion() { return 1; }
-
-lldb::TypeSystemSP JavaASTContext::CreateInstance(lldb::LanguageType language,
- Module *module,
- Target *target) {
- if (language == eLanguageTypeJava) {
- if (module)
- return std::make_shared<JavaASTContext>(module->GetArchitecture());
- if (target)
- return std::make_shared<JavaASTContext>(target->GetArchitecture());
- assert(false && "Either a module or a target has to be specifed to create "
- "a JavaASTContext");
- }
- return lldb::TypeSystemSP();
-}
-
-void JavaASTContext::EnumerateSupportedLanguages(
- std::set<lldb::LanguageType> &languages_for_types,
- std::set<lldb::LanguageType> &languages_for_expressions) {
- static std::vector<lldb::LanguageType> s_languages_for_types(
- {lldb::eLanguageTypeJava});
- static std::vector<lldb::LanguageType> s_languages_for_expressions({});
-
- languages_for_types.insert(s_languages_for_types.begin(),
- s_languages_for_types.end());
- languages_for_expressions.insert(s_languages_for_expressions.begin(),
- s_languages_for_expressions.end());
-}
-
-void JavaASTContext::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(), "AST context plug-in",
- CreateInstance, EnumerateSupportedLanguages);
-}
-
-void JavaASTContext::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-JavaASTContext::JavaASTContext(const ArchSpec &arch)
- : TypeSystem(eKindJava), m_pointer_byte_size(arch.GetAddressByteSize()) {}
-
-JavaASTContext::~JavaASTContext() {}
-
-uint32_t JavaASTContext::GetPointerByteSize() { return m_pointer_byte_size; }
-
-DWARFASTParser *JavaASTContext::GetDWARFParser() {
- if (!m_dwarf_ast_parser_ap)
- m_dwarf_ast_parser_ap.reset(new DWARFASTParserJava(*this));
- return m_dwarf_ast_parser_ap.get();
-}
-
-ConstString JavaASTContext::DeclGetName(void *opaque_decl) {
- return ConstString();
-}
-
-std::vector<CompilerDecl> JavaASTContext::DeclContextFindDeclByName(
- void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls) {
- return std::vector<CompilerDecl>();
-}
-
-bool JavaASTContext::DeclContextIsStructUnionOrClass(void *opaque_decl_ctx) {
- return false;
-}
-
-ConstString JavaASTContext::DeclContextGetName(void *opaque_decl_ctx) {
- return ConstString();
-}
-
-bool JavaASTContext::DeclContextIsClassMethod(
- void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
- bool *is_instance_method_ptr, ConstString *language_object_name_ptr) {
- return false;
-}
-
-bool JavaASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size,
- bool *is_incomplete) {
- if (element_type)
- element_type->Clear();
- if (size)
- *size = 0;
- if (is_incomplete)
- *is_incomplete = false;
-
- if (JavaArrayType *array =
- llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type))) {
- if (element_type)
- *element_type = array->GetElementType();
- return true;
- }
- return false;
-}
-
-bool JavaASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
- return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type));
-}
-
-bool JavaASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type)))
- return ptype->GetTypeKind() == JavaPrimitiveType::eTypeChar;
- return false;
-}
-
-bool JavaASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
- uint32_t &count, bool &is_complex) {
- is_complex = true;
-
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeFloat:
- case JavaPrimitiveType::eTypeDouble:
- count = 1;
- return true;
- default:
- break;
- }
- }
-
- count = 0;
- return false;
-}
-
-bool JavaASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr) {
- if (is_variadic_ptr)
- *is_variadic_ptr = false;
- return false;
-}
-
-size_t JavaASTContext::GetNumberOfFunctionArguments(
- lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-CompilerType
-JavaASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) {
- return CompilerType();
-}
-
-bool JavaASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool JavaASTContext::IsBlockPointerType(
- lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) {
- return false;
-}
-
-bool JavaASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) {
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeByte:
- case JavaPrimitiveType::eTypeShort:
- case JavaPrimitiveType::eTypeInt:
- case JavaPrimitiveType::eTypeLong:
- is_signed = true;
- return true;
- default:
- break;
- }
- }
-
- is_signed = false;
- return false;
-}
-
-bool JavaASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
- CompilerType *target_type,
- bool check_cplusplus,
- bool check_objc) {
- return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type));
-}
-
-bool JavaASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type) {
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool JavaASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type,
- bool *is_rvalue) {
- if (is_rvalue)
- *is_rvalue = false;
-
- if (JavaReferenceType *ref =
- llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type))) {
- if (pointee_type)
- *pointee_type = ref->GetPointeeType();
- return true;
- }
-
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool JavaASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
- return llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)) ||
- llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type));
-}
-
-bool JavaASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
- return false; // TODO: Implement if we introduce the void type
-}
-
-bool JavaASTContext::SupportsLanguage(lldb::LanguageType language) {
- return language == lldb::eLanguageTypeJava;
-}
-
-bool JavaASTContext::IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) {
- return true;
-}
-
-bool JavaASTContext::IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type) {
- return IsPointerType(type, pointee_type) ||
- IsReferenceType(type, pointee_type);
-}
-
-bool JavaASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) {
- return false; // TODO: Implement it if we need it for string literals
-}
-
-bool JavaASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool JavaASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) {
- if (element_type)
- element_type->Clear();
- if (size)
- *size = 0;
- return false;
-}
-
-bool JavaASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
- return llvm::isa<JavaObjectType>(static_cast<JavaType *>(type));
-}
-
-uint32_t
-JavaASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) {
- return false;
-}
-
-bool JavaASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
- return static_cast<JavaType *>(type)->IsCompleteType();
-}
-
-bool JavaASTContext::IsConst(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool JavaASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool JavaASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
- return type != nullptr;
-}
-
-bool JavaASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
- if (IsCompleteType(type))
- return true;
-
- if (JavaArrayType *array =
- llvm::dyn_cast<JavaArrayType>(static_cast<JavaType *>(type)))
- return GetCompleteType(array->GetElementType().GetOpaqueQualType());
-
- if (JavaReferenceType *reference =
- llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
- return GetCompleteType(reference->GetPointeeType().GetOpaqueQualType());
-
- if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type))) {
- SymbolFile *symbol_file = GetSymbolFile();
- if (!symbol_file)
- return false;
-
- CompilerType object_type(this, type);
- return symbol_file->CompleteType(object_type);
- }
- return false;
-}
-
-ConstString JavaASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
- if (type)
- return static_cast<JavaType *>(type)->GetName();
- return ConstString();
-}
-
-uint32_t
-JavaASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_compiler_type) {
- if (pointee_or_element_compiler_type)
- pointee_or_element_compiler_type->Clear();
- if (!type)
- return 0;
-
- if (IsReferenceType(type, pointee_or_element_compiler_type))
- return eTypeHasChildren | eTypeHasValue | eTypeIsReference;
- if (IsArrayType(type, pointee_or_element_compiler_type, nullptr, nullptr))
- return eTypeHasChildren | eTypeIsArray;
- if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
- return eTypeHasChildren | eTypeIsClass;
-
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeByte:
- case JavaPrimitiveType::eTypeShort:
- case JavaPrimitiveType::eTypeInt:
- case JavaPrimitiveType::eTypeLong:
- return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger |
- eTypeIsSigned;
- case JavaPrimitiveType::eTypeFloat:
- case JavaPrimitiveType::eTypeDouble:
- return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsFloat |
- eTypeIsSigned;
- case JavaPrimitiveType::eTypeBoolean:
- return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar;
- case JavaPrimitiveType::eTypeChar:
- return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar;
- }
- }
- return 0;
-}
-
-lldb::TypeClass
-JavaASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
- if (!type)
- return eTypeClassInvalid;
- if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type)))
- return eTypeClassReference;
- if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type)))
- return eTypeClassArray;
- if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
- return eTypeClassClass;
- if (llvm::isa<JavaPrimitiveType>(static_cast<JavaType *>(type)))
- return eTypeClassBuiltin;
- assert(false && "Java type with unhandled type class");
- return eTypeClassInvalid;
-}
-
-lldb::LanguageType
-JavaASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
- return lldb::eLanguageTypeJava;
-}
-
-CompilerType
-JavaASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride) {
- if (stride)
- *stride = 0;
-
- CompilerType element_type;
- if (IsArrayType(type, &element_type, nullptr, nullptr))
- return element_type;
- return CompilerType();
-}
-
-CompilerType JavaASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
- CompilerType pointee_type;
- if (IsPointerType(type, &pointee_type))
- return pointee_type;
- return CompilerType();
-}
-
-CompilerType JavaASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
- return CompilerType(); // No pointer types in java
-}
-
-CompilerType
-JavaASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-CompilerType
-JavaASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-CompilerType
-JavaASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
- CompilerType pointee_type;
- if (IsReferenceType(type, &pointee_type))
- return pointee_type;
- return CompilerType(this, type);
-}
-
-CompilerType
-JavaASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
- return CompilerType();
-}
-
-CompilerType JavaASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
- return CompilerType();
-}
-
-CompilerType
-JavaASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
- size_t bit_size) {
- return CompilerType();
-}
-
-size_t JavaASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-lldb::BasicType
-JavaASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeByte:
- return eBasicTypeOther;
- case JavaPrimitiveType::eTypeShort:
- return eBasicTypeShort;
- case JavaPrimitiveType::eTypeInt:
- return eBasicTypeInt;
- case JavaPrimitiveType::eTypeLong:
- return eBasicTypeLong;
- case JavaPrimitiveType::eTypeFloat:
- return eBasicTypeFloat;
- case JavaPrimitiveType::eTypeDouble:
- return eBasicTypeDouble;
- case JavaPrimitiveType::eTypeBoolean:
- return eBasicTypeBool;
- case JavaPrimitiveType::eTypeChar:
- return eBasicTypeChar;
- }
- }
- return eBasicTypeInvalid;
-}
-
-uint64_t JavaASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) {
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeByte:
- return 8;
- case JavaPrimitiveType::eTypeShort:
- return 16;
- case JavaPrimitiveType::eTypeInt:
- return 32;
- case JavaPrimitiveType::eTypeLong:
- return 64;
- case JavaPrimitiveType::eTypeFloat:
- return 32;
- case JavaPrimitiveType::eTypeDouble:
- return 64;
- case JavaPrimitiveType::eTypeBoolean:
- return 1;
- case JavaPrimitiveType::eTypeChar:
- return 16;
- }
- } else if (llvm::isa<JavaReferenceType>(static_cast<JavaType *>(type))) {
- return 32; // References are always 4 byte long in java
- } else if (llvm::isa<JavaArrayType>(static_cast<JavaType *>(type))) {
- return 64;
- } else if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(type))) {
- return obj->GetByteSize() * 8;
- }
- return 0;
-}
-
-lldb::Encoding JavaASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) {
- count = 1;
-
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeByte:
- case JavaPrimitiveType::eTypeShort:
- case JavaPrimitiveType::eTypeInt:
- case JavaPrimitiveType::eTypeLong:
- return eEncodingSint;
- case JavaPrimitiveType::eTypeFloat:
- case JavaPrimitiveType::eTypeDouble:
- return eEncodingIEEE754;
- case JavaPrimitiveType::eTypeBoolean:
- case JavaPrimitiveType::eTypeChar:
- return eEncodingUint;
- }
- }
- if (IsReferenceType(type))
- return eEncodingUint;
- return eEncodingInvalid;
-}
-
-lldb::Format JavaASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
- if (JavaPrimitiveType *ptype =
- llvm::dyn_cast<JavaPrimitiveType>(static_cast<JavaType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case JavaPrimitiveType::eTypeByte:
- case JavaPrimitiveType::eTypeShort:
- case JavaPrimitiveType::eTypeInt:
- case JavaPrimitiveType::eTypeLong:
- return eFormatDecimal;
- case JavaPrimitiveType::eTypeFloat:
- case JavaPrimitiveType::eTypeDouble:
- return eFormatFloat;
- case JavaPrimitiveType::eTypeBoolean:
- return eFormatBoolean;
- case JavaPrimitiveType::eTypeChar:
- return eFormatUnicode16;
- }
- }
- if (IsReferenceType(type))
- return eFormatHex;
- return eFormatDefault;
-}
-
-unsigned JavaASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-size_t
-JavaASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
- const char *s, uint8_t *dst,
- size_t dst_size) {
- assert(false && "Not implemented");
- return 0;
-}
-
-size_t
-JavaASTContext::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-uint32_t JavaASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
- return obj->GetNumFields();
- }
- return 0;
-}
-
-CompilerType JavaASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx, std::string &name,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- if (bitfield_bit_size_ptr)
- *bitfield_bit_size_ptr = 0;
- if (is_bitfield_ptr)
- *is_bitfield_ptr = false;
-
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
-
- JavaObjectType::Field *field = obj->GetFieldAtIndex(idx);
- if (!field)
- return CompilerType();
- name = field->m_name.AsCString();
- if (bit_offset_ptr)
- *bit_offset_ptr = field->m_offset * 8;
- return field->m_type;
- }
- return CompilerType();
-}
-
-uint32_t JavaASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) {
- GetCompleteType(type);
-
- if (JavaReferenceType *ref =
- llvm::dyn_cast<JavaReferenceType>(static_cast<JavaType *>(type)))
- return ref->GetPointeeType().GetNumChildren(omit_empty_base_classes);
-
- if (llvm::isa<JavaObjectType>(static_cast<JavaType *>(type)))
- return GetNumFields(type) + GetNumDirectBaseClasses(type);
-
- return 0;
-}
-
-uint32_t
-JavaASTContext::GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) {
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
- return obj->GetNumInterfaces() + (obj->GetBaseClass() ? 1 : 0);
- }
- return 0;
-}
-
-uint32_t
-JavaASTContext::GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) {
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
- return obj->GetNumInterfaces();
- }
- return 0;
-}
-
-CompilerType JavaASTContext::GetDirectBaseClassAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
-
- if (CompilerType base_class = obj->GetBaseClass()) {
- if (idx == 0)
- return base_class;
- else
- --idx;
- }
- return obj->GetInterfaceAtIndex(idx);
- }
- return CompilerType();
-}
-
-CompilerType JavaASTContext::GetVirtualBaseClassAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx, uint32_t *bit_offset_ptr) {
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
- return obj->GetInterfaceAtIndex(idx);
- }
- return CompilerType();
-}
-
-void JavaASTContext::DumpValue(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
- lldb::Format format, const DataExtractor &data, lldb::offset_t data_offset,
- size_t data_byte_size, uint32_t bitfield_bit_size,
- uint32_t bitfield_bit_offset, bool show_types, bool show_summary,
- bool verbose, uint32_t depth) {
- assert(false && "Not implemented");
-}
-
-bool JavaASTContext::DumpTypeValue(
- lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
- const DataExtractor &data, lldb::offset_t data_offset,
- size_t data_byte_size, uint32_t bitfield_bit_size,
- uint32_t bitfield_bit_offset, ExecutionContextScope *exe_scope) {
- if (IsScalarType(type)) {
- return DumpDataExtractor(data, s, data_offset, format, data_byte_size,
- 1, // count
- UINT32_MAX, LLDB_INVALID_ADDRESS,
- bitfield_bit_size, bitfield_bit_offset, exe_scope);
- }
- return false;
-}
-
-void JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
- StreamFile s(stdout, false);
- DumpTypeDescription(type, &s);
-}
-
-void JavaASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) {
- static_cast<JavaType *>(type)->Dump(s);
-}
-
-void JavaASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
- ExecutionContext *exe_ctx, Stream *s,
- const DataExtractor &data,
- lldb::offset_t data_offset,
- size_t data_byte_size) {
- assert(false && "Not implemented");
-}
-
-int JavaASTContext::GetFunctionArgumentCount(
- lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-CompilerType JavaASTContext::GetFunctionArgumentTypeAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx) {
- return CompilerType();
-}
-
-CompilerType
-JavaASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
- return CompilerType();
-}
-
-size_t
-JavaASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-TypeMemberFunctionImpl
-JavaASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) {
- return TypeMemberFunctionImpl();
-}
-
-CompilerType JavaASTContext::GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
- bool transparent_pointers, bool omit_empty_base_classes,
- bool ignore_array_bounds, std::string &child_name,
- uint32_t &child_byte_size, int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class, bool &child_is_deref_of_parent,
- ValueObject *valobj, uint64_t &language_flags) {
- child_name.clear();
- child_byte_size = 0;
- child_byte_offset = 0;
- child_bitfield_bit_size = 0;
- child_bitfield_bit_offset = 0;
- child_is_base_class = false;
- child_is_deref_of_parent = false;
- language_flags = 0;
-
- ExecutionContextScope *exec_ctx_scope =
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr;
-
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
-
- if (CompilerType base_class = obj->GetBaseClass()) {
- if (idx == 0) {
- JavaType *base_class_type =
- static_cast<JavaType *>(base_class.GetOpaqueQualType());
- child_name = base_class_type->GetName().GetCString();
- child_byte_size = base_class.GetByteSize(
- exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
- child_byte_offset = obj->GetBaseClassOffset();
- child_is_base_class = true;
- return base_class;
- }
- idx -= 1;
- }
-
- JavaObjectType::Field *field = obj->GetFieldAtIndex(idx);
- if (!field)
- return CompilerType();
-
- child_name = field->m_name.AsCString();
- child_byte_size = field->m_type.GetByteSize(exec_ctx_scope);
- child_byte_offset = field->m_offset;
- return field->m_type;
- } else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(
- static_cast<JavaType *>(type))) {
- CompilerType pointee_type = ref->GetPointeeType();
-
- if (transparent_pointers)
- return pointee_type.GetChildCompilerTypeAtIndex(
- exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
- ignore_array_bounds, child_name, child_byte_size, child_byte_offset,
- child_bitfield_bit_size, child_bitfield_bit_offset,
- child_is_base_class, child_is_deref_of_parent, valobj,
- language_flags);
-
- if (idx != 0)
- return CompilerType();
-
- if (valobj && valobj->GetName())
- child_name = valobj->GetName().GetCString();
- child_is_deref_of_parent = true;
- child_byte_offset = 0;
- child_byte_size = pointee_type.GetByteSize(exec_ctx_scope);
- return pointee_type;
- }
- return CompilerType();
-}
-
-uint32_t
-JavaASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) {
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
-
- uint32_t index_offset = 0;
- if (CompilerType base_class = obj->GetBaseClass()) {
- if (base_class.GetTypeName() == ConstString(name))
- return 0;
- index_offset = 1;
- }
- for (uint32_t i = 0; i < obj->GetNumFields(); ++i) {
- if (obj->GetFieldAtIndex(i)->m_name == ConstString(name))
- return i + index_offset;
- }
- } else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(
- static_cast<JavaType *>(type))) {
- return GetIndexOfChildWithName(ref->GetPointeeType().GetOpaqueQualType(),
- name, omit_empty_base_classes);
- }
- return UINT_MAX;
-}
-
-size_t JavaASTContext::GetIndexOfChildMemberWithName(
- lldb::opaque_compiler_type_t type, const char *name,
- bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
- child_indexes.clear();
-
- if (JavaObjectType *obj =
- llvm::dyn_cast<JavaObjectType>(static_cast<JavaType *>(type))) {
- GetCompleteType(type);
-
- uint32_t index_offset = 0;
- if (CompilerType base_class = obj->GetBaseClass()) {
- if (GetIndexOfChildMemberWithName(base_class.GetOpaqueQualType(), name,
- omit_empty_base_classes,
- child_indexes) != 0) {
- child_indexes.insert(child_indexes.begin(), 0);
- return child_indexes.size();
- }
- index_offset = 1;
- }
-
- for (uint32_t i = 0; i < obj->GetNumFields(); ++i) {
- if (obj->GetFieldAtIndex(i)->m_name == ConstString(name)) {
- child_indexes.push_back(i + index_offset);
- return child_indexes.size();
- }
- }
- } else if (JavaReferenceType *ref = llvm::dyn_cast<JavaReferenceType>(
- static_cast<JavaType *>(type))) {
- return GetIndexOfChildMemberWithName(
- ref->GetPointeeType().GetOpaqueQualType(), name,
- omit_empty_base_classes, child_indexes);
- }
- return 0;
-}
-
-CompilerType
-JavaASTContext::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
- return CreateReferenceType(CompilerType(this, type));
-}
-
-ConstString JavaASTContext::DeclContextGetScopeQualifiedName(
- lldb::opaque_compiler_type_t opaque_decl_ctx) {
- return GetTypeName(opaque_decl_ctx);
-}
-
-static void AddPrimitiveType(JavaASTContext::JavaTypeMap &type_map,
- JavaPrimitiveType::TypeKind type_kind) {
- JavaPrimitiveType *type = new JavaPrimitiveType(type_kind);
- type_map.emplace(type->GetName(),
- std::unique_ptr<JavaASTContext::JavaType>(type));
-}
-
-CompilerType JavaASTContext::CreateBaseType(const ConstString &name) {
- if (m_base_type_map.empty()) {
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeByte);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeShort);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeInt);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeLong);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeFloat);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeDouble);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeBoolean);
- AddPrimitiveType(m_base_type_map, JavaPrimitiveType::eTypeChar);
- }
- auto it = m_base_type_map.find(name);
- if (it != m_base_type_map.end())
- return CompilerType(this, it->second.get());
- return CompilerType();
-}
-
-CompilerType JavaASTContext::CreateObjectType(const ConstString &name,
- const ConstString &linkage_name,
- uint32_t byte_size) {
- auto it = m_object_type_map.find(name);
- if (it == m_object_type_map.end()) {
- std::unique_ptr<JavaType> object_type(
- new JavaObjectType(name, linkage_name, byte_size));
- it = m_object_type_map.emplace(name, std::move(object_type)).first;
- }
- return CompilerType(this, it->second.get());
-}
-
-CompilerType JavaASTContext::CreateArrayType(
- const ConstString &linkage_name, const CompilerType &element_type,
- const DWARFExpression &length_expression, const lldb::addr_t data_offset) {
- ConstString name = element_type.GetTypeName();
- auto it = m_array_type_map.find(name);
- if (it == m_array_type_map.end()) {
- std::unique_ptr<JavaType> array_type(new JavaArrayType(
- linkage_name, element_type, length_expression, data_offset));
- it = m_array_type_map.emplace(name, std::move(array_type)).first;
- }
- return CompilerType(this, it->second.get());
-}
-
-CompilerType
-JavaASTContext::CreateReferenceType(const CompilerType &pointee_type) {
- ConstString name = pointee_type.GetTypeName();
- auto it = m_reference_type_map.find(name);
- if (it == m_reference_type_map.end())
- it = m_reference_type_map
- .emplace(name, std::unique_ptr<JavaType>(
- new JavaReferenceType(pointee_type)))
- .first;
- return CompilerType(this, it->second.get());
-}
-
-void JavaASTContext::CompleteObjectType(const CompilerType &object_type) {
- JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(object_type.GetOpaqueQualType()));
- assert(obj &&
- "JavaASTContext::CompleteObjectType called with not a JavaObjectType");
- obj->SetCompleteType(true);
-}
-
-void JavaASTContext::AddBaseClassToObject(const CompilerType &object_type,
- const CompilerType &member_type,
- uint32_t member_offset) {
- JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(object_type.GetOpaqueQualType()));
- assert(obj &&
- "JavaASTContext::AddMemberToObject called with not a JavaObjectType");
- obj->AddBaseClass(member_type, member_offset);
-}
-
-void JavaASTContext::AddMemberToObject(const CompilerType &object_type,
- const ConstString &name,
- const CompilerType &member_type,
- uint32_t member_offset) {
- JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(object_type.GetOpaqueQualType()));
- assert(obj &&
- "JavaASTContext::AddMemberToObject called with not a JavaObjectType");
- obj->AddField(name, member_type, member_offset);
-}
-
-void JavaASTContext::SetDynamicTypeId(const CompilerType &type,
- const DWARFExpression &type_id) {
- JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(type.GetOpaqueQualType()));
- assert(obj &&
- "JavaASTContext::SetDynamicTypeId called with not a JavaObjectType");
- obj->SetDynamicTypeId(type_id);
-}
-
-uint64_t JavaASTContext::CalculateDynamicTypeId(ExecutionContext *exe_ctx,
- const CompilerType &type,
- ValueObject &in_value) {
- if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(type.GetOpaqueQualType())))
- return obj->CalculateDynamicTypeId(exe_ctx, in_value);
- if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(
- static_cast<JavaType *>(type.GetOpaqueQualType())))
- return arr->CalculateDynamicTypeId(exe_ctx, in_value);
- return UINT64_MAX;
-}
-
-uint32_t JavaASTContext::CalculateArraySize(const CompilerType &type,
- ValueObject &in_value) {
- if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(
- static_cast<JavaType *>(type.GetOpaqueQualType())))
- return arr->GetNumElements(&in_value);
- return UINT32_MAX;
-}
-
-uint64_t JavaASTContext::CalculateArrayElementOffset(const CompilerType &type,
- size_t index) {
- if (JavaArrayType *arr = llvm::dyn_cast<JavaArrayType>(
- static_cast<JavaType *>(type.GetOpaqueQualType())))
- return arr->GetElementOffset(index);
- return UINT64_MAX;
-}
-
-ConstString JavaASTContext::GetLinkageName(const CompilerType &type) {
- if (JavaObjectType *obj = llvm::dyn_cast<JavaObjectType>(
- static_cast<JavaType *>(type.GetOpaqueQualType())))
- return obj->GetLinkageName();
- return ConstString();
-}
diff --git a/source/Symbol/LineEntry.cpp b/source/Symbol/LineEntry.cpp
index 21aa2557518d..bffcc5321b11 100644
--- a/source/Symbol/LineEntry.cpp
+++ b/source/Symbol/LineEntry.cpp
@@ -50,7 +50,6 @@ bool LineEntry::IsValid() const {
}
bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const {
- bool result = false;
if (file) {
if (show_fullpaths)
file.Dump(s);
@@ -59,14 +58,15 @@ bool LineEntry::DumpStopContext(Stream *s, bool show_fullpaths) const {
if (line)
s->PutChar(':');
- result = true;
}
- if (line)
+ if (line) {
s->Printf("%u", line);
- else
- result = false;
-
- return result;
+ if (column) {
+ s->PutChar(':');
+ s->Printf("%u", column);
+ }
+ }
+ return file || line;
}
bool LineEntry::Dump(Stream *s, Target *target, bool show_file,
diff --git a/source/Symbol/OCamlASTContext.cpp b/source/Symbol/OCamlASTContext.cpp
deleted file mode 100644
index 1456ebfa9dce..000000000000
--- a/source/Symbol/OCamlASTContext.cpp
+++ /dev/null
@@ -1,670 +0,0 @@
-//===-- OCamlASTContext.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/Symbol/OCamlASTContext.h"
-#include "lldb/Core/DumpDataExtractor.h"
-#include "lldb/Core/Module.h"
-#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/StreamFile.h"
-#include "lldb/Core/ValueObject.h"
-#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolFile.h"
-#include "lldb/Symbol/Type.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Target.h"
-#include "lldb/Utility/Log.h"
-
-#include "Plugins/SymbolFile/DWARF/DWARFASTParserOCaml.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-namespace lldb_private {
-class OCamlASTContext::OCamlType {
-public:
- enum LLVMCastKind {
- eKindPrimitive,
- eKindObject,
- eKindReference,
- eKindArray,
- kNumKinds
- };
-
- OCamlType(LLVMCastKind kind) : m_kind(kind) {}
-
- virtual ~OCamlType() = default;
-
- virtual ConstString GetName() = 0;
-
- virtual void Dump(Stream *s) = 0;
-
- virtual bool IsCompleteType() = 0;
-
- LLVMCastKind getKind() const { return m_kind; }
-
-private:
- LLVMCastKind m_kind;
-};
-
-} // end of namespace lldb_private
-
-namespace {
-
-class OCamlPrimitiveType : public OCamlASTContext::OCamlType {
-public:
- enum TypeKind {
- eTypeInt,
- };
-
- OCamlPrimitiveType(TypeKind type_kind, uint32_t byte_size)
- : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind),
- m_type(ConstString()), m_byte_size(byte_size) {}
-
- OCamlPrimitiveType(TypeKind type_kind, ConstString s, uint32_t byte_size)
- : OCamlType(OCamlType::eKindPrimitive), m_type_kind(type_kind), m_type(s),
- m_byte_size(byte_size) {}
-
- ConstString GetName() override {
- switch (m_type_kind) {
- case eTypeInt:
- return m_type;
- }
- return ConstString();
- }
-
- TypeKind GetTypeKind() { return m_type_kind; }
-
- void Dump(Stream *s) override { s->Printf("%s\n", GetName().GetCString()); }
-
- bool IsCompleteType() override { return true; }
-
- static bool classof(const OCamlType *ot) {
- return ot->getKind() == OCamlType::eKindPrimitive;
- }
-
- uint64_t GetByteSize() const { return m_byte_size; }
-
-private:
- const TypeKind m_type_kind;
- const ConstString m_type;
- uint64_t m_byte_size;
-};
-}
-
-OCamlASTContext::OCamlASTContext()
- : TypeSystem(eKindOCaml), m_pointer_byte_size(0) {}
-
-OCamlASTContext::~OCamlASTContext() {}
-
-ConstString OCamlASTContext::GetPluginNameStatic() {
- return ConstString("ocaml");
-}
-
-ConstString OCamlASTContext::GetPluginName() {
- return OCamlASTContext::GetPluginNameStatic();
-}
-
-uint32_t OCamlASTContext::GetPluginVersion() { return 1; }
-
-lldb::TypeSystemSP OCamlASTContext::CreateInstance(lldb::LanguageType language,
- Module *module,
- Target *target) {
- Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
-
- if (language == lldb::eLanguageTypeOCaml) {
- std::shared_ptr<OCamlASTContext> ocaml_ast_sp;
- ArchSpec arch;
-
- if (module) {
- arch = module->GetArchitecture();
-
- ObjectFile *objfile = module->GetObjectFile();
- ArchSpec object_arch;
-
- if (!objfile || !objfile->GetArchitecture(object_arch))
- return lldb::TypeSystemSP();
-
- ocaml_ast_sp = std::shared_ptr<OCamlASTContext>(new OCamlASTContext);
-
- if (log) {
- log->Printf(
- "((Module*)%p) [%s]->GetOCamlASTContext() = %p", (void *)module,
- module->GetFileSpec().GetFilename().AsCString("<anonymous>"),
- (void *)ocaml_ast_sp.get());
- }
-
- } else if (target) {
- arch = target->GetArchitecture();
- ocaml_ast_sp = std::shared_ptr<OCamlASTContextForExpr>(
- new OCamlASTContextForExpr(target->shared_from_this()));
-
- if (log) {
- log->Printf("((Target*)%p)->GetOCamlASTContext() = %p", (void *)target,
- (void *)ocaml_ast_sp.get());
- }
- }
-
- if (arch.IsValid()) {
- ocaml_ast_sp->SetAddressByteSize(arch.GetAddressByteSize());
- return ocaml_ast_sp;
- }
- }
-
- return lldb::TypeSystemSP();
-}
-
-void OCamlASTContext::EnumerateSupportedLanguages(
- std::set<lldb::LanguageType> &languages_for_types,
- std::set<lldb::LanguageType> &languages_for_expressions) {
- static std::vector<lldb::LanguageType> s_supported_languages_for_types(
- {lldb::eLanguageTypeOCaml});
- static std::vector<lldb::LanguageType> s_supported_languages_for_expressions(
- {});
-
- languages_for_types.insert(s_supported_languages_for_types.begin(),
- s_supported_languages_for_types.end());
- languages_for_expressions.insert(
- s_supported_languages_for_expressions.begin(),
- s_supported_languages_for_expressions.end());
-}
-
-void OCamlASTContext::Initialize() {
- PluginManager::RegisterPlugin(GetPluginNameStatic(),
- "OCaml AST context plug-in", CreateInstance,
- EnumerateSupportedLanguages);
-}
-
-void OCamlASTContext::Terminate() {
- PluginManager::UnregisterPlugin(CreateInstance);
-}
-
-DWARFASTParser *OCamlASTContext::GetDWARFParser() {
- if (!m_dwarf_ast_parser_ap) {
- m_dwarf_ast_parser_ap.reset(new DWARFASTParserOCaml(*this));
- }
-
- return m_dwarf_ast_parser_ap.get();
-}
-
-bool OCamlASTContext::IsArrayType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size,
- bool *is_incomplete) {
- return false;
-}
-
-bool OCamlASTContext::IsVectorType(lldb::opaque_compiler_type_t type,
- CompilerType *element_type, uint64_t *size) {
- return false;
-}
-
-bool OCamlASTContext::IsAggregateType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsBeingDefined(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsCharType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsCompleteType(lldb::opaque_compiler_type_t type) {
- return static_cast<OCamlPrimitiveType *>(type)->IsCompleteType();
-}
-
-bool OCamlASTContext::IsConst(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsCStringType(lldb::opaque_compiler_type_t type,
- uint32_t &length) {
- return false;
-}
-
-bool OCamlASTContext::IsDefined(lldb::opaque_compiler_type_t type) {
- return type != nullptr;
-}
-
-bool OCamlASTContext::IsFloatingPointType(lldb::opaque_compiler_type_t type,
- uint32_t &count, bool &is_complex) {
- return false;
-}
-
-bool OCamlASTContext::IsFunctionType(lldb::opaque_compiler_type_t type,
- bool *is_variadic_ptr) {
- return false;
-}
-
-uint32_t
-OCamlASTContext::IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
- CompilerType *base_type_ptr) {
- return false;
-}
-
-size_t OCamlASTContext::GetNumberOfFunctionArguments(
- lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-CompilerType
-OCamlASTContext::GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
- const size_t index) {
- return CompilerType();
-}
-
-bool OCamlASTContext::IsFunctionPointerType(lldb::opaque_compiler_type_t type) {
- return IsFunctionType(type);
-}
-
-bool OCamlASTContext::IsBlockPointerType(
- lldb::opaque_compiler_type_t type,
- CompilerType *function_pointer_type_ptr) {
- return false;
-}
-
-bool OCamlASTContext::IsIntegerType(lldb::opaque_compiler_type_t type,
- bool &is_signed) {
- if (OCamlPrimitiveType *ptype =
- llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case OCamlPrimitiveType::eTypeInt:
- is_signed = true;
- return true;
- }
- }
-
- is_signed = false;
- return false;
-}
-
-bool OCamlASTContext::IsPolymorphicClass(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
- CompilerType *target_type,
- bool check_cplusplus,
- bool check_objc) {
- return false;
-}
-
-bool OCamlASTContext::IsRuntimeGeneratedType(
- lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsPointerType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type) {
- if (pointee_type)
- pointee_type->Clear();
- return false;
-}
-
-bool OCamlASTContext::IsPointerOrReferenceType(
- lldb::opaque_compiler_type_t type, CompilerType *pointee_type) {
- return IsPointerType(type, pointee_type);
-}
-
-bool OCamlASTContext::IsReferenceType(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_type,
- bool *is_rvalue) {
- return false;
-}
-
-bool OCamlASTContext::IsScalarType(lldb::opaque_compiler_type_t type) {
- return llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type));
-}
-
-bool OCamlASTContext::IsTypedefType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::IsVoidType(lldb::opaque_compiler_type_t type) {
- return false;
-}
-
-bool OCamlASTContext::SupportsLanguage(lldb::LanguageType language) {
- return language == lldb::eLanguageTypeOCaml;
-}
-
-bool OCamlASTContext::GetCompleteType(lldb::opaque_compiler_type_t type) {
- if (IsCompleteType(type))
- return true;
-
- return false;
-}
-
-uint32_t OCamlASTContext::GetPointerByteSize() { return m_pointer_byte_size; }
-
-ConstString OCamlASTContext::GetTypeName(lldb::opaque_compiler_type_t type) {
- if (type)
- return static_cast<OCamlPrimitiveType *>(type)->GetName();
-
- return ConstString();
-}
-
-uint32_t
-OCamlASTContext::GetTypeInfo(lldb::opaque_compiler_type_t type,
- CompilerType *pointee_or_element_compiler_type) {
- if (pointee_or_element_compiler_type)
- pointee_or_element_compiler_type->Clear();
- if (!type)
- return 0;
-
- if (OCamlPrimitiveType *ptype =
- llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case OCamlPrimitiveType::eTypeInt:
- return eTypeHasValue | eTypeIsBuiltIn | eTypeIsScalar | eTypeIsInteger |
- eTypeIsSigned;
- }
- }
-
- return 0;
-}
-
-lldb::TypeClass
-OCamlASTContext::GetTypeClass(lldb::opaque_compiler_type_t type) {
- if (llvm::isa<OCamlPrimitiveType>(static_cast<OCamlType *>(type)))
- return eTypeClassBuiltin;
-
- return lldb::eTypeClassInvalid;
-}
-
-lldb::BasicType
-OCamlASTContext::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
- return lldb::eBasicTypeInvalid;
-}
-
-lldb::LanguageType
-OCamlASTContext::GetMinimumLanguage(lldb::opaque_compiler_type_t type) {
- return lldb::eLanguageTypeOCaml;
-}
-
-unsigned OCamlASTContext::GetTypeQualifiers(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-//----------------------------------------------------------------------
-// Creating related types
-//----------------------------------------------------------------------
-
-CompilerType
-OCamlASTContext::GetArrayElementType(lldb::opaque_compiler_type_t type,
- uint64_t *stride) {
- return CompilerType();
-}
-
-CompilerType
-OCamlASTContext::GetCanonicalType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-CompilerType
-OCamlASTContext::GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-int OCamlASTContext::GetFunctionArgumentCount(
- lldb::opaque_compiler_type_t type) {
- return GetNumberOfFunctionArguments(type);
-}
-
-CompilerType OCamlASTContext::GetFunctionArgumentTypeAtIndex(
- lldb::opaque_compiler_type_t type, size_t idx) {
- return GetFunctionArgumentAtIndex(type, idx);
-}
-
-CompilerType
-OCamlASTContext::GetFunctionReturnType(lldb::opaque_compiler_type_t type) {
- return CompilerType();
-}
-
-size_t
-OCamlASTContext::GetNumMemberFunctions(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-TypeMemberFunctionImpl
-OCamlASTContext::GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx) {
- return TypeMemberFunctionImpl();
-}
-
-CompilerType
-OCamlASTContext::GetNonReferenceType(lldb::opaque_compiler_type_t type) {
- return CompilerType(this, type);
-}
-
-CompilerType
-OCamlASTContext::GetPointeeType(lldb::opaque_compiler_type_t type) {
- return CompilerType();
-}
-
-CompilerType
-OCamlASTContext::GetPointerType(lldb::opaque_compiler_type_t type) {
- return CompilerType();
-}
-
-CompilerType
-OCamlASTContext::GetTypedefedType(lldb::opaque_compiler_type_t type) {
- return CompilerType();
-}
-
-CompilerType OCamlASTContext::GetBasicTypeFromAST(lldb::BasicType basic_type) {
- return CompilerType();
-}
-
-CompilerType
-OCamlASTContext::GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
- size_t bit_size) {
- return CompilerType();
-}
-
-uint64_t OCamlASTContext::GetBitSize(lldb::opaque_compiler_type_t type,
- ExecutionContextScope *exe_scope) {
- if (OCamlPrimitiveType *ptype =
- llvm::dyn_cast<OCamlPrimitiveType>(static_cast<OCamlType *>(type))) {
- switch (ptype->GetTypeKind()) {
- case OCamlPrimitiveType::eTypeInt:
- return ptype->GetByteSize() * 8;
- }
- }
- return 0;
-}
-
-lldb::Encoding OCamlASTContext::GetEncoding(lldb::opaque_compiler_type_t type,
- uint64_t &count) {
- count = 1;
- bool is_signed;
- if (IsIntegerType(type, is_signed))
- return is_signed ? lldb::eEncodingSint : lldb::eEncodingUint;
- bool is_complex;
- uint32_t complex_count;
- if (IsFloatingPointType(type, complex_count, is_complex)) {
- count = complex_count;
- return lldb::eEncodingIEEE754;
- }
- if (IsPointerType(type))
- return lldb::eEncodingUint;
- return lldb::eEncodingInvalid;
-}
-
-lldb::Format OCamlASTContext::GetFormat(lldb::opaque_compiler_type_t type) {
- if (!type)
- return lldb::eFormatDefault;
- return lldb::eFormatBytes;
-}
-
-size_t OCamlASTContext::GetTypeBitAlign(lldb::opaque_compiler_type_t type) {
- return 0;
-}
-
-uint32_t OCamlASTContext::GetNumChildren(lldb::opaque_compiler_type_t type,
- bool omit_empty_base_classes) {
- if (!type || !GetCompleteType(type))
- return 0;
-
- return GetNumFields(type);
-}
-
-uint32_t OCamlASTContext::GetNumFields(lldb::opaque_compiler_type_t type) {
- if (!type || !GetCompleteType(type))
- return 0;
- return 0;
-}
-
-CompilerType OCamlASTContext::GetFieldAtIndex(lldb::opaque_compiler_type_t type,
- size_t idx, std::string &name,
- uint64_t *bit_offset_ptr,
- uint32_t *bitfield_bit_size_ptr,
- bool *is_bitfield_ptr) {
- if (bit_offset_ptr)
- *bit_offset_ptr = 0;
- if (bitfield_bit_size_ptr)
- *bitfield_bit_size_ptr = 0;
- if (is_bitfield_ptr)
- *is_bitfield_ptr = false;
-
- if (!type || !GetCompleteType(type))
- return CompilerType();
-
- return CompilerType();
-}
-
-CompilerType OCamlASTContext::GetChildCompilerTypeAtIndex(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
- bool transparent_pointers, bool omit_empty_base_classes,
- bool ignore_array_bounds, std::string &child_name,
- uint32_t &child_byte_size, int32_t &child_byte_offset,
- uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
- bool &child_is_base_class, bool &child_is_deref_of_parent,
- ValueObject *valobj, uint64_t &language_flags) {
- child_name.clear();
- child_byte_size = 0;
- child_byte_offset = 0;
- child_bitfield_bit_size = 0;
- child_bitfield_bit_offset = 0;
- child_is_base_class = false;
- child_is_deref_of_parent = false;
- language_flags = 0;
-
- if (!type || !GetCompleteType(type))
- return CompilerType();
-
- return CompilerType();
-}
-
-uint32_t
-OCamlASTContext::GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
- const char *name,
- bool omit_empty_base_classes) {
- if (!type || !GetCompleteType(type))
- return UINT_MAX;
-
- return UINT_MAX;
-}
-
-size_t OCamlASTContext::GetIndexOfChildMemberWithName(
- lldb::opaque_compiler_type_t type, const char *name,
- bool omit_empty_base_classes, std::vector<uint32_t> &child_indexes) {
- uint32_t index = GetIndexOfChildWithName(type, name, omit_empty_base_classes);
- if (index == UINT_MAX)
- return 0;
- child_indexes.push_back(index);
- return 1;
-}
-
-size_t
-OCamlASTContext::ConvertStringToFloatValue(lldb::opaque_compiler_type_t type,
- const char *s, uint8_t *dst,
- size_t dst_size) {
- assert(false);
- return 0;
-}
-//----------------------------------------------------------------------
-// Dumping types
-//----------------------------------------------------------------------
-
-void OCamlASTContext::DumpValue(
- lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, Stream *s,
- lldb::Format format, const DataExtractor &data,
- lldb::offset_t data_byte_offset, size_t data_byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, bool show_types,
- bool show_summary, bool verbose, uint32_t depth) {
- if (!type) {
- s->Printf("no type\n");
- return;
- }
-
- s->Printf("no value\n");
-
- if (show_summary)
- DumpSummary(type, exe_ctx, s, data, data_byte_offset, data_byte_size);
-}
-
-bool OCamlASTContext::DumpTypeValue(
- lldb::opaque_compiler_type_t type, Stream *s, lldb::Format format,
- const DataExtractor &data, lldb::offset_t byte_offset, size_t byte_size,
- uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset,
- ExecutionContextScope *exe_scope) {
- if (!type) {
- s->Printf("no type value\n");
- return false;
- }
-
- if (IsScalarType(type)) {
- return DumpDataExtractor(data, s, byte_offset, format, byte_size, 1,
- SIZE_MAX, LLDB_INVALID_ADDRESS, bitfield_bit_size,
- bitfield_bit_offset, exe_scope);
- }
-
- return false;
-}
-
-void OCamlASTContext::DumpSummary(lldb::opaque_compiler_type_t type,
- ExecutionContext *exe_ctx, Stream *s,
- const DataExtractor &data,
- lldb::offset_t data_offset,
- size_t data_byte_size) {
- s->Printf("no summary\n");
-}
-
-void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type) {
- StreamFile s(stdout, false);
- DumpTypeDescription(type, &s);
-}
-
-void OCamlASTContext::DumpTypeDescription(lldb::opaque_compiler_type_t type,
- Stream *s) {
- static_cast<OCamlType *>(type)->Dump(s);
-}
-
-CompilerType OCamlASTContext::CreateBaseType(const ConstString &name,
- uint64_t byte_size) {
- if (m_base_type_map.empty()) {
- OCamlPrimitiveType *type = new OCamlPrimitiveType(
- OCamlPrimitiveType::eTypeInt, ConstString("ocaml_int"), byte_size);
- m_base_type_map.emplace(type->GetName(),
- std::unique_ptr<OCamlASTContext::OCamlType>(type));
- }
-
- auto it = m_base_type_map.find(name);
- if (it == m_base_type_map.end()) {
- OCamlPrimitiveType *type =
- new OCamlPrimitiveType(OCamlPrimitiveType::eTypeInt, name, byte_size);
- it = m_base_type_map
- .emplace(name, std::unique_ptr<OCamlASTContext::OCamlType>(type))
- .first;
- }
-
- return CompilerType(this, it->second.get());
-}
diff --git a/source/Symbol/ObjectFile.cpp b/source/Symbol/ObjectFile.cpp
index 59012b1f8261..86c18c7beb0b 100644
--- a/source/Symbol/ObjectFile.cpp
+++ b/source/Symbol/ObjectFile.cpp
@@ -19,7 +19,6 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Timer.h"
@@ -47,7 +46,7 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
FileSpec archive_file;
ObjectContainerCreateInstance create_object_container_callback;
- const bool file_exists = file->Exists();
+ const bool file_exists = FileSystem::Instance().Exists(*file);
if (!data_sp) {
// We have an object name which most likely means we have a .o file in
// a static archive (.a file). Try and see if we have a cached archive
@@ -75,8 +74,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
// container plug-ins can use these bytes to see if they can parse this
// file.
if (file_size > 0) {
- data_sp =
- DataBufferLLVM::CreateSliceFromPath(file->GetPath(), 512, file_offset);
+ data_sp = FileSystem::Instance().CreateDataBuffer(file->GetPath(),
+ 512, file_offset);
data_offset = 0;
}
}
@@ -91,7 +90,7 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
const bool must_exist = true;
if (ObjectFile::SplitArchivePathWithObject(
path_with_object, archive_file, archive_object, must_exist)) {
- file_size = archive_file.GetByteSize();
+ file_size = FileSystem::Instance().GetByteSize(archive_file);
if (file_size > 0) {
file = &archive_file;
module_sp->SetFileSpecAndObjectName(archive_file, archive_object);
@@ -120,8 +119,8 @@ ObjectFile::FindPlugin(const lldb::ModuleSP &module_sp, const FileSpec *file,
}
// We failed to find any cached object files in the container plug-
// ins, so lets read the first 512 bytes and try again below...
- data_sp = DataBufferLLVM::CreateSliceFromPath(archive_file.GetPath(),
- 512, file_offset);
+ data_sp = FileSystem::Instance().CreateDataBuffer(
+ archive_file.GetPath(), 512, file_offset);
}
}
}
@@ -209,10 +208,12 @@ size_t ObjectFile::GetModuleSpecifications(const FileSpec &file,
lldb::offset_t file_offset,
lldb::offset_t file_size,
ModuleSpecList &specs) {
- DataBufferSP data_sp = DataBufferLLVM::CreateSliceFromPath(file.GetPath(), 512, file_offset);
+ DataBufferSP data_sp =
+ FileSystem::Instance().CreateDataBuffer(file.GetPath(), 512, file_offset);
if (data_sp) {
if (file_size == 0) {
- const lldb::offset_t actual_file_size = file.GetByteSize();
+ const lldb::offset_t actual_file_size =
+ FileSystem::Instance().GetByteSize(file);
if (actual_file_size > file_offset)
file_size = actual_file_size - file_offset;
}
@@ -344,21 +345,28 @@ AddressClass ObjectFile::GetAddressClass(addr_t file_addr) {
return AddressClass::eData;
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
+ case eSectionTypeDWARFDebugAbbrevDwo:
case eSectionTypeDWARFDebugAddr:
case eSectionTypeDWARFDebugAranges:
case eSectionTypeDWARFDebugCuIndex:
case eSectionTypeDWARFDebugFrame:
case eSectionTypeDWARFDebugInfo:
+ case eSectionTypeDWARFDebugInfoDwo:
case eSectionTypeDWARFDebugLine:
+ case eSectionTypeDWARFDebugLineStr:
case eSectionTypeDWARFDebugLoc:
+ case eSectionTypeDWARFDebugLocLists:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
case eSectionTypeDWARFDebugNames:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
case eSectionTypeDWARFDebugStr:
+ case eSectionTypeDWARFDebugStrDwo:
case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugStrOffsetsDwo:
case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
@@ -578,11 +586,9 @@ bool ObjectFile::SplitArchivePathWithObject(const char *path_with_object,
std::string obj;
if (regex_match.GetMatchAtIndex(path_with_object, 1, path) &&
regex_match.GetMatchAtIndex(path_with_object, 2, obj)) {
- archive_file.SetFile(path, false, FileSpec::Style::native);
+ archive_file.SetFile(path, FileSpec::Style::native);
archive_object.SetCString(obj.c_str());
- if (must_exist && !archive_file.Exists())
- return false;
- return true;
+ return !(must_exist && !FileSystem::Instance().Exists(archive_file));
}
}
return false;
@@ -678,5 +684,65 @@ void ObjectFile::RelocateSection(lldb_private::Section *section)
DataBufferSP ObjectFile::MapFileData(const FileSpec &file, uint64_t Size,
uint64_t Offset) {
- return DataBufferLLVM::CreateSliceFromPath(file.GetPath(), Size, Offset);
+ return FileSystem::Instance().CreateDataBuffer(file.GetPath(), Size, Offset);
+}
+
+void llvm::format_provider<ObjectFile::Type>::format(
+ const ObjectFile::Type &type, raw_ostream &OS, StringRef Style) {
+ switch (type) {
+ case ObjectFile::eTypeInvalid:
+ OS << "invalid";
+ break;
+ case ObjectFile::eTypeCoreFile:
+ OS << "core file";
+ break;
+ case ObjectFile::eTypeExecutable:
+ OS << "executable";
+ break;
+ case ObjectFile::eTypeDebugInfo:
+ OS << "debug info";
+ break;
+ case ObjectFile::eTypeDynamicLinker:
+ OS << "dynamic linker";
+ break;
+ case ObjectFile::eTypeObjectFile:
+ OS << "object file";
+ break;
+ case ObjectFile::eTypeSharedLibrary:
+ OS << "shared library";
+ break;
+ case ObjectFile::eTypeStubLibrary:
+ OS << "stub library";
+ break;
+ case ObjectFile::eTypeJIT:
+ OS << "jit";
+ break;
+ case ObjectFile::eTypeUnknown:
+ OS << "unknown";
+ break;
+ }
+}
+
+void llvm::format_provider<ObjectFile::Strata>::format(
+ const ObjectFile::Strata &strata, raw_ostream &OS, StringRef Style) {
+ switch (strata) {
+ case ObjectFile::eStrataInvalid:
+ OS << "invalid";
+ break;
+ case ObjectFile::eStrataUnknown:
+ OS << "unknown";
+ break;
+ case ObjectFile::eStrataUser:
+ OS << "user";
+ break;
+ case ObjectFile::eStrataKernel:
+ OS << "kernel";
+ break;
+ case ObjectFile::eStrataRawImage:
+ OS << "raw image";
+ break;
+ case ObjectFile::eStrataJIT:
+ OS << "jit";
+ break;
+ }
}
diff --git a/source/Symbol/Symbol.cpp b/source/Symbol/Symbol.cpp
index 69fd5424bd9a..8d055c1c6712 100644
--- a/source/Symbol/Symbol.cpp
+++ b/source/Symbol/Symbol.cpp
@@ -141,7 +141,7 @@ FileSpec Symbol::GetReExportedSymbolSharedLibrary() const {
// 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((const char *)str_ptr);
}
return FileSpec();
}
diff --git a/source/Symbol/SymbolContext.cpp b/source/Symbol/SymbolContext.cpp
index 8716f50a384d..da00875bfa15 100644
--- a/source/Symbol/SymbolContext.cpp
+++ b/source/Symbol/SymbolContext.cpp
@@ -105,12 +105,12 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
if (function != nullptr) {
SymbolContext inline_parent_sc;
Address inline_parent_addr;
- if (show_function_name == false) {
+ if (!show_function_name) {
s->Printf("<");
dumped_something = true;
} else {
ConstString name;
- if (show_function_arguments == false)
+ if (!show_function_arguments)
name = function->GetNameNoArguments();
if (!name)
name = function->GetName();
@@ -122,7 +122,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
const addr_t function_offset =
addr.GetOffset() -
function->GetAddressRange().GetBaseAddress().GetOffset();
- if (show_function_name == false) {
+ if (!show_function_name) {
// Print +offset even if offset is 0
dumped_something = true;
s->Printf("+%" PRIu64 ">", function_offset);
@@ -171,7 +171,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
}
}
} else if (symbol != nullptr) {
- if (show_function_name == false) {
+ if (!show_function_name) {
s->Printf("<");
dumped_something = true;
} else if (symbol->GetName()) {
@@ -184,7 +184,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
if (addr.IsValid() && symbol->ValueIsAddress()) {
const addr_t symbol_offset =
addr.GetOffset() - symbol->GetAddressRef().GetOffset();
- if (show_function_name == false) {
+ if (!show_function_name) {
// Print +offset even if offset is 0
dumped_something = true;
s->Printf("+%" PRIu64 ">", symbol_offset);
@@ -393,12 +393,7 @@ bool lldb_private::operator==(const SymbolContext &lhs,
bool lldb_private::operator!=(const SymbolContext &lhs,
const SymbolContext &rhs) {
- return lhs.function != rhs.function || lhs.symbol != rhs.symbol ||
- lhs.module_sp.get() != rhs.module_sp.get() ||
- lhs.comp_unit != rhs.comp_unit ||
- lhs.target_sp.get() != rhs.target_sp.get() ||
- LineEntry::Compare(lhs.line_entry, rhs.line_entry) != 0 ||
- lhs.variable != rhs.variable;
+ return !(lhs == rhs);
}
bool SymbolContext::GetAddressRange(uint32_t scope, uint32_t range_idx,
@@ -801,14 +796,14 @@ bool SymbolContext::GetAddressRangeFromHereToEndLine(uint32_t end_line,
const Symbol *
SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error) {
error.Clear();
-
+
if (!target_sp) {
return nullptr;
}
-
+
Target &target = *target_sp;
Module *module = module_sp.get();
-
+
auto ProcessMatches = [this, &name, &target, module]
(SymbolContextList &sc_list, Status &error) -> const Symbol* {
llvm::SmallVector<const Symbol *, 1> external_symbols;
@@ -820,7 +815,7 @@ SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error)
if (sym_ctx.symbol) {
const Symbol *symbol = sym_ctx.symbol;
const Address sym_address = symbol->GetAddress();
-
+
if (sym_address.IsValid()) {
switch (symbol->GetType()) {
case eSymbolTypeData:
@@ -865,12 +860,12 @@ SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error)
if (name == symbol->GetReExportedSymbolName() &&
module == reexport_module_sp.get())
return nullptr;
-
+
return FindBestGlobalDataSymbol(
symbol->GetReExportedSymbolName(), error);
}
} break;
-
+
case eSymbolTypeCode: // We already lookup functions elsewhere
case eSymbolTypeVariable:
case eSymbolTypeLocal:
@@ -898,7 +893,7 @@ SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error)
}
}
}
-
+
if (external_symbols.size() > 1) {
StreamString ss;
ss.Printf("Multiple external symbols found for '%s'\n", name.AsCString());
@@ -925,32 +920,32 @@ SymbolContext::FindBestGlobalDataSymbol(const ConstString &name, Status &error)
return nullptr;
}
};
-
+
if (module) {
SymbolContextList sc_list;
module->FindSymbolsWithNameAndType(name, eSymbolTypeAny, sc_list);
const Symbol *const module_symbol = ProcessMatches(sc_list, error);
-
+
if (!error.Success()) {
return nullptr;
} else if (module_symbol) {
return module_symbol;
}
}
-
+
{
SymbolContextList sc_list;
target.GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeAny,
sc_list);
const Symbol *const target_symbol = ProcessMatches(sc_list, error);
-
+
if (!error.Success()) {
return nullptr;
} else if (target_symbol) {
return target_symbol;
}
}
-
+
return nullptr; // no error; we just didn't find anything
}
@@ -999,7 +994,7 @@ bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
break;
case eModuleSpecified: {
// See if we can find the Module, if so stick it in the SymbolContext.
- FileSpec module_file_spec(spec_string, false);
+ FileSpec module_file_spec(spec_string);
ModuleSpec module_spec(module_file_spec);
lldb::ModuleSP module_sp(
m_target_sp->GetImages().FindFirstModule(module_spec));
@@ -1013,7 +1008,7 @@ bool SymbolContextSpecifier::AddSpecification(const char *spec_string,
// CompUnits can't necessarily be resolved here, since an inlined function
// might show up in a number of CompUnits. Instead we just convert to a
// FileSpec and store it away.
- m_file_spec_ap.reset(new FileSpec(spec_string, false));
+ m_file_spec_ap.reset(new FileSpec(spec_string));
m_type |= eFileSpecified;
break;
case eLineStartSpecified:
@@ -1068,7 +1063,7 @@ bool SymbolContextSpecifier::SymbolContextMatches(SymbolContext &sc) {
if (m_module_sp.get() != sc.module_sp.get())
return false;
} else {
- FileSpec module_file_spec(m_module_spec, false);
+ FileSpec module_file_spec(m_module_spec);
if (!FileSpec::Equal(module_file_spec, sc.module_sp->GetFileSpec(),
false))
return false;
@@ -1259,7 +1254,7 @@ bool SymbolContextList::AppendIfUnique(const SymbolContext &sc,
}
if (merge_symbol_into_function && sc.symbol != nullptr &&
sc.comp_unit == nullptr && sc.function == nullptr &&
- sc.block == nullptr && sc.line_entry.IsValid() == false) {
+ sc.block == nullptr && !sc.line_entry.IsValid()) {
if (sc.symbol->ValueIsAddress()) {
for (pos = m_symbol_contexts.begin(); pos != end; ++pos) {
// Don't merge symbols into inlined function symbol contexts
@@ -1285,41 +1280,6 @@ bool SymbolContextList::AppendIfUnique(const SymbolContext &sc,
return true;
}
-bool SymbolContextList::MergeSymbolContextIntoFunctionContext(
- const SymbolContext &symbol_sc, uint32_t start_idx, uint32_t stop_idx) {
- if (symbol_sc.symbol != nullptr && symbol_sc.comp_unit == nullptr &&
- symbol_sc.function == nullptr && symbol_sc.block == nullptr &&
- symbol_sc.line_entry.IsValid() == false) {
- if (symbol_sc.symbol->ValueIsAddress()) {
- const size_t end = std::min<size_t>(m_symbol_contexts.size(), stop_idx);
- for (size_t i = start_idx; i < end; ++i) {
- const SymbolContext &function_sc = m_symbol_contexts[i];
- // Don't merge symbols into inlined function symbol contexts
- if (function_sc.block && function_sc.block->GetContainingInlinedBlock())
- continue;
-
- if (function_sc.function) {
- if (function_sc.function->GetAddressRange().GetBaseAddress() ==
- symbol_sc.symbol->GetAddressRef()) {
- // Do we already have a function with this symbol?
- if (function_sc.symbol == symbol_sc.symbol)
- return true; // Already have a symbol context with this symbol,
- // return true
-
- if (function_sc.symbol == nullptr) {
- // We successfully merged this symbol into an existing symbol
- // context
- m_symbol_contexts[i].symbol = symbol_sc.symbol;
- return true;
- }
- }
- }
- }
- }
- }
- return false;
-}
-
void SymbolContextList::Clear() { m_symbol_contexts.clear(); }
void SymbolContextList::Dump(Stream *s, Target *target) const {
@@ -1346,14 +1306,6 @@ bool SymbolContextList::GetContextAtIndex(size_t idx, SymbolContext &sc) const {
return false;
}
-bool SymbolContextList::GetLastContext(SymbolContext &sc) const {
- if (!m_symbol_contexts.empty()) {
- sc = m_symbol_contexts.back();
- return true;
- }
- return false;
-}
-
bool SymbolContextList::RemoveContextAtIndex(size_t idx) {
if (idx < m_symbol_contexts.size()) {
m_symbol_contexts.erase(m_symbol_contexts.begin() + idx);
diff --git a/source/Symbol/SymbolFile.cpp b/source/Symbol/SymbolFile.cpp
index 6b4da9c53009..6087374969fb 100644
--- a/source/Symbol/SymbolFile.cpp
+++ b/source/Symbol/SymbolFile.cpp
@@ -19,12 +19,18 @@
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-private.h"
+#include <future>
+
using namespace lldb_private;
void SymbolFile::PreloadSymbols() {
// No-op for most implementations.
}
+std::recursive_mutex &SymbolFile::GetModuleMutex() const {
+ return GetObjectFile()->GetModule()->GetMutex();
+}
+
SymbolFile *SymbolFile::FindPlugin(ObjectFile *obj_file) {
std::unique_ptr<SymbolFile> best_symfile_ap;
if (obj_file != nullptr) {
@@ -91,7 +97,7 @@ TypeSystem *SymbolFile::GetTypeSystemForLanguage(lldb::LanguageType language) {
uint32_t SymbolFile::ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line, bool check_inlines,
- uint32_t resolve_scope,
+ lldb::SymbolContextItem resolve_scope,
SymbolContextList &sc_list) {
return 0;
}
@@ -111,7 +117,7 @@ uint32_t SymbolFile::FindGlobalVariables(const RegularExpression &regex,
uint32_t SymbolFile::FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask,
+ lldb::FunctionNameType name_type_mask,
bool include_inlines, bool append,
SymbolContextList &sc_list) {
if (!append)
@@ -134,9 +140,8 @@ void SymbolFile::GetMangledNamesForFunction(
}
uint32_t SymbolFile::FindTypes(
- const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append,
- uint32_t max_matches,
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, uint32_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
if (!append)
@@ -150,3 +155,17 @@ size_t SymbolFile::FindTypes(const std::vector<CompilerContext> &context,
types.Clear();
return 0;
}
+
+void SymbolFile::AssertModuleLock() {
+ // The code below is too expensive to leave enabled in release builds. It's
+ // enabled in debug builds or when the correct macro is set.
+#if defined(LLDB_CONFIGURATION_DEBUG)
+ // We assert that we have to module lock by trying to acquire the lock from a
+ // different thread. Note that we must abort if the result is true to
+ // guarantee correctness.
+ assert(std::async(std::launch::async,
+ [this] { return this->GetModuleMutex().try_lock(); })
+ .get() == false &&
+ "Module is not locked");
+#endif
+}
diff --git a/source/Symbol/SymbolVendor.cpp b/source/Symbol/SymbolVendor.cpp
index 245f7bbf8add..a9badc15a5d6 100644
--- a/source/Symbol/SymbolVendor.cpp
+++ b/source/Symbol/SymbolVendor.cpp
@@ -9,10 +9,6 @@
#include "lldb/Symbol/SymbolVendor.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -61,7 +57,7 @@ SymbolVendor *SymbolVendor::FindPlugin(const lldb::ModuleSP &module_sp,
//----------------------------------------------------------------------
SymbolVendor::SymbolVendor(const lldb::ModuleSP &module_sp)
: ModuleChild(module_sp), m_type_list(), m_compile_units(),
- m_sym_file_ap() {}
+ m_sym_file_ap(), m_symtab() {}
//----------------------------------------------------------------------
// Destructor
@@ -122,63 +118,62 @@ size_t SymbolVendor::GetNumCompileUnits() {
return m_compile_units.size();
}
-lldb::LanguageType
-SymbolVendor::ParseCompileUnitLanguage(const SymbolContext &sc) {
+lldb::LanguageType SymbolVendor::ParseLanguage(CompileUnit &comp_unit) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseCompileUnitLanguage(sc);
+ return m_sym_file_ap->ParseLanguage(comp_unit);
}
return eLanguageTypeUnknown;
}
-size_t SymbolVendor::ParseCompileUnitFunctions(const SymbolContext &sc) {
+size_t SymbolVendor::ParseFunctions(CompileUnit &comp_unit) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseCompileUnitFunctions(sc);
+ return m_sym_file_ap->ParseFunctions(comp_unit);
}
return 0;
}
-bool SymbolVendor::ParseCompileUnitLineTable(const SymbolContext &sc) {
+bool SymbolVendor::ParseLineTable(CompileUnit &comp_unit) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseCompileUnitLineTable(sc);
+ return m_sym_file_ap->ParseLineTable(comp_unit);
}
return false;
}
-bool SymbolVendor::ParseCompileUnitDebugMacros(const SymbolContext &sc) {
+bool SymbolVendor::ParseDebugMacros(CompileUnit &comp_unit) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseCompileUnitDebugMacros(sc);
+ return m_sym_file_ap->ParseDebugMacros(comp_unit);
}
return false;
}
-bool SymbolVendor::ParseCompileUnitSupportFiles(const SymbolContext &sc,
- FileSpecList &support_files) {
+bool SymbolVendor::ParseSupportFiles(CompileUnit &comp_unit,
+ FileSpecList &support_files) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseCompileUnitSupportFiles(sc, support_files);
+ return m_sym_file_ap->ParseSupportFiles(comp_unit, support_files);
}
return false;
}
-bool SymbolVendor::ParseCompileUnitIsOptimized(const SymbolContext &sc) {
+bool SymbolVendor::ParseIsOptimized(CompileUnit &comp_unit) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseCompileUnitIsOptimized(sc);
+ return m_sym_file_ap->ParseIsOptimized(comp_unit);
}
return false;
}
@@ -194,22 +189,22 @@ bool SymbolVendor::ParseImportedModules(
return false;
}
-size_t SymbolVendor::ParseFunctionBlocks(const SymbolContext &sc) {
+size_t SymbolVendor::ParseBlocksRecursive(Function &func) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseFunctionBlocks(sc);
+ return m_sym_file_ap->ParseBlocksRecursive(func);
}
return 0;
}
-size_t SymbolVendor::ParseTypes(const SymbolContext &sc) {
+size_t SymbolVendor::ParseTypes(CompileUnit &comp_unit) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->ParseTypes(sc);
+ return m_sym_file_ap->ParseTypes(comp_unit);
}
return 0;
}
@@ -235,7 +230,7 @@ Type *SymbolVendor::ResolveTypeUID(lldb::user_id_t type_uid) {
}
uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr,
- uint32_t resolve_scope,
+ SymbolContextItem resolve_scope,
SymbolContext &sc) {
ModuleSP module_sp(GetModule());
if (module_sp) {
@@ -248,7 +243,7 @@ uint32_t SymbolVendor::ResolveSymbolContext(const Address &so_addr,
uint32_t SymbolVendor::ResolveSymbolContext(const FileSpec &file_spec,
uint32_t line, bool check_inlines,
- uint32_t resolve_scope,
+ SymbolContextItem resolve_scope,
SymbolContextList &sc_list) {
ModuleSP module_sp(GetModule());
if (module_sp) {
@@ -288,7 +283,7 @@ size_t SymbolVendor::FindGlobalVariables(const RegularExpression &regex,
size_t SymbolVendor::FindFunctions(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx,
- uint32_t name_type_mask,
+ FunctionNameType name_type_mask,
bool include_inlines, bool append,
SymbolContextList &sc_list) {
ModuleSP module_sp(GetModule());
@@ -315,15 +310,15 @@ size_t SymbolVendor::FindFunctions(const RegularExpression &regex,
}
size_t SymbolVendor::FindTypes(
- const SymbolContext &sc, const ConstString &name,
- const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches,
+ const ConstString &name, const CompilerDeclContext *parent_decl_ctx,
+ bool append, size_t max_matches,
llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files,
TypeMap &types) {
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- return m_sym_file_ap->FindTypes(sc, name, parent_decl_ctx, append,
+ return m_sym_file_ap->FindTypes(name, parent_decl_ctx, append,
max_matches, searched_symbol_files,
types);
}
@@ -345,7 +340,7 @@ size_t SymbolVendor::FindTypes(const std::vector<CompilerContext> &context,
return 0;
}
-size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, uint32_t type_mask,
+size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, TypeClass type_mask,
lldb_private::TypeList &type_list) {
ModuleSP module_sp(GetModule());
if (module_sp) {
@@ -357,15 +352,14 @@ size_t SymbolVendor::GetTypes(SymbolContextScope *sc_scope, uint32_t type_mask,
}
CompilerDeclContext
-SymbolVendor::FindNamespace(const SymbolContext &sc, const ConstString &name,
+SymbolVendor::FindNamespace(const ConstString &name,
const CompilerDeclContext *parent_decl_ctx) {
CompilerDeclContext namespace_decl_ctx;
ModuleSP module_sp(GetModule());
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
if (m_sym_file_ap.get())
- namespace_decl_ctx =
- m_sym_file_ap->FindNamespace(sc, name, parent_decl_ctx);
+ namespace_decl_ctx = m_sym_file_ap->FindNamespace(name, parent_decl_ctx);
}
return namespace_decl_ctx;
}
@@ -381,6 +375,7 @@ void SymbolVendor::Dump(Stream *s) {
s->Indent();
s->PutCString("SymbolVendor");
if (m_sym_file_ap.get()) {
+ *s << " " << m_sym_file_ap->GetPluginName();
ObjectFile *objfile = m_sym_file_ap->GetObjectFile();
if (objfile) {
const FileSpec &objfile_file_spec = objfile->GetFileSpec();
@@ -405,6 +400,9 @@ void SymbolVendor::Dump(Stream *s) {
(*cu_pos)->Dump(s, show_context);
}
+ if (Symtab *symtab = GetSymtab())
+ symtab->Dump(s, nullptr, eSortOrderNone);
+
s->IndentLess();
}
}
@@ -438,14 +436,23 @@ FileSpec SymbolVendor::GetMainFileSpec() const {
Symtab *SymbolVendor::GetSymtab() {
ModuleSP module_sp(GetModule());
- if (module_sp) {
- ObjectFile *objfile = module_sp->GetObjectFile();
- if (objfile) {
- // Get symbol table from unified section list.
- return objfile->GetSymtab();
- }
- }
- return nullptr;
+ if (!module_sp)
+ return nullptr;
+
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+
+ if (m_symtab)
+ return m_symtab;
+
+ ObjectFile *objfile = module_sp->GetObjectFile();
+ if (!objfile)
+ return nullptr;
+
+ m_symtab = objfile->GetSymtab();
+ if (m_symtab && m_sym_file_ap)
+ m_sym_file_ap->AddSymbols(*m_symtab);
+
+ return m_symtab;
}
void SymbolVendor::ClearSymtab() {
diff --git a/source/Symbol/Symtab.cpp b/source/Symbol/Symtab.cpp
index c502b18555f0..2472580a41d5 100644
--- a/source/Symbol/Symtab.cpp
+++ b/source/Symbol/Symtab.cpp
@@ -10,9 +10,10 @@
#include <map>
#include <set>
-#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
+
#include "lldb/Core/Module.h"
+#include "lldb/Core/RichManglingContext.h"
#include "lldb/Core/STLUtils.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -23,6 +24,8 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/ADT/StringRef.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -136,6 +139,8 @@ void Symtab::Dump(Stream *s, Target *target, SortOrder sort_order) {
}
break;
}
+ } else {
+ s->PutCString("\n");
}
}
@@ -215,6 +220,40 @@ const Symbol *Symtab::SymbolAtIndex(size_t idx) const {
//----------------------------------------------------------------------
// InitNameIndexes
//----------------------------------------------------------------------
+static bool lldb_skip_name(llvm::StringRef mangled,
+ Mangled::ManglingScheme scheme) {
+ switch (scheme) {
+ case Mangled::eManglingSchemeItanium: {
+ if (mangled.size() < 3 || !mangled.startswith("_Z"))
+ return true;
+
+ // Avoid the following types of symbols in the index.
+ switch (mangled[2]) {
+ case 'G': // guard variables
+ case 'T': // virtual tables, VTT structures, typeinfo structures + names
+ case 'Z': // named local entities (if we eventually handle
+ // eSymbolTypeData, we will want this back)
+ return true;
+
+ default:
+ break;
+ }
+
+ // Include this name in the index.
+ return false;
+ }
+
+ // No filters for this scheme yet. Include all names in indexing.
+ case Mangled::eManglingSchemeMSVC:
+ return false;
+
+ // Don't try and demangle things we can't categorize.
+ case Mangled::eManglingSchemeNone:
+ return true;
+ }
+ llvm_unreachable("unknown scheme!");
+}
+
void Symtab::InitNameIndexes() {
// Protected function, no need to lock mutex...
if (!m_name_indexes_computed) {
@@ -243,16 +282,19 @@ void Symtab::InitNameIndexes() {
m_name_to_index.Reserve(actual_count);
#endif
- NameToIndexMap::Entry entry;
-
- // The "const char *" in "class_contexts" must come from a
- // ConstString::GetCString()
+ // The "const char *" in "class_contexts" and backlog::value_type::second
+ // must come from a ConstString::GetCString()
std::set<const char *> class_contexts;
- UniqueCStringMap<uint32_t> mangled_name_to_index;
- std::vector<const char *> symbol_contexts(num_symbols, nullptr);
+ std::vector<std::pair<NameToIndexMap::Entry, const char *>> backlog;
+ backlog.reserve(num_symbols / 2);
+
+ // Instantiation of the demangler is expensive, so better use a single one
+ // for all entries during batch processing.
+ RichManglingContext rmc;
+ NameToIndexMap::Entry entry;
for (entry.value = 0; entry.value < num_symbols; ++entry.value) {
- const Symbol *symbol = &m_symbols[entry.value];
+ Symbol *symbol = &m_symbols[entry.value];
// Don't let trampolines get into the lookup by name map If we ever need
// the trampoline symbols to be searchable by name we can remove this and
@@ -261,7 +303,9 @@ void Symtab::InitNameIndexes() {
if (symbol->IsTrampoline())
continue;
- const Mangled &mangled = symbol->GetMangled();
+ // If the symbol's name string matched a Mangled::ManglingScheme, it is
+ // stored in the mangled field.
+ Mangled &mangled = symbol->GetMangled();
entry.cstring = mangled.GetMangledName();
if (entry.cstring) {
m_name_to_index.Append(entry);
@@ -274,70 +318,15 @@ void Symtab::InitNameIndexes() {
m_name_to_index.Append(entry);
}
- const SymbolType symbol_type = symbol->GetType();
- if (symbol_type == eSymbolTypeCode ||
- symbol_type == eSymbolTypeResolver) {
- llvm::StringRef entry_ref(entry.cstring.GetStringRef());
- if (entry_ref[0] == '_' && entry_ref[1] == 'Z' &&
- (entry_ref[2] != 'T' && // avoid virtual table, VTT structure,
- // typeinfo structure, and typeinfo
- // name
- entry_ref[2] != 'G' && // avoid guard variables
- entry_ref[2] != 'Z')) // named local entities (if we
- // eventually handle eSymbolTypeData,
- // we will want this back)
- {
- CPlusPlusLanguage::MethodName cxx_method(
- mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus));
- entry.cstring = ConstString(cxx_method.GetBasename());
- if (entry.cstring) {
- // ConstString objects permanently store the string in the pool
- // so calling GetCString() on the value gets us a const char *
- // that will never go away
- const char *const_context =
- ConstString(cxx_method.GetContext()).GetCString();
-
- if (!const_context || const_context[0] == 0) {
- // No context for this function so this has to be a basename
- m_basename_to_index.Append(entry);
- // If there is no context (no namespaces or class scopes that
- // come before the function name) then this also could be a
- // fullname.
- m_name_to_index.Append(entry);
- } else {
- entry_ref = entry.cstring.GetStringRef();
- if (entry_ref[0] == '~' ||
- !cxx_method.GetQualifiers().empty()) {
- // The first character of the demangled basename is '~' which
- // means we have a class destructor. We can use this
- // information to help us know what is a class and what
- // isn't.
- if (class_contexts.find(const_context) == class_contexts.end())
- class_contexts.insert(const_context);
- m_method_to_index.Append(entry);
- } else {
- if (class_contexts.find(const_context) !=
- class_contexts.end()) {
- // The current decl context is in our "class_contexts"
- // which means this is a method on a class
- m_method_to_index.Append(entry);
- } else {
- // We don't know if this is a function basename or a
- // method, so put it into a temporary collection so once we
- // are done we can look in class_contexts to see if each
- // entry is a class or just a function and will put any
- // remaining items into m_method_to_index or
- // m_basename_to_index as needed
- mangled_name_to_index.Append(entry);
- symbol_contexts[entry.value] = const_context;
- }
- }
- }
- }
- }
+ const SymbolType type = symbol->GetType();
+ if (type == eSymbolTypeCode || type == eSymbolTypeResolver) {
+ if (mangled.DemangleWithRichManglingInfo(rmc, lldb_skip_name))
+ RegisterMangledNameEntry(entry, class_contexts, backlog, rmc);
}
}
+ // Symbol name strings that didn't match a Mangled::ManglingScheme, are
+ // stored in the demangled field.
entry.cstring = mangled.GetDemangledName(symbol->GetLanguage());
if (entry.cstring) {
m_name_to_index.Append(entry);
@@ -367,25 +356,10 @@ void Symtab::InitNameIndexes() {
}
}
- size_t count;
- if (!mangled_name_to_index.IsEmpty()) {
- count = mangled_name_to_index.GetSize();
- for (size_t i = 0; i < count; ++i) {
- if (mangled_name_to_index.GetValueAtIndex(i, entry.value)) {
- entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
- if (symbol_contexts[entry.value] &&
- class_contexts.find(symbol_contexts[entry.value]) !=
- class_contexts.end()) {
- m_method_to_index.Append(entry);
- } else {
- // If we got here, we have something that had a context (was inside
- // a namespace or class) yet we don't know if the entry
- m_method_to_index.Append(entry);
- m_basename_to_index.Append(entry);
- }
- }
- }
+ for (const auto &record : backlog) {
+ RegisterBacklogEntry(record.first, record.second, class_contexts);
}
+
m_name_to_index.Sort();
m_name_to_index.SizeToFit();
m_selector_to_index.Sort();
@@ -397,6 +371,71 @@ void Symtab::InitNameIndexes() {
}
}
+void Symtab::RegisterMangledNameEntry(
+ NameToIndexMap::Entry &entry, std::set<const char *> &class_contexts,
+ std::vector<std::pair<NameToIndexMap::Entry, const char *>> &backlog,
+ RichManglingContext &rmc) {
+ // Only register functions that have a base name.
+ rmc.ParseFunctionBaseName();
+ llvm::StringRef base_name = rmc.GetBufferRef();
+ if (base_name.empty())
+ return;
+
+ // The base name will be our entry's name.
+ entry.cstring = ConstString(base_name);
+
+ rmc.ParseFunctionDeclContextName();
+ llvm::StringRef decl_context = rmc.GetBufferRef();
+
+ // Register functions with no context.
+ if (decl_context.empty()) {
+ // This has to be a basename
+ m_basename_to_index.Append(entry);
+ // If there is no context (no namespaces or class scopes that come before
+ // the function name) then this also could be a fullname.
+ m_name_to_index.Append(entry);
+ return;
+ }
+
+ // Make sure we have a pool-string pointer and see if we already know the
+ // context name.
+ const char *decl_context_ccstr = ConstString(decl_context).GetCString();
+ auto it = class_contexts.find(decl_context_ccstr);
+
+ // Register constructors and destructors. They are methods and create
+ // declaration contexts.
+ if (rmc.IsCtorOrDtor()) {
+ m_method_to_index.Append(entry);
+ if (it == class_contexts.end())
+ class_contexts.insert(it, decl_context_ccstr);
+ return;
+ }
+
+ // Register regular methods with a known declaration context.
+ if (it != class_contexts.end()) {
+ m_method_to_index.Append(entry);
+ return;
+ }
+
+ // Regular methods in unknown declaration contexts are put to the backlog. We
+ // will revisit them once we processed all remaining symbols.
+ backlog.push_back(std::make_pair(entry, decl_context_ccstr));
+}
+
+void Symtab::RegisterBacklogEntry(
+ const NameToIndexMap::Entry &entry, const char *decl_context,
+ const std::set<const char *> &class_contexts) {
+ auto it = class_contexts.find(decl_context);
+ if (it != class_contexts.end()) {
+ m_method_to_index.Append(entry);
+ } else {
+ // If we got here, we have something that had a context (was inside
+ // a namespace or class) yet we don't know the entry
+ m_method_to_index.Append(entry);
+ m_basename_to_index.Append(entry);
+ }
+}
+
void Symtab::PreloadSymbols() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
InitNameIndexes();
@@ -571,10 +610,9 @@ void Symtab::SortSymbolIndexesByValue(std::vector<uint32_t> &indexes,
return;
// Sort the indexes in place using std::stable_sort.
- // NOTE: The use of std::stable_sort instead of std::sort here is strictly for
- // performance,
- // not correctness. The indexes vector tends to be "close" to sorted, which
- // the stable sort handles better.
+ // NOTE: The use of std::stable_sort instead of llvm::sort here is strictly
+ // for performance, not correctness. The indexes vector tends to be "close"
+ // to sorted, which the stable sort handles better.
std::vector<lldb::addr_t> addr_cache(m_symbols.size(), LLDB_INVALID_ADDRESS);
@@ -701,7 +739,7 @@ uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType(
for (uint32_t i = 0; i < sym_end; i++) {
if (symbol_type == eSymbolTypeAny ||
m_symbols[i].GetType() == symbol_type) {
- if (CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility) == false)
+ if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility))
continue;
const char *name = m_symbols[i].GetName().AsCString();
@@ -937,32 +975,8 @@ void Symtab::InitAddressIndexes() {
void Symtab::CalculateSymbolSizes() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
-
- if (!m_symbols.empty()) {
- if (!m_file_addr_to_index_computed)
- InitAddressIndexes();
-
- const size_t num_entries = m_file_addr_to_index.GetSize();
-
- for (size_t i = 0; i < num_entries; ++i) {
- // The entries in the m_file_addr_to_index have calculated the sizes
- // already so we will use this size if we need to.
- const FileRangeToIndexMap::Entry &entry =
- m_file_addr_to_index.GetEntryRef(i);
-
- Symbol &symbol = m_symbols[entry.data];
-
- // If the symbol size is already valid, no need to do anything
- if (symbol.GetByteSizeIsValid())
- continue;
-
- const addr_t range_size = entry.GetByteSize();
- if (range_size > 0) {
- symbol.SetByteSize(range_size);
- symbol.SetSizeIsSynthesized(true);
- }
- }
- }
+ // Size computation happens inside InitAddressIndexes.
+ InitAddressIndexes();
}
Symbol *Symtab::FindSymbolAtFileAddress(addr_t file_addr) {
@@ -1117,7 +1131,7 @@ size_t Symtab::FindFunctionSymbols(const ConstString &name,
}
if (!symbol_indexes.empty()) {
- std::sort(symbol_indexes.begin(), symbol_indexes.end());
+ llvm::sort(symbol_indexes.begin(), symbol_indexes.end());
symbol_indexes.erase(
std::unique(symbol_indexes.begin(), symbol_indexes.end()),
symbol_indexes.end());
diff --git a/source/Symbol/Type.cpp b/source/Symbol/Type.cpp
index b62c55f76e2b..e966c269408a 100644
--- a/source/Symbol/Type.cpp
+++ b/source/Symbol/Type.cpp
@@ -7,16 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdio.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Symbol/CompilerType.h"
@@ -325,15 +321,16 @@ uint64_t Type::GetByteSize() {
if (encoding_type)
m_byte_size = encoding_type->GetByteSize();
if (m_byte_size == 0)
- m_byte_size = GetLayoutCompilerType().GetByteSize(nullptr);
+ if (llvm::Optional<uint64_t> size =
+ GetLayoutCompilerType().GetByteSize(nullptr))
+ m_byte_size = *size;
} break;
// If we are a pointer or reference, then this is just a pointer size;
case eEncodingIsPointerUID:
case eEncodingIsLValueReferenceUID:
case eEncodingIsRValueReferenceUID: {
- ArchSpec arch;
- if (m_symbol_file->GetObjectFile()->GetArchitecture(arch))
+ if (ArchSpec arch = m_symbol_file->GetObjectFile()->GetArchitecture())
m_byte_size = arch.GetAddressByteSize();
} break;
}
@@ -342,7 +339,7 @@ uint64_t Type::GetByteSize() {
}
uint32_t Type::GetNumChildren(bool omit_empty_base_classes) {
- return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes);
+ return GetForwardCompilerType().GetNumChildren(omit_empty_base_classes, nullptr);
}
bool Type::IsAggregateType() {
@@ -714,11 +711,7 @@ bool TypeAndOrName::operator==(const TypeAndOrName &other) const {
}
bool TypeAndOrName::operator!=(const TypeAndOrName &other) const {
- if (m_type_pair != other.m_type_pair)
- return true;
- if (m_type_name != other.m_type_name)
- return true;
- return false;
+ return !(*this == other);
}
ConstString TypeAndOrName::GetName() const {
@@ -750,10 +743,7 @@ void TypeAndOrName::SetCompilerType(CompilerType compiler_type) {
}
bool TypeAndOrName::IsEmpty() const {
- if ((bool)m_type_name || (bool)m_type_pair)
- return false;
- else
- return true;
+ return !((bool)m_type_name || (bool)m_type_pair);
}
void TypeAndOrName::Clear() {
@@ -878,8 +868,7 @@ bool TypeImpl::operator==(const TypeImpl &rhs) const {
}
bool TypeImpl::operator!=(const TypeImpl &rhs) const {
- return m_static_type != rhs.m_static_type ||
- m_dynamic_type != rhs.m_dynamic_type;
+ return !(*this == rhs);
}
bool TypeImpl::IsValid() const {
diff --git a/source/Symbol/TypeList.cpp b/source/Symbol/TypeList.cpp
index 4a0a06f3e8e3..26a646e64693 100644
--- a/source/Symbol/TypeList.cpp
+++ b/source/Symbol/TypeList.cpp
@@ -7,15 +7,11 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
-// Project includes
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
@@ -184,8 +180,7 @@ void TypeList::RemoveMismatchedTypes(const std::string &type_scope,
} else {
// The type we are currently looking at doesn't exists in a namespace
// or class, so it only matches if there is no type scope...
- keep_match =
- type_scope.empty() && type_basename.compare(match_type_name) == 0;
+ keep_match = type_scope.empty() && type_basename == match_type_name;
}
}
diff --git a/source/Symbol/TypeMap.cpp b/source/Symbol/TypeMap.cpp
index 2838039ad603..337278c202ed 100644
--- a/source/Symbol/TypeMap.cpp
+++ b/source/Symbol/TypeMap.cpp
@@ -7,11 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
@@ -27,7 +24,6 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
-// Project includes
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
@@ -227,8 +223,7 @@ void TypeMap::RemoveMismatchedTypes(const std::string &type_scope,
} else {
// The type we are currently looking at doesn't exists in a namespace
// or class, so it only matches if there is no type scope...
- keep_match =
- type_scope.empty() && type_basename.compare(match_type_name) == 0;
+ keep_match = type_scope.empty() && type_basename == match_type_name;
}
}
diff --git a/source/Symbol/TypeSystem.cpp b/source/Symbol/TypeSystem.cpp
index b99f21e1e347..91d347edfc79 100644
--- a/source/Symbol/TypeSystem.cpp
+++ b/source/Symbol/TypeSystem.cpp
@@ -101,6 +101,10 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) {
return CompilerType(this, type);
}
+size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
+ return 0;
+}
+
TemplateArgumentKind
TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) {
return eTemplateArgumentKindNull;
@@ -189,7 +193,7 @@ void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) {
TypeSystem *type_system = pair.second.get();
if (type_system && !visited.count(type_system)) {
visited.insert(type_system);
- if (callback(type_system) == false)
+ if (!callback(type_system))
break;
}
}
diff --git a/source/Symbol/UnwindPlan.cpp b/source/Symbol/UnwindPlan.cpp
index 23ca1324ab06..0f8d9bf7e5a4 100644
--- a/source/Symbol/UnwindPlan.cpp
+++ b/source/Symbol/UnwindPlan.cpp
@@ -29,6 +29,8 @@ operator==(const UnwindPlan::Row::RegisterLocation &rhs) const {
case atCFAPlusOffset:
case isCFAPlusOffset:
+ case atAFAPlusOffset:
+ case isAFAPlusOffset:
return m_location.offset == rhs.m_location.offset;
case inOtherRegister:
@@ -95,6 +97,16 @@ void UnwindPlan::Row::RegisterLocation::Dump(Stream &s,
s.PutChar(']');
} break;
+ case atAFAPlusOffset:
+ case isAFAPlusOffset: {
+ s.PutChar('=');
+ if (m_type == atAFAPlusOffset)
+ s.PutChar('[');
+ s.Printf("AFA%+d", m_location.offset);
+ if (m_type == atAFAPlusOffset)
+ s.PutChar(']');
+ } break;
+
case inOtherRegister: {
const RegisterInfo *other_reg_info = nullptr;
if (unwind_plan)
@@ -125,8 +137,8 @@ static void DumpRegisterName(Stream &s, const UnwindPlan *unwind_plan,
s.Printf("reg(%u)", reg_num);
}
-bool UnwindPlan::Row::CFAValue::
-operator==(const UnwindPlan::Row::CFAValue &rhs) const {
+bool UnwindPlan::Row::FAValue::
+operator==(const UnwindPlan::Row::FAValue &rhs) const {
if (m_type == rhs.m_type) {
switch (m_type) {
case unspecified:
@@ -148,7 +160,7 @@ operator==(const UnwindPlan::Row::CFAValue &rhs) const {
return false;
}
-void UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
+void UnwindPlan::Row::FAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
Thread *thread) const {
switch (m_type) {
case isRegisterPlusOffset:
@@ -171,6 +183,7 @@ void UnwindPlan::Row::CFAValue::Dump(Stream &s, const UnwindPlan *unwind_plan,
void UnwindPlan::Row::Clear() {
m_cfa_value.SetUnspecified();
+ m_afa_value.SetUnspecified();
m_offset = 0;
m_register_locations.clear();
}
@@ -183,6 +196,12 @@ void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
s.Printf("%4" PRId64 ": CFA=", GetOffset());
m_cfa_value.Dump(s, unwind_plan, thread);
+
+ if (!m_afa_value.IsUnspecified()) {
+ s.Printf(" AFA=");
+ m_afa_value.Dump(s, unwind_plan, thread);
+ }
+
s.Printf(" => ");
for (collection::const_iterator idx = m_register_locations.begin();
idx != m_register_locations.end(); ++idx) {
@@ -194,7 +213,8 @@ void UnwindPlan::Row::Dump(Stream &s, const UnwindPlan *unwind_plan,
s.EOL();
}
-UnwindPlan::Row::Row() : m_offset(0), m_cfa_value(), m_register_locations() {}
+UnwindPlan::Row::Row()
+ : m_offset(0), m_cfa_value(), m_afa_value(), m_register_locations() {}
bool UnwindPlan::Row::GetRegisterInfo(
uint32_t reg_num,
@@ -296,8 +316,10 @@ bool UnwindPlan::Row::SetRegisterLocationToSame(uint32_t reg_num,
}
bool UnwindPlan::Row::operator==(const UnwindPlan::Row &rhs) const {
- return m_offset == rhs.m_offset && m_cfa_value == rhs.m_cfa_value &&
- m_register_locations == rhs.m_register_locations;
+ return m_offset == rhs.m_offset &&
+ m_cfa_value == rhs.m_cfa_value &&
+ m_afa_value == rhs.m_afa_value &&
+ m_register_locations == rhs.m_register_locations;
}
void UnwindPlan::AppendRow(const UnwindPlan::RowSP &row_sp) {
@@ -399,7 +421,7 @@ bool UnwindPlan::PlanValidAtAddress(Address addr) {
// UnwindPlan.
if (GetRowAtIndex(0).get() == nullptr ||
GetRowAtIndex(0)->GetCFAValue().GetValueType() ==
- Row::CFAValue::unspecified) {
+ Row::FAValue::unspecified) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND));
if (log) {
StreamString s;
diff --git a/source/Symbol/UnwindTable.cpp b/source/Symbol/UnwindTable.cpp
index 7f98eaca2521..4f0b875c5c6f 100644
--- a/source/Symbol/UnwindTable.cpp
+++ b/source/Symbol/UnwindTable.cpp
@@ -180,8 +180,8 @@ ArmUnwindInfo *UnwindTable::GetArmUnwindInfo() {
return m_arm_unwind_up.get();
}
-bool UnwindTable::GetArchitecture(lldb_private::ArchSpec &arch) {
- return m_object_file.GetArchitecture(arch);
+ArchSpec UnwindTable::GetArchitecture() {
+ return m_object_file.GetArchitecture();
}
bool UnwindTable::GetAllowAssemblyEmulationUnwindPlans() {
diff --git a/source/Symbol/Variable.cpp b/source/Symbol/Variable.cpp
index af84872a97a0..ffed48a33bf1 100644
--- a/source/Symbol/Variable.cpp
+++ b/source/Symbol/Variable.cpp
@@ -50,7 +50,8 @@ Variable::Variable(
m_symfile_type_sp(symfile_type_sp), m_scope(scope),
m_owner_scope(context), m_scope_range(scope_range),
m_declaration(decl_ptr), m_location(location), m_external(external),
- m_artificial(artificial), m_static_member(static_member) {}
+ m_artificial(artificial), m_loc_is_const_data(false),
+ m_static_member(static_member) {}
//----------------------------------------------------------------------
// Destructor
@@ -156,14 +157,14 @@ void Variable::Dump(Stream *s, bool show_context) const {
.GetBaseAddress()
.GetFileAddress();
}
- ABI *abi = nullptr;
+ ABISP abi;
if (m_owner_scope) {
ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
if (module_sp)
- abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture()).get();
+ abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
}
m_location.GetDescription(s, lldb::eDescriptionLevelBrief,
- loclist_base_addr, abi);
+ loclist_base_addr, abi.get());
}
if (m_external)
@@ -458,11 +459,11 @@ bool Variable::DumpLocationForAddress(Stream *s, const Address &address) {
SymbolContext sc;
CalculateSymbolContext(&sc);
if (sc.module_sp == address.GetModule()) {
- ABI *abi = nullptr;
+ ABISP abi;
if (m_owner_scope) {
ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
if (module_sp)
- abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture()).get();
+ abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
}
const addr_t file_addr = address.GetFileAddress();
@@ -474,11 +475,12 @@ bool Variable::DumpLocationForAddress(Stream *s, const Address &address) {
return false;
return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief,
loclist_base_file_addr,
- file_addr, abi);
+ file_addr, abi.get());
}
}
- return m_location.DumpLocationForAddress(
- s, eDescriptionLevelBrief, LLDB_INVALID_ADDRESS, file_addr, abi);
+ return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief,
+ LLDB_INVALID_ADDRESS, file_addr,
+ abi.get());
}
}
return false;
@@ -603,7 +605,7 @@ static void PrivateAutoComplete(
case eTypeClassObjCObjectPointer:
case eTypeClassPointer: {
bool omit_empty_base_classes = true;
- if (compiler_type.GetNumChildren(omit_empty_base_classes) > 0)
+ if (compiler_type.GetNumChildren(omit_empty_base_classes, nullptr) > 0)
matches.AppendString((prefix_path + "->").str());
else {
matches.AppendString(prefix_path.str());
diff --git a/source/Target/ABI.cpp b/source/Target/ABI.cpp
index 8d4513ad6811..96e09b75094a 100644
--- a/source/Target/ABI.cpp
+++ b/source/Target/ABI.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ABI.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
#include "lldb/Core/PluginManager.h"
diff --git a/source/Target/CMakeLists.txt b/source/Target/CMakeLists.txt
index df137c314afa..265b3a80779d 100644
--- a/source/Target/CMakeLists.txt
+++ b/source/Target/CMakeLists.txt
@@ -28,6 +28,7 @@ add_lldb_library(lldbTarget
SectionLoadList.cpp
StackFrame.cpp
StackFrameList.cpp
+ StackFrameRecognizer.cpp
StackID.cpp
StopInfo.cpp
StructuredDataPlugin.cpp
diff --git a/source/Target/CPPLanguageRuntime.cpp b/source/Target/CPPLanguageRuntime.cpp
index c7e7b2511971..f0bd1758461c 100644
--- a/source/Target/CPPLanguageRuntime.cpp
+++ b/source/Target/CPPLanguageRuntime.cpp
@@ -14,9 +14,19 @@
#include "llvm/ADT/StringRef.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/VariableList.h"
+
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
using namespace lldb;
using namespace lldb_private;
@@ -40,3 +50,297 @@ bool CPPLanguageRuntime::GetObjectDescription(
// C++ has no generic way to do this.
return false;
}
+
+CPPLanguageRuntime::LibCppStdFunctionCallableInfo
+CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
+ lldb::ValueObjectSP &valobj_sp) {
+ LibCppStdFunctionCallableInfo optional_info;
+
+ if (!valobj_sp)
+ return optional_info;
+
+ // Member __f_ has type __base*, the contents of which will hold:
+ // 1) a vtable entry which may hold type information needed to discover the
+ // lambda being called
+ // 2) possibly hold a pointer to the callable object
+ // e.g.
+ //
+ // (lldb) frame var -R f_display
+ // (std::__1::function<void (int)>) f_display = {
+ // __buf_ = {
+ // …
+ // }
+ // __f_ = 0x00007ffeefbffa00
+ // }
+ // (lldb) memory read -fA 0x00007ffeefbffa00
+ // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
+ // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
+ //
+ // We will be handling five cases below, std::function is wrapping:
+ //
+ // 1) a lambda we know at compile time. We will obtain the name of the lambda
+ // from the first template pameter from __func's vtable. We will look up
+ // the lambda's operator()() and obtain the line table entry.
+ // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
+ // will be stored after the vtable. We will obtain the lambdas name from
+ // this entry and lookup operator()() and obtain the line table entry.
+ // 3) a callable object via operator()(). We will obtain the name of the
+ // object from the first template parameter from __func's vtable. We will
+ // look up the objectc operator()() and obtain the line table entry.
+ // 4) a member function. A pointer to the function will stored after the
+ // we will obtain the name from this pointer.
+ // 5) a free function. A pointer to the function will stored after the vtable
+ // we will obtain the name from this pointer.
+ ValueObjectSP member__f_(
+ valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));
+
+ if (member__f_) {
+ ValueObjectSP sub_member__f_(
+ member__f_->GetChildMemberWithName(ConstString("__f_"), true));
+
+ if (sub_member__f_)
+ member__f_ = sub_member__f_;
+ }
+
+ lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);
+
+ optional_info.member__f_pointer_value = member__f_pointer_value;
+
+ ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == nullptr)
+ return optional_info;
+
+ uint32_t address_size = process->GetAddressByteSize();
+ Status status;
+
+ // First item pointed to by __f_ should be the pointer to the vtable for
+ // a __base object.
+ lldb::addr_t vtable_address =
+ process->ReadPointerFromMemory(member__f_pointer_value, status);
+
+ if (status.Fail())
+ return optional_info;
+
+ lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
+ // As commened above we may not have a function pointer but if we do we will
+ // need it.
+ lldb::addr_t possible_function_address =
+ process->ReadPointerFromMemory(address_after_vtable, status);
+
+ if (status.Fail())
+ return optional_info;
+
+ Target &target = process->GetTarget();
+
+ if (target.GetSectionLoadList().IsEmpty())
+ return optional_info;
+
+ Address vtable_addr_resolved;
+ SymbolContext sc;
+ Symbol *symbol;
+
+ if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
+ vtable_addr_resolved))
+ return optional_info;
+
+ target.GetImages().ResolveSymbolContextForAddress(
+ vtable_addr_resolved, eSymbolContextEverything, sc);
+ symbol = sc.symbol;
+
+ if (symbol == nullptr)
+ return optional_info;
+
+ llvm::StringRef vtable_name(symbol->GetName().GetCString());
+ bool found_expected_start_string =
+ vtable_name.startswith("vtable for std::__1::__function::__func<");
+
+ if (!found_expected_start_string)
+ return optional_info;
+
+ // Given case 1 or 3 we have a vtable name, we are want to extract the first
+ // template parameter
+ //
+ // ... __func<main::$_0, std::__1::allocator<main::$_0> ...
+ // ^^^^^^^^^
+ //
+ // We do this by find the first < and , and extracting in between.
+ //
+ // This covers the case of the lambda known at compile time.
+ size_t first_open_angle_bracket = vtable_name.find('<') + 1;
+ size_t first_comma = vtable_name.find_first_of(',');
+
+ llvm::StringRef first_template_parameter =
+ vtable_name.slice(first_open_angle_bracket, first_comma);
+
+ Address function_address_resolved;
+
+ // Setup for cases 2, 4 and 5 we have a pointer to a function after the
+ // vtable. We will use a process of elimination to drop through each case
+ // and obtain the data we need.
+ if (target.GetSectionLoadList().ResolveLoadAddress(
+ possible_function_address, function_address_resolved)) {
+ target.GetImages().ResolveSymbolContextForAddress(
+ function_address_resolved, eSymbolContextEverything, sc);
+ symbol = sc.symbol;
+ }
+
+ auto get_name = [&first_template_parameter, &symbol]() {
+ // Given case 1:
+ //
+ // main::$_0
+ //
+ // we want to append ::operator()()
+ if (first_template_parameter.contains("$_"))
+ return llvm::Regex::escape(first_template_parameter.str()) +
+ R"(::operator\(\)\(.*\))";
+
+ if (symbol != NULL &&
+ symbol->GetName().GetStringRef().contains("__invoke")) {
+
+ llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
+ size_t pos2 = symbol_name.find_last_of(':');
+
+ // Given case 2:
+ //
+ // main::$_1::__invoke(...)
+ //
+ // We want to slice off __invoke(...) and append operator()()
+ std::string lambda_operator =
+ llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
+ R"(operator\(\)\(.*\))";
+
+ return lambda_operator;
+ }
+
+ // Case 3
+ return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
+ ;
+ };
+
+ std::string func_to_match = get_name();
+
+ SymbolContextList scl;
+
+ target.GetImages().FindFunctions(RegularExpression{func_to_match}, true, true,
+ true, scl);
+
+ // Case 1,2 or 3
+ if (scl.GetSize() >= 1) {
+ SymbolContext sc2 = scl[0];
+
+ AddressRange range;
+ sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);
+
+ Address address = range.GetBaseAddress();
+
+ Address addr;
+ if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
+ addr)) {
+ LineEntry line_entry;
+ addr.CalculateSymbolContextLineEntry(line_entry);
+
+ if (first_template_parameter.contains("$_") ||
+ (symbol != nullptr &&
+ symbol->GetName().GetStringRef().contains("__invoke"))) {
+ // Case 1 and 2
+ optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
+ } else {
+ // Case 3
+ optional_info.callable_case =
+ LibCppStdFunctionCallableCase::CallableObject;
+ }
+
+ optional_info.callable_symbol = *symbol;
+ optional_info.callable_line_entry = line_entry;
+ optional_info.callable_address = addr;
+ return optional_info;
+ }
+ }
+
+ // Case 4 or 5
+ if (!symbol->GetName().GetStringRef().startswith("vtable for")) {
+ optional_info.callable_case =
+ LibCppStdFunctionCallableCase::FreeOrMemberFunction;
+ optional_info.callable_address = function_address_resolved;
+ optional_info.callable_symbol = *symbol;
+
+ return optional_info;
+ }
+
+ return optional_info;
+}
+
+lldb::ThreadPlanSP
+CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
+ bool stop_others) {
+ ThreadPlanSP ret_plan_sp;
+
+ lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
+
+ TargetSP target_sp(thread.CalculateTarget());
+
+ if (target_sp->GetSectionLoadList().IsEmpty())
+ return ret_plan_sp;
+
+ Address pc_addr_resolved;
+ SymbolContext sc;
+ Symbol *symbol;
+
+ if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
+ pc_addr_resolved))
+ return ret_plan_sp;
+
+ target_sp->GetImages().ResolveSymbolContextForAddress(
+ pc_addr_resolved, eSymbolContextEverything, sc);
+ symbol = sc.symbol;
+
+ if (symbol == nullptr)
+ return ret_plan_sp;
+
+ llvm::StringRef function_name(symbol->GetName().GetCString());
+
+ // Handling the case where we are attempting to step into std::function.
+ // The behavior will be that we will attempt to obtain the wrapped
+ // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
+ // will return a ThreadPlanRunToAddress to the callable. Therefore we will
+ // step into the wrapped callable.
+ //
+ bool found_expected_start_string =
+ function_name.startswith("std::__1::function<");
+
+ if (!found_expected_start_string)
+ return ret_plan_sp;
+
+ AddressRange range_of_curr_func;
+ sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);
+
+ StackFrameSP frame = thread.GetStackFrameAtIndex(0);
+
+ if (frame) {
+ ValueObjectSP value_sp = frame->FindVariable(ConstString("this"));
+
+ CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
+ FindLibCppStdFunctionCallableInfo(value_sp);
+
+ if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
+ value_sp->GetValueIsValid()) {
+ // We found the std::function wrapped callable and we have its address.
+ // We now create a ThreadPlan to run to the callable.
+ ret_plan_sp.reset(new ThreadPlanRunToAddress(
+ thread, callable_info.callable_address, stop_others));
+ return ret_plan_sp;
+ } else {
+ // We are in std::function but we could not obtain the callable.
+ // We create a ThreadPlan to keep stepping through using the address range
+ // of the current function.
+ ret_plan_sp.reset(new ThreadPlanStepInRange(thread, range_of_curr_func,
+ sc, eOnlyThisThread,
+ eLazyBoolYes, eLazyBoolYes));
+ return ret_plan_sp;
+ }
+ }
+
+ return ret_plan_sp;
+}
diff --git a/source/Target/ExecutionContext.cpp b/source/Target/ExecutionContext.cpp
index 73c64916cf1f..7f1f0331c922 100644
--- a/source/Target/ExecutionContext.cpp
+++ b/source/Target/ExecutionContext.cpp
@@ -7,17 +7,13 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/State.h"
using namespace lldb_private;
diff --git a/source/Target/InstrumentationRuntime.cpp b/source/Target/InstrumentationRuntime.cpp
index ac8b5dfe4599..e948d43d50af 100644
--- a/source/Target/InstrumentationRuntime.cpp
+++ b/source/Target/InstrumentationRuntime.cpp
@@ -7,10 +7,6 @@
//
//===---------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/InstrumentationRuntime.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
diff --git a/source/Target/JITLoader.cpp b/source/Target/JITLoader.cpp
index 77ce4add486f..ddadcfa87a0a 100644
--- a/source/Target/JITLoader.cpp
+++ b/source/Target/JITLoader.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/JITLoader.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/JITLoaderList.h"
diff --git a/source/Target/Language.cpp b/source/Target/Language.cpp
index cde6f8654aec..5c7a4097dd6f 100644
--- a/source/Target/Language.cpp
+++ b/source/Target/Language.cpp
@@ -77,7 +77,39 @@ Language *Language::FindPlugin(lldb::LanguageType language) {
return nullptr;
}
+Language *Language::FindPlugin(llvm::StringRef file_path) {
+ Language *result = nullptr;
+ ForEach([&result, file_path](Language *language) {
+ if (language->IsSourceFile(file_path)) {
+ result = language;
+ return false;
+ }
+ return true;
+ });
+ return result;
+}
+
+Language *Language::FindPlugin(LanguageType language,
+ llvm::StringRef file_path) {
+ Language *result = FindPlugin(language);
+ // Finding a language by file path is slower, we so we use this as the
+ // fallback.
+ if (!result)
+ result = FindPlugin(file_path);
+ return result;
+}
+
void Language::ForEach(std::function<bool(Language *)> callback) {
+ // If we want to iterate over all languages, we first have to complete the
+ // LanguagesMap.
+ static llvm::once_flag g_initialize;
+ llvm::call_once(g_initialize, [] {
+ for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;
+ ++lang) {
+ FindPlugin(static_cast<lldb::LanguageType>(lang));
+ }
+ });
+
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
LanguagesMap &map(GetLanguagesMap());
for (const auto &entry : map) {
@@ -353,11 +385,10 @@ bool Language::ImageListTypeScavenger::Find_Impl(
Target *target = exe_scope->CalculateTarget().get();
if (target) {
const auto &images(target->GetImages());
- SymbolContext null_sc;
ConstString cs_key(key);
llvm::DenseSet<SymbolFile *> searched_sym_files;
TypeList matches;
- images.FindTypes(null_sc, cs_key, false, UINT32_MAX, searched_sym_files,
+ images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files,
matches);
for (const auto &match : matches.Types()) {
if (match.get()) {
diff --git a/source/Target/LanguageRuntime.cpp b/source/Target/LanguageRuntime.cpp
index bd02121f6a4d..ea6914fb076d 100644
--- a/source/Target/LanguageRuntime.cpp
+++ b/source/Target/LanguageRuntime.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/LanguageRuntime.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/PluginManager.h"
@@ -125,11 +121,11 @@ public:
return eCallbackReturnStop;
}
- Searcher::Depth GetDepth() override {
+ lldb::SearchDepth GetDepth() override {
if (SetActualResolver())
return m_actual_resolver_sp->GetDepth();
else
- return eDepthTarget;
+ return lldb::eSearchDepthTarget;
}
void GetDescription(Stream *s) override {
diff --git a/source/Target/Memory.cpp b/source/Target/Memory.cpp
index ad1b4093155d..190c5057e881 100644
--- a/source/Target/Memory.cpp
+++ b/source/Target/Memory.cpp
@@ -8,16 +8,12 @@
//===----------------------------------------------------------------------===//
#include "lldb/Target/Memory.h"
-// C Includes
#include <inttypes.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/RangeMap.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/MemoryHistory.cpp b/source/Target/MemoryHistory.cpp
index 627942796507..eae931482552 100644
--- a/source/Target/MemoryHistory.cpp
+++ b/source/Target/MemoryHistory.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/MemoryHistory.h"
#include "lldb/Core/PluginManager.h"
diff --git a/source/Target/ModuleCache.cpp b/source/Target/ModuleCache.cpp
index 19adfbabe277..daf787b1fb22 100644
--- a/source/Target/ModuleCache.cpp
+++ b/source/Target/ModuleCache.cpp
@@ -76,7 +76,7 @@ FileSpec GetModuleDirectory(const FileSpec &root_dir_spec, const UUID &uuid) {
}
FileSpec GetSymbolFileSpec(const FileSpec &module_file_spec) {
- return FileSpec(module_file_spec.GetPath() + kSymFileExtension, false);
+ return FileSpec(module_file_spec.GetPath() + kSymFileExtension);
}
void DeleteExistingModule(const FileSpec &root_dir_spec,
@@ -133,7 +133,7 @@ Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec,
const auto sysroot_module_path_spec =
JoinPath(JoinPath(root_dir_spec, hostname),
platform_module_spec.GetPath().c_str());
- if (sysroot_module_path_spec.Exists()) {
+ if (FileSystem::Instance().Exists(sysroot_module_path_spec)) {
if (!delete_existing)
return Status();
@@ -141,7 +141,7 @@ Status CreateHostSysRootModuleLink(const FileSpec &root_dir_spec,
}
const auto error = MakeDirectory(
- FileSpec(sysroot_module_path_spec.GetDirectory().AsCString(), false));
+ FileSpec(sysroot_module_path_spec.GetDirectory().AsCString()));
if (error.Fail())
return error;
@@ -159,9 +159,10 @@ ModuleLock::ModuleLock(const FileSpec &root_dir_spec, const UUID &uuid,
return;
m_file_spec = JoinPath(lock_dir_spec, uuid.GetAsString().c_str());
- m_file.Open(m_file_spec.GetCString(), File::eOpenOptionWrite |
- File::eOpenOptionCanCreate |
- File::eOpenOptionCloseOnExec);
+ FileSystem::Instance().Open(m_file, m_file_spec,
+ File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate |
+ File::eOpenOptionCloseOnExec);
if (!m_file) {
error.SetErrorToErrno();
return;
@@ -225,9 +226,10 @@ Status ModuleCache::Get(const FileSpec &root_dir_spec, const char *hostname,
const auto module_file_path = JoinPath(
module_spec_dir, module_spec.GetFileSpec().GetFilename().AsCString());
- if (!module_file_path.Exists())
+ if (!FileSystem::Instance().Exists(module_file_path))
return Status("Module %s not found", module_file_path.GetPath().c_str());
- if (module_file_path.GetByteSize() != module_spec.GetObjectSize())
+ if (FileSystem::Instance().GetByteSize(module_file_path) !=
+ module_spec.GetObjectSize())
return Status("Module %s has invalid file size",
module_file_path.GetPath().c_str());
@@ -252,7 +254,7 @@ Status ModuleCache::Get(const FileSpec &root_dir_spec, const char *hostname,
return error;
FileSpec symfile_spec = GetSymbolFileSpec(cached_module_sp->GetFileSpec());
- if (symfile_spec.Exists())
+ if (FileSystem::Instance().Exists(symfile_spec))
cached_module_sp->SetSymbolFileFileSpec(symfile_spec);
m_loaded_modules.insert(
diff --git a/source/Target/ObjCLanguageRuntime.cpp b/source/Target/ObjCLanguageRuntime.cpp
index b1fcee6db63b..8627da938ea3 100644
--- a/source/Target/ObjCLanguageRuntime.cpp
+++ b/source/Target/ObjCLanguageRuntime.cpp
@@ -108,14 +108,13 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) {
if (!module_sp)
return TypeSP();
- const SymbolContext null_sc;
const bool exact_match = true;
const uint32_t max_matches = UINT32_MAX;
TypeList types;
llvm::DenseSet<SymbolFile *> searched_symbol_files;
const uint32_t num_types = module_sp->FindTypes(
- null_sc, name, exact_match, max_matches, searched_symbol_files, types);
+ name, exact_match, max_matches, searched_symbol_files, types);
if (num_types) {
uint32_t i;
diff --git a/source/Target/OperatingSystem.cpp b/source/Target/OperatingSystem.cpp
index 7a1d9d619879..099bfd055ed1 100644
--- a/source/Target/OperatingSystem.cpp
+++ b/source/Target/OperatingSystem.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/OperatingSystem.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Thread.h"
diff --git a/source/Target/PathMappingList.cpp b/source/Target/PathMappingList.cpp
index 778728eebb09..c2249cce89b9 100644
--- a/source/Target/PathMappingList.cpp
+++ b/source/Target/PathMappingList.cpp
@@ -7,19 +7,16 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <climits>
#include <cstring>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/lldb-private-enumerations.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/PosixApi.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
+#include "lldb/lldb-private-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -37,7 +34,7 @@ namespace {
ConstString NormalizePath(const ConstString &path) {
// If we use "path" to construct a FileSpec, it will normalize the path for
// us. We then grab the string and turn it back into a ConstString.
- return ConstString(FileSpec(path.GetStringRef(), false).GetPath());
+ return ConstString(FileSpec(path.GetStringRef()).GetPath());
}
}
//----------------------------------------------------------------------
@@ -176,13 +173,13 @@ bool PathMappingList::RemapPath(llvm::StringRef path,
// We need to figure out if the "path" argument is relative. If it is,
// then we should remap, else skip this entry.
if (path_is_relative == eLazyBoolCalculate) {
- path_is_relative = FileSpec(path, false).IsRelative() ? eLazyBoolYes :
- eLazyBoolNo;
+ path_is_relative =
+ FileSpec(path).IsRelative() ? eLazyBoolYes : eLazyBoolNo;
}
if (!path_is_relative)
continue;
}
- FileSpec remapped(it.second.GetStringRef(), false);
+ FileSpec remapped(it.second.GetStringRef());
remapped.AppendPathComponent(path);
new_path = remapped.GetPath();
return true;
@@ -196,7 +193,7 @@ bool PathMappingList::ReverseRemapPath(const FileSpec &file, FileSpec &fixed) co
for (const auto &it : m_pairs) {
if (!path_ref.consume_front(it.second.GetStringRef()))
continue;
- fixed.SetFile(it.first.GetStringRef(), false, FileSpec::Style::native);
+ fixed.SetFile(it.first.GetStringRef(), FileSpec::Style::native);
fixed.AppendPathComponent(path_ref);
return true;
}
@@ -216,10 +213,9 @@ bool PathMappingList::FindFile(const FileSpec &orig_spec,
if (orig_path_len >= prefix_len) {
if (::strncmp(pos->first.GetCString(), orig_path, prefix_len) == 0) {
- new_spec.SetFile(pos->second.GetCString(), false,
- FileSpec::Style::native);
+ new_spec.SetFile(pos->second.GetCString(), FileSpec::Style::native);
new_spec.AppendPathComponent(orig_path + prefix_len);
- if (new_spec.Exists())
+ if (FileSystem::Instance().Exists(new_spec))
return true;
}
}
diff --git a/source/Target/Platform.cpp b/source/Target/Platform.cpp
index 5ae556ecc02a..400b3c92b5ab 100644
--- a/source/Target/Platform.cpp
+++ b/source/Target/Platform.cpp
@@ -7,18 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <algorithm>
#include <csignal>
#include <fstream>
#include <vector>
-// Other libraries and framework includes
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-// Project includes
#include "lldb/Breakpoint/BreakpointIDList.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Debugger.h"
@@ -67,12 +63,11 @@ const char *Platform::GetHostPlatformName() { return "host"; }
namespace {
-PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"use-module-cache", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr, "Use module cache."},
+ {}, "Use module cache."},
{"module-cache-directory", OptionValue::eTypeFileSpec, true, 0, nullptr,
- nullptr, "Root directory for cached modules."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {}, "Root directory for cached modules."}};
enum { ePropertyUseModuleCache, ePropertyModuleCacheDirectory };
@@ -95,7 +90,7 @@ PlatformProperties::PlatformProperties() {
if (!llvm::sys::path::home_directory(user_home_dir))
return;
- module_cache_dir = FileSpec(user_home_dir.c_str(), false);
+ module_cache_dir = FileSpec(user_home_dir.c_str());
module_cache_dir.AppendPathComponent(".lldb");
module_cache_dir.AppendPathComponent("module_cache");
SetModuleCacheDirectory(module_cache_dir);
@@ -228,16 +223,35 @@ Status Platform::GetSharedModule(const ModuleSpec &module_spec,
module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
did_create_ptr, false);
- return GetRemoteSharedModule(module_spec, process, module_sp,
- [&](const ModuleSpec &spec) {
- Status error = ModuleList::GetSharedModule(
- spec, module_sp, module_search_paths_ptr,
- old_module_sp_ptr, did_create_ptr, false);
- if (error.Success() && module_sp)
- module_sp->SetPlatformFileSpec(
- spec.GetFileSpec());
- return error;
- },
+ // Module resolver lambda.
+ auto resolver = [&](const ModuleSpec &spec) {
+ Status error(eErrorTypeGeneric);
+ ModuleSpec resolved_spec;
+ // Check if we have sysroot set.
+ if (m_sdk_sysroot) {
+ // Prepend sysroot to module spec.
+ resolved_spec = spec;
+ resolved_spec.GetFileSpec().PrependPathComponent(
+ m_sdk_sysroot.GetStringRef());
+ // Try to get shared module with resolved spec.
+ error = ModuleList::GetSharedModule(
+ resolved_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
+ did_create_ptr, false);
+ }
+ // If we don't have sysroot or it didn't work then
+ // try original module spec.
+ if (!error.Success()) {
+ resolved_spec = spec;
+ error = ModuleList::GetSharedModule(
+ resolved_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr,
+ did_create_ptr, false);
+ }
+ if (error.Success() && module_sp)
+ module_sp->SetPlatformFileSpec(resolved_spec.GetFileSpec());
+ return error;
+ };
+
+ return GetRemoteSharedModule(module_spec, process, module_sp, resolver,
did_create_ptr);
}
@@ -518,9 +532,12 @@ FileSpec Platform::GetWorkingDirectory() {
if (IsHost()) {
llvm::SmallString<64> cwd;
if (llvm::sys::fs::current_path(cwd))
- return FileSpec{};
- else
- return FileSpec(cwd, true);
+ return {};
+ else {
+ FileSpec file_spec(cwd);
+ FileSystem::Instance().Resolve(file_spec);
+ return file_spec;
+ }
} else {
if (!m_working_dir)
m_working_dir = GetRemoteWorkingDirectory();
@@ -534,16 +551,17 @@ struct RecurseCopyBaton {
Status error;
};
-static FileSpec::EnumerateDirectoryResult
+static FileSystem::EnumerateDirectoryResult
RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
- const FileSpec &src) {
+ llvm::StringRef path) {
RecurseCopyBaton *rc_baton = (RecurseCopyBaton *)baton;
+ FileSpec src(path);
namespace fs = llvm::sys::fs;
switch (ft) {
case fs::file_type::fifo_file:
case fs::file_type::socket_file:
// we have no way to copy pipes and sockets - ignore them and continue
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
break;
case fs::file_type::directory_file: {
@@ -556,7 +574,7 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
if (error.Fail()) {
rc_baton->error.SetErrorStringWithFormat(
"unable to setup directory %s on remote end", dst_dir.GetCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
}
// now recurse
@@ -568,13 +586,13 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
recurse_dst.GetDirectory().SetCString(dst_dir.GetPath().c_str());
RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr,
Status()};
- FileSpec::EnumerateDirectory(src_dir_path, true, true, true,
- RecurseCopy_Callback, &rc_baton2);
+ FileSystem::Instance().EnumerateDirectory(src_dir_path, 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 FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} break;
case fs::file_type::symlink_file: {
@@ -585,18 +603,18 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
FileSpec src_resolved;
- rc_baton->error = FileSystem::Readlink(src, src_resolved);
+ rc_baton->error = FileSystem::Instance().Readlink(src, src_resolved);
if (rc_baton->error.Fail())
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
rc_baton->error =
rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved);
if (rc_baton->error.Fail())
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} break;
case fs::file_type::regular_file: {
@@ -607,15 +625,15 @@ RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,
Status err = rc_baton->platform_ptr->PutFile(src, dst_file);
if (err.Fail()) {
rc_baton->error.SetErrorString(err.AsCString());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
}
- return FileSpec::eEnumerateDirectoryResultNext;
+ return FileSystem::eEnumerateDirectoryResultNext;
} break;
default:
rc_baton->error.SetErrorStringWithFormat(
"invalid file detected during copy: %s", src.GetPath().c_str());
- return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
+ return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out
break;
}
llvm_unreachable("Unhandled file_type!");
@@ -690,7 +708,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
switch (fs::get_file_type(src.GetPath(), false)) {
case fs::file_type::directory_file: {
llvm::sys::fs::remove(fixed_dst.GetPath());
- uint32_t permissions = src.GetPermissions();
+ uint32_t permissions = FileSystem::Instance().GetPermissions(src);
if (permissions == 0)
permissions = eFilePermissionsDirectoryDefault;
error = MakeDirectory(fixed_dst, permissions);
@@ -701,8 +719,8 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
recurse_dst.GetDirectory().SetCString(fixed_dst.GetCString());
std::string src_dir_path(src.GetPath());
RecurseCopyBaton baton = {recurse_dst, this, Status()};
- FileSpec::EnumerateDirectory(src_dir_path, true, true, true,
- RecurseCopy_Callback, &baton);
+ FileSystem::Instance().EnumerateDirectory(
+ src_dir_path, true, true, true, RecurseCopy_Callback, &baton);
return baton.error;
}
} break;
@@ -715,7 +733,7 @@ Status Platform::Install(const FileSpec &src, const FileSpec &dst) {
case fs::file_type::symlink_file: {
llvm::sys::fs::remove(fixed_dst.GetPath());
FileSpec src_resolved;
- error = FileSystem::Readlink(src, src_resolved);
+ error = FileSystem::Instance().Readlink(src, src_resolved);
if (error.Success())
error = CreateSymlink(dst, src_resolved);
} break;
@@ -871,7 +889,7 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
lldb::ModuleSP &exe_module_sp,
const FileSpecList *module_search_paths_ptr) {
Status error;
- if (module_spec.GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
if (module_spec.GetArchitecture().IsValid()) {
error = ModuleList::GetSharedModule(module_spec, exe_module_sp,
module_search_paths_ptr, nullptr,
@@ -902,7 +920,7 @@ Platform::ResolveExecutable(const ModuleSpec &module_spec,
Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
FileSpec &sym_file) {
Status error;
- if (sym_spec.GetSymbolFileSpec().Exists())
+ if (FileSystem::Instance().Exists(sym_spec.GetSymbolFileSpec()))
sym_file = sym_spec.GetSymbolFileSpec();
else
error.SetErrorString("unable to resolve symbol file");
@@ -912,7 +930,8 @@ Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,
bool Platform::ResolveRemotePath(const FileSpec &platform_path,
FileSpec &resolved_platform_path) {
resolved_platform_path = platform_path;
- return resolved_platform_path.ResolvePath();
+ FileSystem::Instance().Resolve(resolved_platform_path);
+ return true;
}
const ArchSpec &Platform::GetSystemArchitecture() {
@@ -1257,8 +1276,9 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
if (fs::is_symlink_file(source.GetPath()))
source_open_options |= File::eOpenOptionDontFollowSymlinks;
- File source_file(source, source_open_options, lldb::eFilePermissionsUserRW);
- Status error;
+ File source_file;
+ Status error = FileSystem::Instance().Open(
+ source_file, source, source_open_options, lldb::eFilePermissionsUserRW);
uint32_t permissions = source_file.GetPermissions(error);
if (permissions == 0)
permissions = lldb::eFilePermissionsFileDefault;
@@ -1276,7 +1296,7 @@ Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,
return error;
if (dest_file == UINT64_MAX)
return Status("unable to open target file");
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024, 0));
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));
uint64_t offset = 0;
for (;;) {
size_t bytes_read = buffer_sp->GetByteSize();
@@ -1378,32 +1398,32 @@ const char *Platform::GetLocalCacheDirectory() {
return m_local_cache_directory.c_str();
}
-static OptionDefinition g_rsync_option_table[] = {
+static constexpr OptionDefinition g_rsync_option_table[] = {
{LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone, "Enable rsync."},
+ {}, 0, eArgTypeNone, "Enable rsync."},
{LLDB_OPT_SET_ALL, false, "rsync-opts", 'R',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommandName,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,
"Platform-specific options required for rsync to work."},
{LLDB_OPT_SET_ALL, false, "rsync-prefix", 'P',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCommandName,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,
"Platform-specific rsync prefix put before the remote path."},
{LLDB_OPT_SET_ALL, false, "ignore-remote-hostname", 'i',
- OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,
"Do not automatically fill in the remote hostname when composing the "
"rsync command."},
};
-static OptionDefinition g_ssh_option_table[] = {
+static constexpr OptionDefinition g_ssh_option_table[] = {
{LLDB_OPT_SET_ALL, false, "ssh", 's', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone, "Enable SSH."},
+ {}, 0, eArgTypeNone, "Enable SSH."},
{LLDB_OPT_SET_ALL, false, "ssh-opts", 'S', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeCommandName,
+ nullptr, {}, 0, eArgTypeCommandName,
"Platform-specific options required for SSH to work."},
};
-static OptionDefinition g_caching_option_table[] = {
+static constexpr OptionDefinition g_caching_option_table[] = {
{LLDB_OPT_SET_ALL, false, "local-cache-dir", 'c',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePath,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePath,
"Path in which to store local copies of files."},
};
@@ -1566,14 +1586,14 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
if (process->GetModuleSpec(module_spec.GetFileSpec(),
module_spec.GetArchitecture(),
resolved_module_spec)) {
- if (module_spec.GetUUID().IsValid() == false ||
+ if (!module_spec.GetUUID().IsValid() ||
module_spec.GetUUID() == resolved_module_spec.GetUUID()) {
got_module_spec = true;
}
}
}
- if (module_spec.GetArchitecture().IsValid() == false) {
+ if (!module_spec.GetArchitecture().IsValid()) {
Status error;
// No valid architecture was specified, ask the platform for the
// architectures that we should be using (in the correct order) and see if
@@ -1596,7 +1616,7 @@ Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,
// Get module information from a target.
if (!GetModuleSpec(module_spec.GetFileSpec(), module_spec.GetArchitecture(),
resolved_module_spec)) {
- if (module_spec.GetUUID().IsValid() == false ||
+ if (!module_spec.GetUUID().IsValid() ||
module_spec.GetUUID() == resolved_module_spec.GetUUID()) {
return module_resolver(module_spec);
}
@@ -1780,9 +1800,9 @@ uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,
{
FileSpec file_to_use;
if (remote_filename.IsAbsolute())
- file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
- false,
- remote_filename.GetPathStyle());
+ file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),
+
+ remote_filename.GetPathStyle());
else
file_to_use = remote_filename;
@@ -1802,9 +1822,19 @@ lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url,
error.Clear();
if (!target) {
+ ArchSpec arch;
+ if (target && target->GetArchitecture().IsValid())
+ arch = target->GetArchitecture();
+ else
+ arch = Target::GetDefaultArchitecture();
+
+ const char *triple = "";
+ if (arch.IsValid())
+ triple = arch.GetTriple().getTriple().c_str();
+
TargetSP new_target_sp;
- error = debugger.GetTargetList().CreateTarget(debugger, "", "", false,
- nullptr, new_target_sp);
+ error = debugger.GetTargetList().CreateTarget(
+ debugger, "", triple, eLoadDependentsNo, nullptr, new_target_sp);
target = new_target_sp.get();
}
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index c3d8abc9f78d..fb3b758912eb 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -7,25 +7,19 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <atomic>
#include <mutex>
-// Other libraries and framework includes
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/Threading.h"
-// Project includes
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Expression/DiagnosticManager.h"
#include "lldb/Expression/IRDynamicChecks.h"
@@ -67,9 +61,11 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanBase.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
#include "lldb/Utility/SelectHelper.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -116,39 +112,38 @@ public:
}
};
-static PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"disable-memory-cache", OptionValue::eTypeBoolean, false,
- DISABLE_MEM_CACHE_DEFAULT, nullptr, nullptr,
+ DISABLE_MEM_CACHE_DEFAULT, nullptr, {},
"Disable reading and caching of memory in fixed-size units."},
{"extra-startup-command", OptionValue::eTypeArray, false,
- OptionValue::eTypeString, nullptr, nullptr,
+ OptionValue::eTypeString, nullptr, {},
"A list containing extra commands understood by the particular process "
"plugin used. "
"For instance, to turn on debugserver logging set this to "
"\"QSetLogging:bitmask=LOG_DEFAULT;\""},
{"ignore-breakpoints-in-expressions", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr,
+ nullptr, {},
"If true, breakpoints will be ignored during expression evaluation."},
{"unwind-on-error-in-expressions", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr, "If true, errors in expression evaluation will unwind "
- "the stack back to the state before the call."},
+ nullptr, {}, "If true, errors in expression evaluation will unwind "
+ "the stack back to the state before the call."},
{"python-os-plugin-path", OptionValue::eTypeFileSpec, false, true, nullptr,
- nullptr, "A path to a python OS plug-in module file that contains a "
- "OperatingSystemPlugIn class."},
+ {}, "A path to a python OS plug-in module file that contains a "
+ "OperatingSystemPlugIn class."},
{"stop-on-sharedlibrary-events", OptionValue::eTypeBoolean, true, false,
- nullptr, nullptr,
+ nullptr, {},
"If true, stop when a shared library is loaded or unloaded."},
{"detach-keeps-stopped", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, detach will attempt to keep the process stopped."},
+ {}, "If true, detach will attempt to keep the process stopped."},
{"memory-cache-line-size", OptionValue::eTypeUInt64, false, 512, nullptr,
- nullptr, "The memory cache line size"},
+ {}, "The memory cache line size"},
{"optimization-warnings", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "If true, warn when stopped in code that is optimized where "
- "stepping and variable availability may not behave as expected."},
+ {}, "If true, warn when stopped in code that is optimized where "
+ "stepping and variable availability may not behave as expected."},
{"stop-on-exec", OptionValue::eTypeBoolean, true, true,
- nullptr, nullptr,
- "If true, stop when a shared library is loaded or unloaded."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ nullptr, {},
+ "If true, stop when a shared library is loaded or unloaded."}};
enum {
ePropertyDisableMemCache,
@@ -431,7 +426,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'i': // STDIN for read only
{
FileAction action;
- if (action.Open(STDIN_FILENO, FileSpec{option_arg, false}, true, false))
+ if (action.Open(STDIN_FILENO, FileSpec(option_arg), true, false))
launch_info.AppendFileAction(action);
break;
}
@@ -439,7 +434,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'o': // Open STDOUT for write only
{
FileAction action;
- if (action.Open(STDOUT_FILENO, FileSpec{option_arg, false}, false, true))
+ if (action.Open(STDOUT_FILENO, FileSpec(option_arg), false, true))
launch_info.AppendFileAction(action);
break;
}
@@ -447,7 +442,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'e': // STDERR for write only
{
FileAction action;
- if (action.Open(STDERR_FILENO, FileSpec{option_arg, false}, false, true))
+ if (action.Open(STDERR_FILENO, FileSpec(option_arg), false, true))
launch_info.AppendFileAction(action);
break;
}
@@ -459,7 +454,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'n': // Disable STDIO
{
FileAction action;
- const FileSpec dev_null{FileSystem::DEV_NULL, false};
+ const FileSpec dev_null(FileSystem::DEV_NULL);
if (action.Open(STDIN_FILENO, dev_null, true, false))
launch_info.AppendFileAction(action);
if (action.Open(STDOUT_FILENO, dev_null, false, true))
@@ -470,7 +465,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
}
case 'w':
- launch_info.SetWorkingDirectory(FileSpec{option_arg, false});
+ launch_info.SetWorkingDirectory(FileSpec(option_arg));
break;
case 't': // Open process in new terminal window
@@ -516,7 +511,7 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
case 'c':
if (!option_arg.empty())
- launch_info.SetShell(FileSpec(option_arg, false));
+ launch_info.SetShell(FileSpec(option_arg));
else
launch_info.SetShell(HostInfo::GetDefaultShell());
break;
@@ -533,52 +528,52 @@ Status ProcessLaunchCommandOptions::SetOptionValue(
return error;
}
-static OptionDefinition g_process_launch_options[] = {
+static constexpr OptionDefinition g_process_launch_options[] = {
{LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', OptionParser::eNoArgument,
- nullptr, nullptr, 0, eArgTypeNone,
+ nullptr, {}, 0, eArgTypeNone,
"Stop at the entry point of the program when launching a process."},
{LLDB_OPT_SET_ALL, false, "disable-aslr", 'A',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Set whether to disable address space layout randomization when launching "
"a process."},
{LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypePlugin,
+ nullptr, {}, 0, eArgTypePlugin,
"Name of the process plugin you want to use."},
{LLDB_OPT_SET_ALL, false, "working-dir", 'w',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0,
+ OptionParser::eRequiredArgument, nullptr, {}, 0,
eArgTypeDirectoryName,
"Set the current working directory to <path> when running the inferior."},
{LLDB_OPT_SET_ALL, false, "arch", 'a', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeArchitecture,
+ nullptr, {}, 0, eArgTypeArchitecture,
"Set the architecture for the process to launch when ambiguous."},
{LLDB_OPT_SET_ALL, false, "environment", 'v',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone,
"Specify an environment variable name/value string (--environment "
"NAME=VALUE). Can be specified multiple times for subsequent environment "
"entries."},
{LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, false, "shell", 'c',
- OptionParser::eOptionalArgument, nullptr, nullptr, 0, eArgTypeFilename,
+ OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeFilename,
"Run the process in a shell (not supported on all platforms)."},
{LLDB_OPT_SET_1, false, "stdin", 'i', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Redirect stdin for the process to <filename>."},
{LLDB_OPT_SET_1, false, "stdout", 'o', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Redirect stdout for the process to <filename>."},
{LLDB_OPT_SET_1, false, "stderr", 'e', OptionParser::eRequiredArgument,
- nullptr, nullptr, 0, eArgTypeFilename,
+ nullptr, {}, 0, eArgTypeFilename,
"Redirect stderr for the process to <filename>."},
{LLDB_OPT_SET_2, false, "tty", 't', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone,
+ {}, 0, eArgTypeNone,
"Start the process in a terminal (not supported on all platforms)."},
{LLDB_OPT_SET_3, false, "no-stdio", 'n', OptionParser::eNoArgument, nullptr,
- nullptr, 0, eArgTypeNone,
+ {}, 0, eArgTypeNone,
"Do not set up for terminal I/O to go to running process."},
{LLDB_OPT_SET_4, false, "shell-expand-args", 'X',
- OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
+ OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean,
"Set whether to shell expand arguments to the process when launching."},
};
@@ -1729,6 +1724,10 @@ void Process::SetRunningUserExpression(bool on) {
m_mod_id.SetRunningUserExpression(on);
}
+void Process::SetRunningUtilityFunction(bool on) {
+ m_mod_id.SetRunningUtilityFunction(on);
+}
+
addr_t Process::GetImageInfoAddress() { return LLDB_INVALID_ADDRESS; }
const lldb::ABISP &Process::GetABI() {
@@ -1921,7 +1920,7 @@ Process::CreateBreakpointSite(const BreakpointLocationSP &owner,
owner->SetBreakpointSite(bp_site_sp);
return m_breakpoint_site_list.Add(bp_site_sp);
} else {
- if (show_error) {
+ if (show_error || use_hardware) {
// Report error for setting breakpoint...
GetTarget().GetDebugger().GetErrorFile()->Printf(
"warning: failed to set breakpoint site at 0x%" PRIx64
@@ -2731,7 +2730,7 @@ Status Process::Launch(ProcessLaunchInfo &launch_info) {
sizeof(local_exec_file_path));
exe_module->GetPlatformFileSpec().GetPath(platform_exec_file_path,
sizeof(platform_exec_file_path));
- if (exe_module->GetFileSpec().Exists()) {
+ if (FileSystem::Instance().Exists(exe_module->GetFileSpec())) {
// Install anything that might need to be installed prior to launching.
// For host systems, this will do nothing, but if we are connected to a
// remote platform it will install any needed binaries
@@ -3211,7 +3210,8 @@ void Process::CompleteAttach() {
}
}
if (new_executable_module_sp) {
- GetTarget().SetExecutableModule(new_executable_module_sp, false);
+ GetTarget().SetExecutableModule(new_executable_module_sp,
+ eLoadDependentsNo);
if (log) {
ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
log->Printf(
@@ -3291,6 +3291,11 @@ Status Process::PrivateResume() {
m_thread_list.DidResume();
if (log)
log->Printf("Process thinks the process has resumed.");
+ } else {
+ if (log)
+ log->Printf(
+ "Process::PrivateResume() DoResume failed.");
+ return error;
}
}
} else {
@@ -4685,7 +4690,12 @@ bool Process::PushProcessIOHandler() {
log->Printf("Process::%s pushing IO handler", __FUNCTION__);
io_handler_sp->SetIsDone(false);
- GetTarget().GetDebugger().PushIOHandler(io_handler_sp);
+ // If we evaluate an utility function, then we don't cancel the current
+ // IOHandler. Our IOHandler is non-interactive and shouldn't disturb the
+ // existing IOHandler that potentially provides the user interface (e.g.
+ // the IOHandler for Editline).
+ bool cancel_top_handler = !m_mod_id.IsRunningUtilityFunction();
+ GetTarget().GetDebugger().PushIOHandler(io_handler_sp, cancel_top_handler);
return true;
}
return false;
@@ -4875,6 +4885,11 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx,
thread_plan_sp->SetIsMasterPlan(true);
thread_plan_sp->SetOkayToDiscard(false);
+ // If we are running some utility expression for LLDB, we now have to mark
+ // this in the ProcesModID of this process. This RAII takes care of marking
+ // and reverting the mark it once we are done running the expression.
+ UtilityFunctionScope util_scope(options.IsForUtilityExpr() ? this : nullptr);
+
if (m_private_state.GetValue() != eStateStopped) {
diagnostic_manager.PutString(
eDiagnosticSeverityError,
@@ -5842,7 +5857,7 @@ void Process::ModulesDidLoad(ModuleList &module_list) {
// that loaded.
// Iterate over a copy of this language runtime list in case the language
- // runtime ModulesDidLoad somehow causes the language riuntime to be
+ // runtime ModulesDidLoad somehow causes the language runtime to be
// unloaded.
LanguageRuntimeCollection language_runtimes(m_language_runtimes);
for (const auto &pair : language_runtimes) {
@@ -6020,7 +6035,7 @@ Process::AdvanceAddressToNextBranchInstruction(Address default_stop_addr,
}
Status
-Process::GetMemoryRegions(std::vector<lldb::MemoryRegionInfoSP> &region_list) {
+Process::GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list) {
Status error;
@@ -6028,17 +6043,17 @@ Process::GetMemoryRegions(std::vector<lldb::MemoryRegionInfoSP> &region_list) {
region_list.clear();
do {
- lldb::MemoryRegionInfoSP region_info(new lldb_private::MemoryRegionInfo());
- error = GetMemoryRegionInfo(range_end, *region_info);
+ lldb_private::MemoryRegionInfo region_info;
+ error = GetMemoryRegionInfo(range_end, region_info);
// GetMemoryRegionInfo should only return an error if it is unimplemented.
if (error.Fail()) {
region_list.clear();
break;
}
- range_end = region_info->GetRange().GetRangeEnd();
- if (region_info->GetMapped() == MemoryRegionInfo::eYes) {
- region_list.push_back(region_info);
+ range_end = region_info.GetRange().GetRangeEnd();
+ if (region_info.GetMapped() == MemoryRegionInfo::eYes) {
+ region_list.push_back(std::move(region_info));
}
} while (range_end != LLDB_INVALID_ADDRESS);
@@ -6095,7 +6110,7 @@ void Process::MapSupportedStructuredDataPlugins(
// For each StructuredDataPlugin, if the plugin handles any of the types in
// the supported_type_names, map that type name to that plugin. Stop when
// we've consumed all the type names.
- // FIXME: should we return an error if there are type names nobody
+ // FIXME: should we return an error if there are type names nobody
// supports?
for (uint32_t plugin_index = 0; !const_type_names.empty(); plugin_index++) {
auto create_instance =
@@ -6103,7 +6118,7 @@ void Process::MapSupportedStructuredDataPlugins(
plugin_index);
if (!create_instance)
break;
-
+
// Create the plugin.
StructuredDataPluginSP plugin_sp = (*create_instance)(*this);
if (!plugin_sp) {
diff --git a/source/Target/ProcessInfo.cpp b/source/Target/ProcessInfo.cpp
index ac0350686706..1ada6123fa1e 100644
--- a/source/Target/ProcessInfo.cpp
+++ b/source/Target/ProcessInfo.cpp
@@ -9,12 +9,8 @@
#include "lldb/Target/ProcessInfo.h"
-// C Includes
-// C++ Includes
#include <climits>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Host/PosixApi.h"
#include "lldb/Utility/Stream.h"
@@ -29,8 +25,8 @@ ProcessInfo::ProcessInfo()
ProcessInfo::ProcessInfo(const char *name, const ArchSpec &arch,
lldb::pid_t pid)
- : m_executable(name, false), m_arguments(), m_environment(),
- m_uid(UINT32_MAX), m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {}
+ : m_executable(name), m_arguments(), m_environment(), m_uid(UINT32_MAX),
+ m_gid(UINT32_MAX), m_arch(arch), m_pid(pid) {}
void ProcessInfo::Clear() {
m_executable.Clear();
@@ -67,7 +63,7 @@ void ProcessInfo::SetExecutableFile(const FileSpec &exe_file,
if (exe_file) {
m_executable = exe_file;
if (add_exe_file_as_first_arg) {
- llvm::SmallString<PATH_MAX> filename;
+ llvm::SmallString<128> filename;
exe_file.GetPath(filename);
if (!filename.empty())
m_arguments.InsertArgumentAtIndex(0, filename);
@@ -96,8 +92,7 @@ void ProcessInfo::SetArguments(char const **argv,
// Yes the first argument is an executable, set it as the executable in
// the launch options. Don't resolve the file path as the path could be a
// remote platform path
- const bool resolve = false;
- m_executable.SetFile(first_arg, resolve, FileSpec::Style::native);
+ m_executable.SetFile(first_arg, FileSpec::Style::native);
}
}
}
@@ -113,8 +108,7 @@ void ProcessInfo::SetArguments(const Args &args, bool first_arg_is_executable) {
// Yes the first argument is an executable, set it as the executable in
// the launch options. Don't resolve the file path as the path could be a
// remote platform path
- const bool resolve = false;
- m_executable.SetFile(first_arg, resolve, FileSpec::Style::native);
+ m_executable.SetFile(first_arg, FileSpec::Style::native);
}
}
}
diff --git a/source/Target/ProcessLaunchInfo.cpp b/source/Target/ProcessLaunchInfo.cpp
index 9569750bc5fd..ac1eba04f0cb 100644
--- a/source/Target/ProcessLaunchInfo.cpp
+++ b/source/Target/ProcessLaunchInfo.cpp
@@ -7,19 +7,13 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <climits>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/Debugger.h"
#include "lldb/Host/Config.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/FileAction.h"
#include "lldb/Target/ProcessLaunchInfo.h"
-#include "lldb/Target/Target.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"
@@ -108,8 +102,7 @@ bool ProcessLaunchInfo::AppendOpenFileAction(int fd, const FileSpec &file_spec,
bool ProcessLaunchInfo::AppendSuppressFileAction(int fd, bool read,
bool write) {
FileAction file_action;
- if (file_action.Open(fd, FileSpec{FileSystem::DEV_NULL, false}, read,
- write)) {
+ if (file_action.Open(fd, FileSpec(FileSystem::DEV_NULL), read, write)) {
AppendFileAction(file_action);
return true;
}
@@ -151,7 +144,7 @@ const FileSpec &ProcessLaunchInfo::GetShell() const { return m_shell; }
void ProcessLaunchInfo::SetShell(const FileSpec &shell) {
m_shell = shell;
if (m_shell) {
- m_shell.ResolveExecutableLocation();
+ FileSystem::Instance().ResolveExecutableLocation(m_shell);
m_flags.Set(lldb::eLaunchFlagLaunchInShell);
} else
m_flags.Clear(lldb::eLaunchFlagLaunchInShell);
@@ -212,124 +205,38 @@ void ProcessLaunchInfo::SetDetachOnError(bool enable) {
m_flags.Clear(lldb::eLaunchFlagDetachOnError);
}
-void ProcessLaunchInfo::FinalizeFileActions(Target *target,
- bool default_to_use_pty) {
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // If nothing for stdin or stdout or stderr was specified, then check the
- // process for any default settings that were set with "settings set"
- if (GetFileActionForFD(STDIN_FILENO) == nullptr ||
- GetFileActionForFD(STDOUT_FILENO) == nullptr ||
- GetFileActionForFD(STDERR_FILENO) == nullptr) {
- if (log)
- log->Printf("ProcessLaunchInfo::%s at least one of stdin/stdout/stderr "
- "was not set, evaluating default handling",
- __FUNCTION__);
-
- if (m_flags.Test(eLaunchFlagLaunchInTTY)) {
- // Do nothing, if we are launching in a remote terminal no file actions
- // should be done at all.
- return;
- }
-
- if (m_flags.Test(eLaunchFlagDisableSTDIO)) {
- if (log)
- log->Printf("ProcessLaunchInfo::%s eLaunchFlagDisableSTDIO set, adding "
- "suppression action for stdin, stdout and stderr",
- __FUNCTION__);
- AppendSuppressFileAction(STDIN_FILENO, true, false);
- AppendSuppressFileAction(STDOUT_FILENO, false, true);
- AppendSuppressFileAction(STDERR_FILENO, false, true);
- } else {
- // Check for any values that might have gotten set with any of: (lldb)
- // settings set target.input-path (lldb) settings set target.output-path
- // (lldb) settings set target.error-path
- FileSpec in_file_spec;
- FileSpec out_file_spec;
- FileSpec err_file_spec;
- if (target) {
- // Only override with the target settings if we don't already have an
- // action for in, out or error
- if (GetFileActionForFD(STDIN_FILENO) == nullptr)
- in_file_spec = target->GetStandardInputPath();
- if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
- out_file_spec = target->GetStandardOutputPath();
- if (GetFileActionForFD(STDERR_FILENO) == nullptr)
- err_file_spec = target->GetStandardErrorPath();
- }
-
- if (log)
- log->Printf("ProcessLaunchInfo::%s target stdin='%s', target "
- "stdout='%s', stderr='%s'",
- __FUNCTION__,
- in_file_spec ? in_file_spec.GetCString() : "<null>",
- out_file_spec ? out_file_spec.GetCString() : "<null>",
- err_file_spec ? err_file_spec.GetCString() : "<null>");
-
- if (in_file_spec) {
- AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
- if (log)
- log->Printf(
- "ProcessLaunchInfo::%s appended stdin open file action for %s",
- __FUNCTION__, in_file_spec.GetCString());
- }
-
- if (out_file_spec) {
- AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
- if (log)
- log->Printf(
- "ProcessLaunchInfo::%s appended stdout open file action for %s",
- __FUNCTION__, out_file_spec.GetCString());
- }
-
- if (err_file_spec) {
- AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
- if (log)
- log->Printf(
- "ProcessLaunchInfo::%s appended stderr open file action for %s",
- __FUNCTION__, err_file_spec.GetCString());
- }
-
- if (default_to_use_pty &&
- (!in_file_spec || !out_file_spec || !err_file_spec)) {
- if (log)
- log->Printf("ProcessLaunchInfo::%s default_to_use_pty is set, and at "
- "least one stdin/stderr/stdout is unset, so generating a "
- "pty to use for it",
- __FUNCTION__);
+llvm::Error ProcessLaunchInfo::SetUpPtyRedirection() {
+ Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS);
+ LLDB_LOG(log, "Generating a pty to use for stdin/out/err");
- int open_flags = O_RDWR | O_NOCTTY;
+ int open_flags = O_RDWR | O_NOCTTY;
#if !defined(_WIN32)
- // We really shouldn't be specifying platform specific flags that are
- // intended for a system call in generic code. But this will have to
- // do for now.
- open_flags |= O_CLOEXEC;
+ // We really shouldn't be specifying platform specific flags that are
+ // intended for a system call in generic code. But this will have to
+ // do for now.
+ open_flags |= O_CLOEXEC;
#endif
- if (m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
- const FileSpec slave_file_spec{m_pty->GetSlaveName(nullptr, 0),
- false};
-
- // Only use the slave tty if we don't have anything specified for
- // input and don't have an action for stdin
- if (!in_file_spec && GetFileActionForFD(STDIN_FILENO) == nullptr) {
- AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
- }
-
- // Only use the slave tty if we don't have anything specified for
- // output and don't have an action for stdout
- if (!out_file_spec && GetFileActionForFD(STDOUT_FILENO) == nullptr) {
- AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
- }
-
- // Only use the slave tty if we don't have anything specified for
- // error and don't have an action for stderr
- if (!err_file_spec && GetFileActionForFD(STDERR_FILENO) == nullptr) {
- AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
- }
- }
- }
- }
+ if (!m_pty->OpenFirstAvailableMaster(open_flags, nullptr, 0)) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "PTY::OpenFirstAvailableMaster failed");
}
+ const FileSpec slave_file_spec(m_pty->GetSlaveName(nullptr, 0));
+
+ // Only use the slave tty if we don't have anything specified for
+ // input and don't have an action for stdin
+ if (GetFileActionForFD(STDIN_FILENO) == nullptr)
+ AppendOpenFileAction(STDIN_FILENO, slave_file_spec, true, false);
+
+ // Only use the slave tty if we don't have anything specified for
+ // output and don't have an action for stdout
+ if (GetFileActionForFD(STDOUT_FILENO) == nullptr)
+ AppendOpenFileAction(STDOUT_FILENO, slave_file_spec, false, true);
+
+ // Only use the slave tty if we don't have anything specified for
+ // error and don't have an action for stderr
+ if (GetFileActionForFD(STDERR_FILENO) == nullptr)
+ AppendOpenFileAction(STDERR_FILENO, slave_file_spec, false, true);
+ return llvm::Error::success();
}
bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
@@ -359,7 +266,7 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
// Add a modified PATH environment variable in case argv[0] is a
// relative path.
const char *argv0 = argv[0];
- FileSpec arg_spec(argv0, false);
+ FileSpec arg_spec(argv0);
if (arg_spec.IsRelative()) {
// We have a relative path to our executable which may not work if we
// just try to run "a.out" (without it being converted to "./a.out")
@@ -439,10 +346,3 @@ bool ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell(
}
return false;
}
-
-ListenerSP ProcessLaunchInfo::GetListenerForProcess(Debugger &debugger) {
- if (m_listener_sp)
- return m_listener_sp;
- else
- return debugger.GetListener();
-}
diff --git a/source/Target/Queue.cpp b/source/Target/Queue.cpp
index 45fdbea13db5..c0683d10b151 100644
--- a/source/Target/Queue.cpp
+++ b/source/Target/Queue.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Queue.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/QueueList.h"
diff --git a/source/Target/QueueItem.cpp b/source/Target/QueueItem.cpp
index fe58980c01c1..a20fa918a758 100644
--- a/source/Target/QueueItem.cpp
+++ b/source/Target/QueueItem.cpp
@@ -94,7 +94,7 @@ std::string QueueItem::GetQueueLabel() {
ProcessSP QueueItem::GetProcessSP() { return m_process_wp.lock(); }
void QueueItem::FetchEntireItem() {
- if (m_have_fetched_entire_item == true)
+ if (m_have_fetched_entire_item)
return;
ProcessSP process_sp = m_process_wp.lock();
if (process_sp) {
diff --git a/source/Target/RegisterContext.cpp b/source/Target/RegisterContext.cpp
index eaec03d9b595..976f9e8b45e7 100644
--- a/source/Target/RegisterContext.cpp
+++ b/source/Target/RegisterContext.cpp
@@ -7,14 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/RegisterContext.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Core/Value.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Target/ExecutionContext.h"
@@ -24,6 +18,8 @@
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/RegisterNumber.cpp b/source/Target/RegisterNumber.cpp
index d1bb8adf56e1..8b01bd103395 100644
--- a/source/Target/RegisterNumber.cpp
+++ b/source/Target/RegisterNumber.cpp
@@ -61,26 +61,15 @@ bool RegisterNumber::operator==(RegisterNumber &rhs) {
return false;
if (m_kind == rhs.m_kind) {
- if (m_regnum == rhs.m_regnum)
- return true;
- else
- return false;
+ return m_regnum == rhs.m_regnum;
}
uint32_t rhs_regnum = rhs.GetAsKind(m_kind);
if (rhs_regnum != LLDB_INVALID_REGNUM) {
- if (m_regnum == rhs_regnum)
- return true;
- else
- return false;
+ return m_regnum == rhs_regnum;
}
uint32_t lhs_regnum = GetAsKind(rhs.m_kind);
- {
- if (lhs_regnum == rhs.m_regnum)
- return true;
- else
- return false;
- }
+ { return lhs_regnum == rhs.m_regnum; }
return false;
}
diff --git a/source/Target/SectionLoadHistory.cpp b/source/Target/SectionLoadHistory.cpp
index 5844da5d41e9..1229933793ff 100644
--- a/source/Target/SectionLoadHistory.cpp
+++ b/source/Target/SectionLoadHistory.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/SectionLoadHistory.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Utility/Stream.h"
diff --git a/source/Target/SectionLoadList.cpp b/source/Target/SectionLoadList.cpp
index 6839aaccaa52..ea9f7ea9911c 100644
--- a/source/Target/SectionLoadList.cpp
+++ b/source/Target/SectionLoadList.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/SectionLoadList.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/Block.h"
diff --git a/source/Target/StackFrame.cpp b/source/Target/StackFrame.cpp
index 2b9260f95f3f..3cea6444596c 100644
--- a/source/Target/StackFrame.cpp
+++ b/source/Target/StackFrame.cpp
@@ -7,17 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackFrame.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
@@ -32,8 +27,12 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/RegisterValue.h"
+
+#include "lldb/lldb-enumerations.h"
using namespace lldb;
using namespace lldb_private;
@@ -49,20 +48,19 @@ using namespace lldb_private;
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,
+ bool cfa_is_valid, addr_t pc, StackFrame::Kind kind,
const SymbolContext *sc_ptr)
: m_thread_wp(thread_sp), m_frame_index(frame_idx),
m_concrete_frame_index(unwind_frame_index), m_reg_context_sp(),
m_id(pc, cfa, nullptr), m_frame_code_addr(pc), m_sc(), 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(), m_mutex() {
+ m_stack_frame_kind(kind), m_variable_list_sp(),
+ m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
+ m_mutex() {
// 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) {
+ if (IsHistorical() && !m_cfa_is_valid) {
m_id.SetCFA(m_frame_index);
}
@@ -80,9 +78,9 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
m_concrete_frame_index(unwind_frame_index),
m_reg_context_sp(reg_context_sp), m_id(pc, cfa, nullptr),
m_frame_code_addr(pc), m_sc(), 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(),
+ m_frame_base_error(), m_cfa_is_valid(true),
+ m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
+ m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
m_mutex() {
if (sc_ptr != nullptr) {
m_sc = *sc_ptr;
@@ -106,9 +104,9 @@ StackFrame::StackFrame(const ThreadSP &thread_sp, user_id_t frame_idx,
m_id(pc_addr.GetLoadAddress(thread_sp->CalculateTarget().get()), cfa,
nullptr),
m_frame_code_addr(pc_addr), m_sc(), 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(),
+ m_frame_base_error(), m_cfa_is_valid(true),
+ m_stack_frame_kind(StackFrame::Kind::Regular), m_variable_list_sp(),
+ m_variable_list_value_objects(), m_recognized_frame_sp(), m_disassembly(),
m_mutex() {
if (sc_ptr != nullptr) {
m_sc = *sc_ptr;
@@ -210,7 +208,7 @@ const Address &StackFrame::GetFrameCodeAddress() {
bool StackFrame::ChangePC(addr_t pc) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// We can't change the pc value of a history stack frame - it is immutable.
- if (m_is_history_frame)
+ if (IsHistorical())
return false;
m_frame_code_addr.SetRawAddress(pc);
m_sc.Clear(false);
@@ -266,7 +264,8 @@ Block *StackFrame::GetFrameBlock() {
// StackFrame object, everyone will have as much information as possible and no
// one will ever have to look things up manually.
//----------------------------------------------------------------------
-const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
+const SymbolContext &
+StackFrame::GetSymbolContext(SymbolContextItem resolve_scope) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// Copy our internal symbol context into "sc".
if ((m_flags.Get() & resolve_scope) != resolve_scope) {
@@ -318,7 +317,7 @@ const SymbolContext &StackFrame::GetSymbolContext(uint32_t resolve_scope) {
// haven't already tried to lookup one of those things. If we haven't
// then we will do the query.
- uint32_t actual_resolve_scope = 0;
+ SymbolContextItem actual_resolve_scope = SymbolContextItem(0);
if (resolve_scope & eSymbolContextCompUnit) {
if (m_flags.IsClear(eSymbolContextCompUnit)) {
@@ -456,7 +455,7 @@ StackFrame::GetInScopeVariableList(bool get_file_globals,
bool must_have_valid_location) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
// We can't fetch variable information for a history stack frame.
- if (m_is_history_frame)
+ if (IsHistorical())
return VariableListSP();
VariableListSP var_list_sp(new VariableList);
@@ -490,7 +489,7 @@ ValueObjectSP StackFrame::GetValueForVariableExpressionPath(
VariableSP &var_sp, Status &error) {
llvm::StringRef original_var_expr = var_expr;
// We can't fetch variable information for a history stack frame.
- if (m_is_history_frame)
+ if (IsHistorical())
return ValueObjectSP();
if (var_expr.empty()) {
@@ -1080,9 +1079,9 @@ bool StackFrame::GetFrameBaseValue(Scalar &frame_base, Status *error_ptr) {
m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
exe_ctx.GetTargetPtr());
- if (m_sc.function->GetFrameBaseExpression().Evaluate(
+ if (!m_sc.function->GetFrameBaseExpression().Evaluate(
&exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr,
- expr_value, &m_frame_base_error) == false) {
+ expr_value, &m_frame_base_error)) {
// We should really have an error if evaluate returns, but in case we
// don't, lets set the error to something at least.
if (m_frame_base_error.Success())
@@ -1135,7 +1134,7 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
DynamicValueType use_dynamic) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
ValueObjectSP valobj_sp;
- if (m_is_history_frame) {
+ if (IsHistorical()) {
return valobj_sp;
}
VariableList *var_list = GetVariableList(true);
@@ -1164,7 +1163,7 @@ StackFrame::GetValueObjectForFrameVariable(const VariableSP &variable_sp,
ValueObjectSP StackFrame::TrackGlobalVariable(const VariableSP &variable_sp,
DynamicValueType use_dynamic) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_is_history_frame)
+ if (IsHistorical())
return ValueObjectSP();
// Check to make sure we aren't already tracking this variable?
@@ -1194,6 +1193,14 @@ bool StackFrame::IsInlined() {
return false;
}
+bool StackFrame::IsHistorical() const {
+ return m_stack_frame_kind == StackFrame::Kind::History;
+}
+
+bool StackFrame::IsArtificial() const {
+ return m_stack_frame_kind == StackFrame::Kind::Artificial;
+}
+
lldb::LanguageType StackFrame::GetLanguage() {
CompileUnit *cu = GetSymbolContext(eSymbolContextCompUnit).comp_unit;
if (cu)
@@ -1709,6 +1716,41 @@ lldb::ValueObjectSP StackFrame::GuessValueForRegisterAndOffset(ConstString reg,
GetFrameCodeAddress());
}
+lldb::ValueObjectSP StackFrame::FindVariable(ConstString name) {
+ ValueObjectSP value_sp;
+
+ if (!name)
+ return value_sp;
+
+ TargetSP target_sp = CalculateTarget();
+ ProcessSP process_sp = CalculateProcess();
+
+ if (!target_sp && !process_sp)
+ return value_sp;
+
+ VariableList variable_list;
+ VariableSP var_sp;
+ SymbolContext sc(GetSymbolContext(eSymbolContextBlock));
+
+ if (sc.block) {
+ const bool can_create = true;
+ const bool get_parent_variables = true;
+ const bool stop_if_block_is_inlined_function = true;
+
+ if (sc.block->AppendVariables(
+ can_create, get_parent_variables, stop_if_block_is_inlined_function,
+ [this](Variable *v) { return v->IsInScope(this); },
+ &variable_list)) {
+ var_sp = variable_list.FindVariable(name);
+ }
+
+ if (var_sp)
+ value_sp = GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
+ }
+
+ return value_sp;
+}
+
TargetSP StackFrame::CalculateTarget() {
TargetSP target_sp;
ThreadSP thread_sp(GetThread());
@@ -1910,3 +1952,11 @@ bool StackFrame::GetStatus(Stream &strm, bool show_frame_info, bool show_source,
}
return true;
}
+
+RecognizedStackFrameSP StackFrame::GetRecognizedFrame() {
+ if (!m_recognized_frame_sp) {
+ m_recognized_frame_sp =
+ StackFrameRecognizerManager::RecognizeFrame(CalculateStackFrame());
+ }
+ return m_recognized_frame_sp;
+}
diff --git a/source/Target/StackFrameList.cpp b/source/Target/StackFrameList.cpp
index 2380a91df41d..fc9fcec6c076 100644
--- a/source/Target/StackFrameList.cpp
+++ b/source/Target/StackFrameList.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackFrameList.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -27,6 +23,7 @@
#include "lldb/Target/Thread.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/Log.h"
+#include "llvm/ADT/SmallPtrSet.h"
//#define DEBUG_STACK_FRAMES 1
@@ -81,127 +78,119 @@ uint32_t StackFrameList::GetCurrentInlinedDepth() {
}
void StackFrameList::ResetCurrentInlinedDepth() {
+ if (!m_show_inlined_frames)
+ return;
+
std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_show_inlined_frames) {
- GetFramesUpTo(0);
- if (m_frames.empty())
- return;
- if (!m_frames[0]->IsInlined()) {
- m_current_inlined_depth = UINT32_MAX;
- m_current_inlined_pc = LLDB_INVALID_ADDRESS;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- if (log && log->GetVerbose())
- log->Printf(
- "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
- } else {
- // We only need to do something special about inlined blocks when we are
- // at the beginning of an inlined function:
- // FIXME: We probably also have to do something special if the PC is at
- // the END
- // of an inlined function, which coincides with the end of either its
- // containing function or another inlined function.
-
- lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
- Block *block_ptr = m_frames[0]->GetFrameBlock();
- if (block_ptr) {
- Address pc_as_address;
- pc_as_address.SetLoadAddress(curr_pc,
- &(m_thread.GetProcess()->GetTarget()));
- AddressRange containing_range;
- if (block_ptr->GetRangeContainingAddress(pc_as_address,
- containing_range)) {
- if (pc_as_address == containing_range.GetBaseAddress()) {
- // If we got here because of a breakpoint hit, then set the inlined
- // depth depending on where the breakpoint was set. If we got here
- // because of a crash, then set the inlined depth to the deepest
- // most block. Otherwise, we stopped here naturally as the result
- // of a step, so set ourselves in the containing frame of the whole
- // set of nested inlines, so the user can then "virtually" step
- // into the frames one by one, or next over the whole mess. Note:
- // We don't have to handle being somewhere in the middle of the
- // stack here, since ResetCurrentInlinedDepth doesn't get called if
- // there is a valid inlined depth set.
- StopInfoSP stop_info_sp = m_thread.GetStopInfo();
- if (stop_info_sp) {
- switch (stop_info_sp->GetStopReason()) {
- case eStopReasonWatchpoint:
- case eStopReasonException:
- case eStopReasonExec:
- case eStopReasonSignal:
- // In all these cases we want to stop in the deepest most
- // frame.
- m_current_inlined_pc = curr_pc;
- m_current_inlined_depth = 0;
- break;
- case eStopReasonBreakpoint: {
- // FIXME: Figure out what this break point is doing, and set the
- // inline depth
- // appropriately. Be careful to take into account breakpoints
- // that implement step over prologue, since that should do the
- // default calculation. For now, if the breakpoints
- // corresponding to this hit are all internal,
- // I set the stop location to the top of the inlined stack,
- // since that will make
- // things like stepping over prologues work right. But if
- // there are any non-internal breakpoints I do to the bottom of
- // the stack, since that was the old behavior.
- uint32_t bp_site_id = stop_info_sp->GetValue();
- BreakpointSiteSP bp_site_sp(
- m_thread.GetProcess()->GetBreakpointSiteList().FindByID(
- bp_site_id));
- bool all_internal = true;
- if (bp_site_sp) {
- uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
- for (uint32_t i = 0; i < num_owners; i++) {
- Breakpoint &bp_ref =
- bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
- if (!bp_ref.IsInternal()) {
- all_internal = false;
- }
- }
- }
- if (!all_internal) {
- m_current_inlined_pc = curr_pc;
- m_current_inlined_depth = 0;
- break;
- }
- }
- LLVM_FALLTHROUGH;
- default: {
- // Otherwise, we should set ourselves at the container of the
- // inlining, so that the user can descend into them. So first
- // we check whether we have more than one inlined block sharing
- // this PC:
- int num_inlined_functions = 0;
-
- for (Block *container_ptr = block_ptr->GetInlinedParent();
- container_ptr != nullptr;
- container_ptr = container_ptr->GetInlinedParent()) {
- if (!container_ptr->GetRangeContainingAddress(
- pc_as_address, containing_range))
- break;
- if (pc_as_address != containing_range.GetBaseAddress())
- break;
-
- num_inlined_functions++;
- }
- m_current_inlined_pc = curr_pc;
- m_current_inlined_depth = num_inlined_functions + 1;
- Log *log(
- lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
- if (log && log->GetVerbose())
- log->Printf("ResetCurrentInlinedDepth: setting inlined "
- "depth: %d 0x%" PRIx64 ".\n",
- m_current_inlined_depth, curr_pc);
-
- } break;
- }
- }
- }
+ GetFramesUpTo(0);
+ if (m_frames.empty())
+ return;
+ if (!m_frames[0]->IsInlined()) {
+ m_current_inlined_depth = UINT32_MAX;
+ m_current_inlined_pc = LLDB_INVALID_ADDRESS;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log && log->GetVerbose())
+ log->Printf(
+ "ResetCurrentInlinedDepth: Invalidating current inlined depth.\n");
+ return;
+ }
+
+ // We only need to do something special about inlined blocks when we are
+ // at the beginning of an inlined function:
+ // FIXME: We probably also have to do something special if the PC is at
+ // the END of an inlined function, which coincides with the end of either
+ // its containing function or another inlined function.
+
+ Block *block_ptr = m_frames[0]->GetFrameBlock();
+ if (!block_ptr)
+ return;
+
+ Address pc_as_address;
+ lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC();
+ pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget()));
+ AddressRange containing_range;
+ if (!block_ptr->GetRangeContainingAddress(pc_as_address, containing_range) ||
+ pc_as_address != containing_range.GetBaseAddress())
+ return;
+
+ // If we got here because of a breakpoint hit, then set the inlined depth
+ // depending on where the breakpoint was set. If we got here because of a
+ // crash, then set the inlined depth to the deepest most block. Otherwise,
+ // we stopped here naturally as the result of a step, so set ourselves in the
+ // containing frame of the whole set of nested inlines, so the user can then
+ // "virtually" step into the frames one by one, or next over the whole mess.
+ // Note: We don't have to handle being somewhere in the middle of the stack
+ // here, since ResetCurrentInlinedDepth doesn't get called if there is a
+ // valid inlined depth set.
+ StopInfoSP stop_info_sp = m_thread.GetStopInfo();
+ if (!stop_info_sp)
+ return;
+ switch (stop_info_sp->GetStopReason()) {
+ case eStopReasonWatchpoint:
+ case eStopReasonException:
+ case eStopReasonExec:
+ case eStopReasonSignal:
+ // In all these cases we want to stop in the deepest frame.
+ m_current_inlined_pc = curr_pc;
+ m_current_inlined_depth = 0;
+ break;
+ case eStopReasonBreakpoint: {
+ // FIXME: Figure out what this break point is doing, and set the inline
+ // depth appropriately. Be careful to take into account breakpoints that
+ // implement step over prologue, since that should do the default
+ // calculation. For now, if the breakpoints corresponding to this hit are
+ // all internal, I set the stop location to the top of the inlined stack,
+ // since that will make things like stepping over prologues work right.
+ // But if there are any non-internal breakpoints I do to the bottom of the
+ // stack, since that was the old behavior.
+ uint32_t bp_site_id = stop_info_sp->GetValue();
+ BreakpointSiteSP bp_site_sp(
+ m_thread.GetProcess()->GetBreakpointSiteList().FindByID(bp_site_id));
+ bool all_internal = true;
+ if (bp_site_sp) {
+ uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
+ for (uint32_t i = 0; i < num_owners; i++) {
+ Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
+ if (!bp_ref.IsInternal()) {
+ all_internal = false;
}
}
}
+ if (!all_internal) {
+ m_current_inlined_pc = curr_pc;
+ m_current_inlined_depth = 0;
+ break;
+ }
+ }
+ LLVM_FALLTHROUGH;
+ default: {
+ // Otherwise, we should set ourselves at the container of the inlining, so
+ // that the user can descend into them. So first we check whether we have
+ // more than one inlined block sharing this PC:
+ int num_inlined_functions = 0;
+
+ for (Block *container_ptr = block_ptr->GetInlinedParent();
+ container_ptr != nullptr;
+ container_ptr = container_ptr->GetInlinedParent()) {
+ if (!container_ptr->GetRangeContainingAddress(pc_as_address,
+ containing_range))
+ break;
+ if (pc_as_address != containing_range.GetBaseAddress())
+ break;
+
+ num_inlined_functions++;
+ }
+ m_current_inlined_pc = curr_pc;
+ m_current_inlined_depth = num_inlined_functions + 1;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log && log->GetVerbose())
+ log->Printf("ResetCurrentInlinedDepth: setting inlined "
+ "depth: %d 0x%" PRIx64 ".\n",
+ m_current_inlined_depth, curr_pc);
+
+ break;
+ }
}
}
@@ -226,8 +215,202 @@ void StackFrameList::SetCurrentInlinedDepth(uint32_t new_depth) {
m_current_inlined_pc = m_thread.GetRegisterContext()->GetPC();
}
+void StackFrameList::GetOnlyConcreteFramesUpTo(uint32_t end_idx,
+ Unwind *unwinder) {
+ assert(m_thread.IsValid() && "Expected valid thread");
+ assert(m_frames.size() <= end_idx && "Expected there to be frames to fill");
+
+ if (end_idx < m_concrete_frames_fetched)
+ return;
+
+ if (!unwinder)
+ return;
+
+ uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
+ if (num_frames <= end_idx + 1) {
+ // Done unwinding.
+ m_concrete_frames_fetched = UINT32_MAX;
+ }
+
+ // Don't create the frames eagerly. Defer this work to GetFrameAtIndex,
+ // which can lazily query the unwinder to create frames.
+ m_frames.resize(num_frames);
+}
+
+/// Find the unique path through the call graph from \p begin (with return PC
+/// \p return_pc) to \p end. On success this path is stored into \p path, and
+/// on failure \p path is unchanged.
+static void FindInterveningFrames(Function &begin, Function &end,
+ Target &target, addr_t return_pc,
+ std::vector<Function *> &path,
+ ModuleList &images, Log *log) {
+ LLDB_LOG(log, "Finding frames between {0} and {1}, retn-pc={2:x}",
+ begin.GetDisplayName(), end.GetDisplayName(), return_pc);
+
+ // Find a non-tail calling edge with the correct return PC.
+ auto first_level_edges = begin.GetCallEdges();
+ if (log)
+ for (const CallEdge &edge : first_level_edges)
+ LLDB_LOG(log, "FindInterveningFrames: found call with retn-PC = {0:x}",
+ edge.GetReturnPCAddress(begin, target));
+ auto first_edge_it = std::lower_bound(
+ first_level_edges.begin(), first_level_edges.end(), return_pc,
+ [&](const CallEdge &edge, addr_t target_pc) {
+ return edge.GetReturnPCAddress(begin, target) < target_pc;
+ });
+ if (first_edge_it == first_level_edges.end() ||
+ first_edge_it->GetReturnPCAddress(begin, target) != return_pc) {
+ LLDB_LOG(log, "No call edge outgoing from {0} with retn-PC == {1:x}",
+ begin.GetDisplayName(), return_pc);
+ return;
+ }
+ CallEdge &first_edge = const_cast<CallEdge &>(*first_edge_it);
+
+ // The first callee may not be resolved, or there may be nothing to fill in.
+ Function *first_callee = first_edge.GetCallee(images);
+ if (!first_callee) {
+ LLDB_LOG(log, "Could not resolve callee");
+ return;
+ }
+ if (first_callee == &end) {
+ LLDB_LOG(log, "Not searching further, first callee is {0} (retn-PC: {1:x})",
+ end.GetDisplayName(), return_pc);
+ return;
+ }
+
+ // Run DFS on the tail-calling edges out of the first callee to find \p end.
+ // Fully explore the set of functions reachable from the first edge via tail
+ // calls in order to detect ambiguous executions.
+ struct DFS {
+ std::vector<Function *> active_path = {};
+ std::vector<Function *> solution_path = {};
+ llvm::SmallPtrSet<Function *, 2> visited_nodes = {};
+ bool ambiguous = false;
+ Function *end;
+ ModuleList &images;
+
+ DFS(Function *end, ModuleList &images) : end(end), images(images) {}
+
+ void search(Function *first_callee, std::vector<Function *> &path) {
+ dfs(first_callee);
+ if (!ambiguous)
+ path = std::move(solution_path);
+ }
+
+ void dfs(Function *callee) {
+ // Found a path to the target function.
+ if (callee == end) {
+ if (solution_path.empty())
+ solution_path = active_path;
+ else
+ ambiguous = true;
+ return;
+ }
+
+ // Terminate the search if tail recursion is found, or more generally if
+ // there's more than one way to reach a target. This errs on the side of
+ // caution: it conservatively stops searching when some solutions are
+ // still possible to save time in the average case.
+ if (!visited_nodes.insert(callee).second) {
+ ambiguous = true;
+ return;
+ }
+
+ // Search the calls made from this callee.
+ active_path.push_back(callee);
+ for (CallEdge &edge : callee->GetTailCallingEdges()) {
+ Function *next_callee = edge.GetCallee(images);
+ if (!next_callee)
+ continue;
+
+ dfs(next_callee);
+ if (ambiguous)
+ return;
+ }
+ active_path.pop_back();
+ }
+ };
+
+ DFS(&end, images).search(first_callee, path);
+}
+
+/// Given that \p next_frame will be appended to the frame list, synthesize
+/// tail call frames between the current end of the list and \p next_frame.
+/// If any frames are added, adjust the frame index of \p next_frame.
+///
+/// --------------
+/// | ... | <- Completed frames.
+/// --------------
+/// | prev_frame |
+/// --------------
+/// | ... | <- Artificial frames inserted here.
+/// --------------
+/// | next_frame |
+/// --------------
+/// | ... | <- Not-yet-visited frames.
+/// --------------
+void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
+ TargetSP target_sp = next_frame.CalculateTarget();
+ if (!target_sp)
+ return;
+
+ lldb::RegisterContextSP next_reg_ctx_sp = next_frame.GetRegisterContext();
+ if (!next_reg_ctx_sp)
+ return;
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+
+ assert(!m_frames.empty() && "Cannot synthesize frames in an empty stack");
+ StackFrame &prev_frame = *m_frames.back().get();
+
+ // Find the functions prev_frame and next_frame are stopped in. The function
+ // objects are needed to search the lazy call graph for intervening frames.
+ Function *prev_func =
+ prev_frame.GetSymbolContext(eSymbolContextFunction).function;
+ if (!prev_func) {
+ LLDB_LOG(log, "SynthesizeTailCallFrames: can't find previous function");
+ return;
+ }
+ Function *next_func =
+ next_frame.GetSymbolContext(eSymbolContextFunction).function;
+ if (!next_func) {
+ LLDB_LOG(log, "SynthesizeTailCallFrames: can't find next function");
+ return;
+ }
+
+ // Try to find the unique sequence of (tail) calls which led from next_frame
+ // to prev_frame.
+ std::vector<Function *> path;
+ addr_t return_pc = next_reg_ctx_sp->GetPC();
+ Target &target = *target_sp.get();
+ ModuleList &images = next_frame.CalculateTarget()->GetImages();
+ FindInterveningFrames(*next_func, *prev_func, target, return_pc, path, images,
+ log);
+
+ // Push synthetic tail call frames.
+ for (Function *callee : llvm::reverse(path)) {
+ uint32_t frame_idx = m_frames.size();
+ uint32_t concrete_frame_idx = next_frame.GetConcreteFrameIndex();
+ addr_t cfa = LLDB_INVALID_ADDRESS;
+ bool cfa_is_valid = false;
+ addr_t pc =
+ callee->GetAddressRange().GetBaseAddress().GetLoadAddress(&target);
+ SymbolContext sc;
+ callee->CalculateSymbolContext(&sc);
+ auto synth_frame = std::make_shared<StackFrame>(
+ m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
+ cfa_is_valid, pc, StackFrame::Kind::Artificial, &sc);
+ m_frames.push_back(synth_frame);
+ LLDB_LOG(log, "Pushed frame {0}", callee->GetDisplayName());
+ }
+
+ // If any frames were created, adjust next_frame's index.
+ if (!path.empty())
+ next_frame.SetFrameIndex(m_frames.size());
+}
+
void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
- // this makes sure we do not fetch frames for an invalid thread
+ // Do not fetch frames for an invalid thread.
if (!m_thread.IsValid())
return;
@@ -238,201 +421,189 @@ void StackFrameList::GetFramesUpTo(uint32_t end_idx) {
Unwind *unwinder = m_thread.GetUnwinder();
- if (m_show_inlined_frames) {
+ if (!m_show_inlined_frames) {
+ GetOnlyConcreteFramesUpTo(end_idx, unwinder);
+ return;
+ }
+
#if defined(DEBUG_STACK_FRAMES)
- StreamFile s(stdout, false);
+ StreamFile s(stdout, false);
#endif
- // If we are hiding some frames from the outside world, we need to add
- // those onto the total count of frames to fetch. However, we don't need
- // to do that if end_idx is 0 since in that case we always get the first
- // concrete frame and all the inlined frames below it... And of course, if
- // end_idx is UINT32_MAX that means get all, so just do that...
-
- uint32_t inlined_depth = 0;
- if (end_idx > 0 && end_idx != UINT32_MAX) {
- inlined_depth = GetCurrentInlinedDepth();
- if (inlined_depth != UINT32_MAX) {
- if (end_idx > 0)
- end_idx += inlined_depth;
- }
+ // If we are hiding some frames from the outside world, we need to add
+ // those onto the total count of frames to fetch. However, we don't need
+ // to do that if end_idx is 0 since in that case we always get the first
+ // concrete frame and all the inlined frames below it... And of course, if
+ // end_idx is UINT32_MAX that means get all, so just do that...
+
+ uint32_t inlined_depth = 0;
+ if (end_idx > 0 && end_idx != UINT32_MAX) {
+ inlined_depth = GetCurrentInlinedDepth();
+ if (inlined_depth != UINT32_MAX) {
+ if (end_idx > 0)
+ end_idx += inlined_depth;
}
+ }
- StackFrameSP unwind_frame_sp;
- do {
- uint32_t idx = m_concrete_frames_fetched++;
- lldb::addr_t pc = LLDB_INVALID_ADDRESS;
- lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
- if (idx == 0) {
- // We might have already created frame zero, only create it if we need
- // to
- if (m_frames.empty()) {
- RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
-
- if (reg_ctx_sp) {
- const bool success =
- unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- // There shouldn't be any way not to get the frame info for frame
- // 0. But if the unwinder can't make one, lets make one by hand
- // with the
- // SP as the CFA and see if that gets any further.
- if (!success) {
- cfa = reg_ctx_sp->GetSP();
- pc = reg_ctx_sp->GetPC();
- }
-
- unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
- m_frames.size(), idx,
- reg_ctx_sp, cfa, pc, nullptr));
- m_frames.push_back(unwind_frame_sp);
+ StackFrameSP unwind_frame_sp;
+ do {
+ uint32_t idx = m_concrete_frames_fetched++;
+ lldb::addr_t pc = LLDB_INVALID_ADDRESS;
+ lldb::addr_t cfa = LLDB_INVALID_ADDRESS;
+ if (idx == 0) {
+ // We might have already created frame zero, only create it if we need
+ // to.
+ if (m_frames.empty()) {
+ RegisterContextSP reg_ctx_sp(m_thread.GetRegisterContext());
+
+ if (reg_ctx_sp) {
+ const bool success =
+ unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ // There shouldn't be any way not to get the frame info for frame
+ // 0. But if the unwinder can't make one, lets make one by hand
+ // with the SP as the CFA and see if that gets any further.
+ if (!success) {
+ cfa = reg_ctx_sp->GetSP();
+ pc = reg_ctx_sp->GetPC();
}
- } else {
- unwind_frame_sp = m_frames.front();
- cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
+
+ unwind_frame_sp.reset(new StackFrame(m_thread.shared_from_this(),
+ m_frames.size(), idx, reg_ctx_sp,
+ cfa, pc, nullptr));
+ m_frames.push_back(unwind_frame_sp);
}
} else {
- const bool success =
- unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
- if (!success) {
- // We've gotten to the end of the stack.
- SetAllFramesFetched();
- break;
- }
- 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, nullptr));
- m_frames.push_back(unwind_frame_sp);
+ unwind_frame_sp = m_frames.front();
+ cfa = unwind_frame_sp->m_id.GetCallFrameAddress();
}
+ } else {
+ const bool success =
+ unwinder && unwinder->GetFrameInfoAtIndex(idx, cfa, pc);
+ if (!success) {
+ // We've gotten to the end of the stack.
+ SetAllFramesFetched();
+ break;
+ }
+ const bool cfa_is_valid = true;
+ unwind_frame_sp.reset(
+ new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx, cfa,
+ cfa_is_valid, pc, StackFrame::Kind::Regular, nullptr));
- assert(unwind_frame_sp);
- SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
- eSymbolContextBlock | eSymbolContextFunction);
- Block *unwind_block = unwind_sc.block;
- if (unwind_block) {
- Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
- TargetSP target_sp = m_thread.CalculateTarget();
- // Be sure to adjust the frame address to match the address that was
- // used to lookup the symbol context above. If we are in the first
- // concrete frame, then we lookup using the current address, else we
- // decrement the address by one to get the correct location.
- if (idx > 0) {
- if (curr_frame_address.GetOffset() == 0) {
- // If curr_frame_address points to the first address in a section
- // then after adjustment it will point to an other section. In that
- // case resolve the address again to the correct section plus
- // offset form.
- addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
- target_sp.get(), AddressClass::eCode);
- curr_frame_address.SetOpcodeLoadAddress(
- load_addr - 1, target_sp.get(), AddressClass::eCode);
- } else {
- curr_frame_address.Slide(-1);
- }
- }
-
- SymbolContext next_frame_sc;
- Address next_frame_address;
+ // Create synthetic tail call frames between the previous frame and the
+ // newly-found frame. The new frame's index may change after this call,
+ // although its concrete index will stay the same.
+ SynthesizeTailCallFrames(*unwind_frame_sp.get());
- while (unwind_sc.GetParentOfInlinedScope(
- curr_frame_address, next_frame_sc, next_frame_address)) {
- next_frame_sc.line_entry.ApplyFileMappings(target_sp);
- StackFrameSP frame_sp(
- new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
- unwind_frame_sp->GetRegisterContextSP(), cfa,
- next_frame_address, &next_frame_sc));
+ m_frames.push_back(unwind_frame_sp);
+ }
- m_frames.push_back(frame_sp);
- unwind_sc = next_frame_sc;
- curr_frame_address = next_frame_address;
+ assert(unwind_frame_sp);
+ SymbolContext unwind_sc = unwind_frame_sp->GetSymbolContext(
+ eSymbolContextBlock | eSymbolContextFunction);
+ Block *unwind_block = unwind_sc.block;
+ if (unwind_block) {
+ Address curr_frame_address(unwind_frame_sp->GetFrameCodeAddress());
+ TargetSP target_sp = m_thread.CalculateTarget();
+ // Be sure to adjust the frame address to match the address that was
+ // used to lookup the symbol context above. If we are in the first
+ // concrete frame, then we lookup using the current address, else we
+ // decrement the address by one to get the correct location.
+ if (idx > 0) {
+ if (curr_frame_address.GetOffset() == 0) {
+ // If curr_frame_address points to the first address in a section
+ // then after adjustment it will point to an other section. In that
+ // case resolve the address again to the correct section plus
+ // offset form.
+ addr_t load_addr = curr_frame_address.GetOpcodeLoadAddress(
+ target_sp.get(), AddressClass::eCode);
+ curr_frame_address.SetOpcodeLoadAddress(
+ load_addr - 1, target_sp.get(), AddressClass::eCode);
+ } else {
+ curr_frame_address.Slide(-1);
}
}
- } while (m_frames.size() - 1 < end_idx);
- // Don't try to merge till you've calculated all the frames in this stack.
- if (GetAllFramesFetched() && m_prev_frames_sp) {
- StackFrameList *prev_frames = m_prev_frames_sp.get();
- StackFrameList *curr_frames = this;
+ SymbolContext next_frame_sc;
+ Address next_frame_address;
+
+ while (unwind_sc.GetParentOfInlinedScope(
+ curr_frame_address, next_frame_sc, next_frame_address)) {
+ next_frame_sc.line_entry.ApplyFileMappings(target_sp);
+ StackFrameSP frame_sp(
+ new StackFrame(m_thread.shared_from_this(), m_frames.size(), idx,
+ unwind_frame_sp->GetRegisterContextSP(), cfa,
+ next_frame_address, &next_frame_sc));
+
+ m_frames.push_back(frame_sp);
+ unwind_sc = next_frame_sc;
+ curr_frame_address = next_frame_address;
+ }
+ }
+ } while (m_frames.size() - 1 < end_idx);
-// curr_frames->m_current_inlined_depth = prev_frames->m_current_inlined_depth;
-// curr_frames->m_current_inlined_pc = prev_frames->m_current_inlined_pc;
-// printf ("GetFramesUpTo: Copying current inlined depth: %d 0x%" PRIx64 ".\n",
-// curr_frames->m_current_inlined_depth, curr_frames->m_current_inlined_pc);
+ // Don't try to merge till you've calculated all the frames in this stack.
+ if (GetAllFramesFetched() && m_prev_frames_sp) {
+ StackFrameList *prev_frames = m_prev_frames_sp.get();
+ StackFrameList *curr_frames = this;
#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("\nprev_frames:\n");
- prev_frames->Dump(&s);
- s.PutCString("\ncurr_frames:\n");
- curr_frames->Dump(&s);
- s.EOL();
+ s.PutCString("\nprev_frames:\n");
+ prev_frames->Dump(&s);
+ s.PutCString("\ncurr_frames:\n");
+ curr_frames->Dump(&s);
+ s.EOL();
#endif
- size_t curr_frame_num, prev_frame_num;
+ size_t curr_frame_num, prev_frame_num;
- for (curr_frame_num = curr_frames->m_frames.size(),
- prev_frame_num = prev_frames->m_frames.size();
- curr_frame_num > 0 && prev_frame_num > 0;
- --curr_frame_num, --prev_frame_num) {
- const size_t curr_frame_idx = curr_frame_num - 1;
- const size_t prev_frame_idx = prev_frame_num - 1;
- StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
- StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
+ for (curr_frame_num = curr_frames->m_frames.size(),
+ prev_frame_num = prev_frames->m_frames.size();
+ curr_frame_num > 0 && prev_frame_num > 0;
+ --curr_frame_num, --prev_frame_num) {
+ const size_t curr_frame_idx = curr_frame_num - 1;
+ const size_t prev_frame_idx = prev_frame_num - 1;
+ StackFrameSP curr_frame_sp(curr_frames->m_frames[curr_frame_idx]);
+ StackFrameSP prev_frame_sp(prev_frames->m_frames[prev_frame_idx]);
#if defined(DEBUG_STACK_FRAMES)
- s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
- if (curr_frame_sp)
- curr_frame_sp->Dump(&s, true, false);
- else
- s.PutCString("NULL");
- s.Printf("\nPrev frame #%u ", prev_frame_idx);
- if (prev_frame_sp)
- prev_frame_sp->Dump(&s, true, false);
- else
- s.PutCString("NULL");
+ s.Printf("\n\nCurr frame #%u ", curr_frame_idx);
+ if (curr_frame_sp)
+ curr_frame_sp->Dump(&s, true, false);
+ else
+ s.PutCString("NULL");
+ s.Printf("\nPrev frame #%u ", prev_frame_idx);
+ if (prev_frame_sp)
+ prev_frame_sp->Dump(&s, true, false);
+ else
+ s.PutCString("NULL");
#endif
- StackFrame *curr_frame = curr_frame_sp.get();
- StackFrame *prev_frame = prev_frame_sp.get();
+ StackFrame *curr_frame = curr_frame_sp.get();
+ StackFrame *prev_frame = prev_frame_sp.get();
- if (curr_frame == nullptr || prev_frame == nullptr)
- break;
+ if (curr_frame == nullptr || prev_frame == nullptr)
+ break;
- // Check the stack ID to make sure they are equal
- if (curr_frame->GetStackID() != prev_frame->GetStackID())
- break;
+ // Check the stack ID to make sure they are equal.
+ if (curr_frame->GetStackID() != prev_frame->GetStackID())
+ break;
- prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
- // Now copy the fixed up previous frame into the current frames so the
- // pointer doesn't change
- m_frames[curr_frame_idx] = prev_frame_sp;
-// curr_frame->UpdateCurrentFrameFromPreviousFrame (*prev_frame);
+ prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
+ // Now copy the fixed up previous frame into the current frames so the
+ // pointer doesn't change.
+ m_frames[curr_frame_idx] = prev_frame_sp;
#if defined(DEBUG_STACK_FRAMES)
- s.Printf("\n Copying previous frame to current frame");
+ s.Printf("\n Copying previous frame to current frame");
#endif
- }
- // We are done with the old stack frame list, we can release it now
- m_prev_frames_sp.reset();
}
+ // We are done with the old stack frame list, we can release it now.
+ m_prev_frames_sp.reset();
+ }
#if defined(DEBUG_STACK_FRAMES)
- s.PutCString("\n\nNew frames:\n");
- Dump(&s);
- s.EOL();
+ s.PutCString("\n\nNew frames:\n");
+ Dump(&s);
+ s.EOL();
#endif
- } else {
- if (end_idx < m_concrete_frames_fetched)
- return;
-
- if (unwinder) {
- uint32_t num_frames = unwinder->GetFramesUpTo(end_idx);
- if (num_frames <= end_idx + 1) {
- // Done unwinding.
- m_concrete_frames_fetched = UINT32_MAX;
- }
- m_frames.resize(num_frames);
- }
- }
}
uint32_t StackFrameList::GetNumFrames(bool can_create) {
@@ -441,11 +612,7 @@ uint32_t StackFrameList::GetNumFrames(bool can_create) {
if (can_create)
GetFramesUpTo(UINT32_MAX);
- uint32_t inlined_depth = GetCurrentInlinedDepth();
- if (inlined_depth == UINT32_MAX)
- return m_frames.size();
- else
- return m_frames.size() - inlined_depth;
+ return GetVisibleStackFrameIndex(m_frames.size());
}
void StackFrameList::Dump(Stream *s) {
@@ -497,11 +664,9 @@ StackFrameSP StackFrameList::GetFrameAtIndex(uint32_t idx) {
addr_t pc, cfa;
if (unwinder->GetFrameInfoAtIndex(idx, cfa, pc)) {
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, nullptr));
+ frame_sp.reset(new StackFrame(m_thread.shared_from_this(), idx, idx,
+ cfa, cfa_is_valid, pc,
+ StackFrame::Kind::Regular, nullptr));
Function *function =
frame_sp->GetSymbolContext(eSymbolContextFunction).function;
@@ -576,9 +741,6 @@ StackFrameSP StackFrameList::GetFrameWithStackID(const StackID &stack_id) {
if ((*pos)->GetStackID() == stack_id)
return *pos;
}
-
- // if (m_frames.back()->GetStackID() < stack_id)
- // frame_idx = m_frames.size();
}
do {
frame_sp = GetFrameAtIndex(frame_idx);
@@ -625,7 +787,6 @@ uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
return m_selected_frame_idx;
}
-// Mark a stack frame as the current frame using the frame index
bool StackFrameList::SetSelectedFrameByIndex(uint32_t idx) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
StackFrameSP frame_sp(GetFrameAtIndex(idx));
@@ -657,19 +818,6 @@ void StackFrameList::Clear() {
m_concrete_frames_fetched = 0;
}
-void StackFrameList::InvalidateFrames(uint32_t start_idx) {
- std::lock_guard<std::recursive_mutex> guard(m_mutex);
- if (m_show_inlined_frames) {
- Clear();
- } else {
- const size_t num_frames = m_frames.size();
- while (start_idx < num_frames) {
- m_frames[start_idx].reset();
- ++start_idx;
- }
- }
-}
-
void StackFrameList::Merge(std::unique_ptr<StackFrameList> &curr_ap,
lldb::StackFrameListSP &prev_sp) {
std::unique_lock<std::recursive_mutex> current_lock, previous_lock;
diff --git a/source/Target/StackFrameRecognizer.cpp b/source/Target/StackFrameRecognizer.cpp
new file mode 100644
index 000000000000..152f4a198e20
--- /dev/null
+++ b/source/Target/StackFrameRecognizer.cpp
@@ -0,0 +1,191 @@
+//===-- StackFrameRecognizer.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 "lldb/Core/Module.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/StackFrameRecognizer.h"
+#include "lldb/Utility/RegularExpression.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#ifndef LLDB_DISABLE_PYTHON
+
+class ScriptedRecognizedStackFrame : public RecognizedStackFrame {
+public:
+ ScriptedRecognizedStackFrame(ValueObjectListSP args) {
+ m_arguments = args;
+ }
+};
+
+ScriptedStackFrameRecognizer::ScriptedStackFrameRecognizer(
+ ScriptInterpreter *interpreter, const char *pclass)
+ : m_interpreter(interpreter), m_python_class(pclass) {
+ m_python_object_sp =
+ m_interpreter->CreateFrameRecognizer(m_python_class.c_str());
+}
+
+RecognizedStackFrameSP
+ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
+ if (!m_python_object_sp || !m_interpreter)
+ return RecognizedStackFrameSP();
+
+ ValueObjectListSP args =
+ m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
+
+ return RecognizedStackFrameSP(new ScriptedRecognizedStackFrame(args));
+}
+
+#endif
+
+class StackFrameRecognizerManagerImpl {
+public:
+ void AddRecognizer(StackFrameRecognizerSP recognizer,
+ const ConstString &module, const ConstString &symbol,
+ bool first_instruction_only) {
+ m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, false, module, RegularExpressionSP(),
+ symbol, RegularExpressionSP(),
+ first_instruction_only});
+ }
+
+ void AddRecognizer(StackFrameRecognizerSP recognizer,
+ RegularExpressionSP module, RegularExpressionSP symbol,
+ bool first_instruction_only) {
+ m_recognizers.push_front({(uint32_t)m_recognizers.size(), false, recognizer, true, ConstString(), module,
+ ConstString(), symbol, first_instruction_only});
+ }
+
+ void ForEach(
+ std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module,
+ std::string symbol, bool regexp)> const &callback) {
+ for (auto entry : m_recognizers) {
+ if (entry.is_regexp) {
+ callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module_regexp->GetText(),
+ entry.symbol_regexp->GetText(), true);
+ } else {
+ callback(entry.recognizer_id, entry.recognizer->GetName(), entry.module.GetCString(),
+ entry.symbol.GetCString(), false);
+ }
+ }
+ }
+
+ bool RemoveRecognizerWithID(uint32_t recognizer_id) {
+ if (recognizer_id >= m_recognizers.size()) return false;
+ if (m_recognizers[recognizer_id].deleted) return false;
+ m_recognizers[recognizer_id].deleted = true;
+ return true;
+ }
+
+ void RemoveAllRecognizers() {
+ m_recognizers.clear();
+ }
+
+ StackFrameRecognizerSP GetRecognizerForFrame(StackFrameSP frame) {
+ const SymbolContext &symctx =
+ frame->GetSymbolContext(eSymbolContextModule | eSymbolContextFunction);
+ ConstString function_name = symctx.GetFunctionName();
+ ModuleSP module_sp = symctx.module_sp;
+ if (!module_sp) return StackFrameRecognizerSP();
+ ConstString module_name = module_sp->GetFileSpec().GetFilename();
+ Symbol *symbol = symctx.symbol;
+ if (!symbol) return StackFrameRecognizerSP();
+ Address start_addr = symbol->GetAddress();
+ Address current_addr = frame->GetFrameCodeAddress();
+
+ for (auto entry : m_recognizers) {
+ if (entry.deleted) continue;
+ if (entry.module)
+ if (entry.module != module_name) continue;
+
+ if (entry.module_regexp)
+ if (!entry.module_regexp->Execute(module_name.GetStringRef())) continue;
+
+ if (entry.symbol)
+ if (entry.symbol != function_name) continue;
+
+ if (entry.symbol_regexp)
+ if (!entry.symbol_regexp->Execute(function_name.GetStringRef()))
+ continue;
+
+ if (entry.first_instruction_only)
+ if (start_addr != current_addr) continue;
+
+ return entry.recognizer;
+ }
+ return StackFrameRecognizerSP();
+ }
+
+ RecognizedStackFrameSP RecognizeFrame(StackFrameSP frame) {
+ auto recognizer = GetRecognizerForFrame(frame);
+ if (!recognizer) return RecognizedStackFrameSP();
+ return recognizer->RecognizeFrame(frame);
+ }
+
+ private:
+ struct RegisteredEntry {
+ uint32_t recognizer_id;
+ bool deleted;
+ StackFrameRecognizerSP recognizer;
+ bool is_regexp;
+ ConstString module;
+ RegularExpressionSP module_regexp;
+ ConstString symbol;
+ RegularExpressionSP symbol_regexp;
+ bool first_instruction_only;
+ };
+
+ std::deque<RegisteredEntry> m_recognizers;
+};
+
+StackFrameRecognizerManagerImpl &GetStackFrameRecognizerManagerImpl() {
+ static StackFrameRecognizerManagerImpl instance =
+ StackFrameRecognizerManagerImpl();
+ return instance;
+}
+
+void StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP recognizer, const ConstString &module,
+ const ConstString &symbol, bool first_instruction_only) {
+ GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
+ first_instruction_only);
+}
+
+void StackFrameRecognizerManager::AddRecognizer(
+ StackFrameRecognizerSP recognizer, RegularExpressionSP module,
+ RegularExpressionSP symbol, bool first_instruction_only) {
+ GetStackFrameRecognizerManagerImpl().AddRecognizer(recognizer, module, symbol,
+ first_instruction_only);
+}
+
+void StackFrameRecognizerManager::ForEach(
+ std::function<void(uint32_t recognized_id, std::string recognizer_name, std::string module,
+ std::string symbol, bool regexp)> const &callback) {
+ GetStackFrameRecognizerManagerImpl().ForEach(callback);
+}
+
+void StackFrameRecognizerManager::RemoveAllRecognizers() {
+ GetStackFrameRecognizerManagerImpl().RemoveAllRecognizers();
+}
+
+bool StackFrameRecognizerManager::RemoveRecognizerWithID(uint32_t recognizer_id) {
+ return GetStackFrameRecognizerManagerImpl().RemoveRecognizerWithID(recognizer_id);
+}
+
+RecognizedStackFrameSP StackFrameRecognizerManager::RecognizeFrame(
+ StackFrameSP frame) {
+ return GetStackFrameRecognizerManagerImpl().RecognizeFrame(frame);
+}
+
+StackFrameRecognizerSP StackFrameRecognizerManager::GetRecognizerForFrame(
+ lldb::StackFrameSP frame) {
+ return GetStackFrameRecognizerManagerImpl().GetRecognizerForFrame(frame);
+}
diff --git a/source/Target/StackID.cpp b/source/Target/StackID.cpp
index 341c902af995..d6640b24ad5c 100644
--- a/source/Target/StackID.cpp
+++ b/source/Target/StackID.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/StackID.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Symbol.h"
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index f8b17dc10eca..4e13c588b484 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -333,6 +329,19 @@ protected:
// commands when we see the same breakpoint hit a second time.
m_should_stop_is_valid = true;
+
+ // It is possible that the user has a breakpoint at the same site
+ // as the completed plan had (e.g. user has a breakpoint
+ // on a module entry point, and `ThreadPlanCallFunction` ends
+ // also there). We can't find an internal breakpoint in the loop
+ // later because it was already removed on the plan completion.
+ // So check if the plan was completed, and stop if so.
+ if (thread_sp->CompletedPlanOverridesBreakpoint()) {
+ m_should_stop = true;
+ thread_sp->ResetStopInfo();
+ return;
+ }
+
if (log)
log->Printf("StopInfoBreakpoint::PerformAction - Hit a "
"breakpoint while running an expression,"
@@ -358,9 +367,8 @@ protected:
"continuing: %s.",
m_should_stop ? "true" : "false");
process->GetTarget().GetDebugger().GetAsyncOutputStream()->Printf(
- "Warning: hit breakpoint while "
- "running function, skipping commands and conditions to prevent "
- "recursion.");
+ "Warning: hit breakpoint while running function, skipping "
+ "commands and conditions to prevent recursion.\n");
return;
}
@@ -534,9 +542,9 @@ protected:
__FUNCTION__, m_value);
}
- if ((m_should_stop == false || internal_breakpoint)
- && thread_sp->CompletedPlanOverridesBreakpoint()) {
-
+ if ((!m_should_stop || internal_breakpoint) &&
+ thread_sp->CompletedPlanOverridesBreakpoint()) {
+
// Override should_stop decision when we have completed step plan
// additionally to the breakpoint
m_should_stop = true;
@@ -720,14 +728,18 @@ protected:
StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo();
assert(stored_stop_info_sp.get() == this);
+ Status new_plan_status;
ThreadPlanSP new_plan_sp(
thread_sp->QueueThreadPlanForStepSingleInstruction(
- false, // step-over
- false, // abort_other_plans
- true)); // stop_other_threads
- new_plan_sp->SetIsMasterPlan(true);
- new_plan_sp->SetOkayToDiscard(false);
- new_plan_sp->SetPrivate(true);
+ false, // step-over
+ false, // abort_other_plans
+ true, // stop_other_threads
+ new_plan_status));
+ if (new_plan_sp && new_plan_status.Success()) {
+ new_plan_sp->SetIsMasterPlan(true);
+ new_plan_sp->SetOkayToDiscard(false);
+ new_plan_sp->SetPrivate(true);
+ }
process_sp->GetThreadList().SetSelectedThreadByID(
thread_sp->GetID());
process_sp->ResumeSynchronous(nullptr);
diff --git a/source/Target/SystemRuntime.cpp b/source/Target/SystemRuntime.cpp
index 3fdf6daa6afa..574c01cb5ae1 100644
--- a/source/Target/SystemRuntime.cpp
+++ b/source/Target/SystemRuntime.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"
diff --git a/source/Target/Target.cpp b/source/Target/Target.cpp
index 3f70741713fb..437f92abdab3 100644
--- a/source/Target/Target.cpp
+++ b/source/Target/Target.cpp
@@ -7,11 +7,7 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-#include <mutex>
-// Other libraries and framework includes
-// Project includes
+#include "lldb/Target/Target.h"
#include "Plugins/ExpressionParser/Clang/ClangASTSource.h"
#include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h"
#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
@@ -21,16 +17,17 @@
#include "lldb/Breakpoint/BreakpointResolverFileLine.h"
#include "lldb/Breakpoint/BreakpointResolverFileRegex.h"
#include "lldb/Breakpoint/BreakpointResolverName.h"
+#include "lldb/Breakpoint/BreakpointResolverScripted.h"
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/SearchFilter.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/SourceManager.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/REPL.h"
#include "lldb/Expression/UserExpression.h"
@@ -52,14 +49,16 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/SystemRuntime.h"
-#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadSpec.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
+#include <mutex>
using namespace lldb;
using namespace lldb_private;
@@ -195,6 +194,8 @@ void Target::DeleteCurrentProcess() {
const lldb::ProcessSP &Target::CreateProcess(ListenerSP listener_sp,
llvm::StringRef plugin_name,
const FileSpec *crash_file) {
+ if (!listener_sp)
+ listener_sp = GetDebugger().GetListener();
DeleteCurrentProcess();
m_process_sp = Process::FindPlugin(shared_from_this(), plugin_name,
listener_sp, crash_file);
@@ -322,7 +323,7 @@ BreakpointSP Target::CreateSourceRegexBreakpoint(
BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
const FileSpec &file, uint32_t line_no,
- lldb::addr_t offset,
+ uint32_t column, lldb::addr_t offset,
LazyBool check_inlines,
LazyBool skip_prologue, bool internal,
bool hardware,
@@ -366,8 +367,8 @@ BreakpointSP Target::CreateBreakpoint(const FileSpecList *containingModules,
move_to_nearest_code = GetMoveToNearestCode() ? eLazyBoolYes : eLazyBoolNo;
BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine(
- nullptr, remapped_file, line_no, offset, check_inlines, skip_prologue,
- !static_cast<bool>(move_to_nearest_code)));
+ nullptr, remapped_file, line_no, column, offset, check_inlines,
+ skip_prologue, !static_cast<bool>(move_to_nearest_code)));
return CreateBreakpoint(filter_sp, resolver_sp, internal, hardware, true);
}
@@ -412,12 +413,11 @@ Target::CreateAddressInModuleBreakpoint(lldb::addr_t file_addr, bool internal,
false);
}
-BreakpointSP
-Target::CreateBreakpoint(const FileSpecList *containingModules,
- const FileSpecList *containingSourceFiles,
- const char *func_name, uint32_t func_name_type_mask,
- LanguageType language, lldb::addr_t offset,
- LazyBool skip_prologue, bool internal, bool hardware) {
+BreakpointSP Target::CreateBreakpoint(
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles, const char *func_name,
+ FunctionNameType func_name_type_mask, LanguageType language,
+ lldb::addr_t offset, LazyBool skip_prologue, bool internal, bool hardware) {
BreakpointSP bp_sp;
if (func_name) {
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
@@ -440,9 +440,9 @@ lldb::BreakpointSP
Target::CreateBreakpoint(const FileSpecList *containingModules,
const FileSpecList *containingSourceFiles,
const std::vector<std::string> &func_names,
- uint32_t func_name_type_mask, LanguageType language,
- lldb::addr_t offset, LazyBool skip_prologue,
- bool internal, bool hardware) {
+ FunctionNameType func_name_type_mask,
+ LanguageType language, lldb::addr_t offset,
+ LazyBool skip_prologue, bool internal, bool hardware) {
BreakpointSP bp_sp;
size_t num_names = func_names.size();
if (num_names > 0) {
@@ -462,11 +462,13 @@ Target::CreateBreakpoint(const FileSpecList *containingModules,
return bp_sp;
}
-BreakpointSP Target::CreateBreakpoint(
- const FileSpecList *containingModules,
- const FileSpecList *containingSourceFiles, const char *func_names[],
- size_t num_names, uint32_t func_name_type_mask, LanguageType language,
- lldb::addr_t offset, LazyBool skip_prologue, bool internal, bool hardware) {
+BreakpointSP
+Target::CreateBreakpoint(const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ const char *func_names[], size_t num_names,
+ FunctionNameType func_name_type_mask,
+ LanguageType language, lldb::addr_t offset,
+ LazyBool skip_prologue, bool internal, bool hardware) {
BreakpointSP bp_sp;
if (num_names > 0) {
SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList(
@@ -579,13 +581,56 @@ Target::CreateExceptionBreakpoint(enum lldb::LanguageType language,
return exc_bkpt_sp;
}
+lldb::BreakpointSP
+Target::CreateScriptedBreakpoint(const llvm::StringRef class_name,
+ const FileSpecList *containingModules,
+ const FileSpecList *containingSourceFiles,
+ bool internal,
+ bool request_hardware,
+ StructuredData::ObjectSP extra_args_sp,
+ Status *creation_error)
+{
+ SearchFilterSP filter_sp;
+
+ lldb::SearchDepth depth = lldb::eSearchDepthTarget;
+ bool has_files = containingSourceFiles && containingSourceFiles->GetSize() > 0;
+ bool has_modules = containingModules && containingModules->GetSize() > 0;
+
+ if (has_files && has_modules) {
+ filter_sp = GetSearchFilterForModuleAndCUList(
+ containingModules, containingSourceFiles);
+ } else if (has_files) {
+ filter_sp = GetSearchFilterForModuleAndCUList(
+ nullptr, containingSourceFiles);
+ } else if (has_modules) {
+ filter_sp = GetSearchFilterForModuleList(containingModules);
+ } else {
+ filter_sp.reset(new SearchFilterForUnconstrainedSearches(shared_from_this()));
+ }
+
+ StructuredDataImpl *extra_args_impl = new StructuredDataImpl();
+ if (extra_args_sp)
+ extra_args_impl->SetObjectSP(extra_args_sp);
+
+ BreakpointResolverSP resolver_sp(new
+ BreakpointResolverScripted(nullptr, class_name,
+ depth,
+ extra_args_impl,
+ *GetDebugger().GetCommandInterpreter()
+ .GetScriptInterpreter()));
+ return CreateBreakpoint(filter_sp, resolver_sp, internal, false, true);
+
+}
+
+
BreakpointSP Target::CreateBreakpoint(SearchFilterSP &filter_sp,
BreakpointResolverSP &resolver_sp,
bool internal, bool request_hardware,
bool resolve_indirect_symbols) {
BreakpointSP bp_sp;
if (filter_sp && resolver_sp) {
- bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, request_hardware,
+ const bool hardware = request_hardware || GetRequireHardwareBreakpoints();
+ bp_sp.reset(new Breakpoint(*this, filter_sp, resolver_sp, hardware,
resolve_indirect_symbols));
resolver_sp->SetBreakpoint(bp_sp.get());
AddBreakpoint(bp_sp, internal);
@@ -719,17 +764,23 @@ void Target::GetBreakpointNames(std::vector<std::string> &names)
for (auto bp_name : m_breakpoint_names) {
names.push_back(bp_name.first.AsCString());
}
- std::sort(names.begin(), names.end());
+ llvm::sort(names.begin(), names.end());
}
bool Target::ProcessIsValid() {
return (m_process_sp && m_process_sp->IsAlive());
}
-static bool CheckIfWatchpointsExhausted(Target *target, Status &error) {
+static bool CheckIfWatchpointsSupported(Target *target, Status &error) {
uint32_t num_supported_hardware_watchpoints;
Status rc = target->GetProcessSP()->GetWatchpointSupportInfo(
num_supported_hardware_watchpoints);
+
+ // If unable to determine the # of watchpoints available,
+ // assume they are supported.
+ if (rc.Fail())
+ return true;
+
if (num_supported_hardware_watchpoints == 0) {
error.SetErrorStringWithFormat(
"Target supports (%u) hardware watchpoint slots.\n",
@@ -768,7 +819,7 @@ WatchpointSP Target::CreateWatchpoint(lldb::addr_t addr, size_t size,
error.SetErrorStringWithFormat("invalid watchpoint type: %d", kind);
}
- if (!CheckIfWatchpointsExhausted(this, error))
+ if (!CheckIfWatchpointsSupported(this, error))
return wp_sp;
// Currently we only support one watchpoint per address, with total number of
@@ -1377,7 +1428,7 @@ void Target::DidExec() {
}
void Target::SetExecutableModule(ModuleSP &executable_sp,
- bool get_dependent_files) {
+ LoadDependentFiles load_dependent_files) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
ClearModules(false);
@@ -1401,8 +1452,20 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
FileSpecList dependent_files;
ObjectFile *executable_objfile = executable_sp->GetObjectFile();
+ bool load_dependents = true;
+ switch (load_dependent_files) {
+ case eLoadDependentsDefault:
+ load_dependents = executable_sp->IsExecutable();
+ break;
+ case eLoadDependentsYes:
+ load_dependents = true;
+ break;
+ case eLoadDependentsNo:
+ load_dependents = false;
+ break;
+ }
- if (executable_objfile && get_dependent_files) {
+ if (executable_objfile && load_dependents) {
executable_objfile->GetDependentModules(dependent_files);
for (uint32_t i = 0; i < dependent_files.GetSize(); i++) {
FileSpec dependent_file_spec(
@@ -1426,13 +1489,33 @@ void Target::SetExecutableModule(ModuleSP &executable_sp,
}
}
-bool Target::SetArchitecture(const ArchSpec &arch_spec) {
+bool Target::SetArchitecture(const ArchSpec &arch_spec, bool set_platform) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
bool missing_local_arch = !m_arch.GetSpec().IsValid();
bool replace_local_arch = true;
bool compatible_local_arch = false;
ArchSpec other(arch_spec);
+ // Changing the architecture might mean that the currently selected platform
+ // isn't compatible. Set the platform correctly if we are asked to do so,
+ // otherwise assume the user will set the platform manually.
+ if (set_platform) {
+ if (other.IsValid()) {
+ auto platform_sp = GetPlatform();
+ if (!platform_sp ||
+ !platform_sp->IsCompatibleArchitecture(other, false, nullptr)) {
+ ArchSpec platform_arch;
+ auto arch_platform_sp =
+ Platform::GetPlatformForArchitecture(other, &platform_arch);
+ if (arch_platform_sp) {
+ SetPlatform(arch_platform_sp);
+ if (platform_arch.IsValid())
+ other = platform_arch;
+ }
+ }
+ }
+ }
+
if (!missing_local_arch) {
if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
other.MergeFrom(m_arch.GetSpec());
@@ -1487,7 +1570,7 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) {
nullptr, nullptr);
if (!error.Fail() && executable_sp) {
- SetExecutableModule(executable_sp, true);
+ SetExecutableModule(executable_sp, eLoadDependentsYes);
return true;
}
}
@@ -1495,11 +1578,18 @@ bool Target::SetArchitecture(const ArchSpec &arch_spec) {
}
bool Target::MergeArchitecture(const ArchSpec &arch_spec) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TARGET));
if (arch_spec.IsValid()) {
if (m_arch.GetSpec().IsCompatibleMatch(arch_spec)) {
// The current target arch is compatible with "arch_spec", see if we can
// improve our current architecture using bits from "arch_spec"
+ if (log)
+ log->Printf("Target::MergeArchitecture target has arch %s, merging with "
+ "arch %s",
+ m_arch.GetSpec().GetTriple().getTriple().c_str(),
+ arch_spec.GetTriple().getTriple().c_str());
+
// Merge bits from arch_spec into "merged_arch" and set our architecture
ArchSpec merged_arch(m_arch.GetSpec());
merged_arch.MergeFrom(arch_spec);
@@ -2057,7 +2147,7 @@ void Target::ImageSearchPathsChanged(const PathMappingList &path_list,
Target *target = (Target *)baton;
ModuleSP exe_module_sp(target->GetExecutableModule());
if (exe_module_sp)
- target->SetExecutableModule(exe_module_sp, true);
+ target->SetExecutableModule(exe_module_sp, eLoadDependentsYes);
}
TypeSystem *Target::GetScratchTypeSystemForLanguage(Status *error,
@@ -2351,249 +2441,22 @@ lldb::addr_t Target::GetPersistentSymbol(const ConstString &name) {
lldb::addr_t Target::GetCallableLoadAddress(lldb::addr_t load_addr,
AddressClass addr_class) const {
- addr_t code_addr = load_addr;
- switch (m_arch.GetSpec().GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- switch (addr_class) {
- case AddressClass::eData:
- case AddressClass::eDebug:
- return LLDB_INVALID_ADDRESS;
-
- case AddressClass::eUnknown:
- case AddressClass::eInvalid:
- case AddressClass::eCode:
- case AddressClass::eCodeAlternateISA:
- case AddressClass::eRuntime:
- if ((code_addr & 2ull) || (addr_class == AddressClass::eCodeAlternateISA))
- code_addr |= 1ull;
- break;
- }
- break;
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (addr_class) {
- case AddressClass::eData:
- case AddressClass::eDebug:
- return LLDB_INVALID_ADDRESS;
-
- case AddressClass::eUnknown:
- case AddressClass::eInvalid:
- case AddressClass::eCode:
- case AddressClass::eCodeAlternateISA:
- case AddressClass::eRuntime:
- // Check if bit zero it no set?
- if ((code_addr & 1ull) == 0) {
- // Bit zero isn't set, check if the address is a multiple of 2?
- if (code_addr & 2ull) {
- // The address is a multiple of 2 so it must be thumb, set bit zero
- code_addr |= 1ull;
- } else if (addr_class == AddressClass::eCodeAlternateISA) {
- // We checked the address and the address claims to be the alternate
- // ISA which means thumb, so set bit zero.
- code_addr |= 1ull;
- }
- }
- break;
- }
- break;
-
- default:
- break;
- }
- return code_addr;
+ auto arch_plugin = GetArchitecturePlugin();
+ return arch_plugin ?
+ arch_plugin->GetCallableLoadAddress(load_addr, addr_class) : load_addr;
}
lldb::addr_t Target::GetOpcodeLoadAddress(lldb::addr_t load_addr,
AddressClass addr_class) const {
- addr_t opcode_addr = load_addr;
- switch (m_arch.GetSpec().GetMachine()) {
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el:
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (addr_class) {
- case AddressClass::eData:
- case AddressClass::eDebug:
- return LLDB_INVALID_ADDRESS;
-
- case AddressClass::eInvalid:
- case AddressClass::eUnknown:
- case AddressClass::eCode:
- case AddressClass::eCodeAlternateISA:
- case AddressClass::eRuntime:
- opcode_addr &= ~(1ull);
- break;
- }
- break;
-
- default:
- break;
- }
- return opcode_addr;
+ auto arch_plugin = GetArchitecturePlugin();
+ return arch_plugin ?
+ arch_plugin->GetOpcodeLoadAddress(load_addr, addr_class) : load_addr;
}
lldb::addr_t Target::GetBreakableLoadAddress(lldb::addr_t addr) {
- addr_t breakable_addr = addr;
- Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
-
- switch (m_arch.GetSpec().GetMachine()) {
- default:
- break;
- case llvm::Triple::mips:
- case llvm::Triple::mipsel:
- case llvm::Triple::mips64:
- case llvm::Triple::mips64el: {
- addr_t function_start = 0;
- addr_t current_offset = 0;
- uint32_t loop_count = 0;
- Address resolved_addr;
- uint32_t arch_flags = m_arch.GetSpec().GetFlags();
- bool IsMips16 = arch_flags & ArchSpec::eMIPSAse_mips16;
- bool IsMicromips = arch_flags & ArchSpec::eMIPSAse_micromips;
- SectionLoadList &section_load_list = GetSectionLoadList();
-
- if (section_load_list.IsEmpty())
- // No sections are loaded, so we must assume we are not running yet and
- // need to operate only on file address.
- m_images.ResolveFileAddress(addr, resolved_addr);
- else
- section_load_list.ResolveLoadAddress(addr, resolved_addr);
-
- // Get the function boundaries to make sure we don't scan back before the
- // beginning of the current function.
- ModuleSP temp_addr_module_sp(resolved_addr.GetModule());
- if (temp_addr_module_sp) {
- SymbolContext sc;
- uint32_t resolve_scope = eSymbolContextFunction | eSymbolContextSymbol;
- temp_addr_module_sp->ResolveSymbolContextForAddress(resolved_addr,
- resolve_scope, sc);
- Address sym_addr;
- if (sc.function)
- sym_addr = sc.function->GetAddressRange().GetBaseAddress();
- else if (sc.symbol)
- sym_addr = sc.symbol->GetAddress();
-
- function_start = sym_addr.GetLoadAddress(this);
- if (function_start == LLDB_INVALID_ADDRESS)
- function_start = sym_addr.GetFileAddress();
-
- if (function_start)
- current_offset = addr - function_start;
- }
-
- // If breakpoint address is start of function then we dont have to do
- // anything.
- if (current_offset == 0)
- return breakable_addr;
- else
- loop_count = current_offset / 2;
-
- if (loop_count > 3) {
- // Scan previous 6 bytes
- if (IsMips16 | IsMicromips)
- loop_count = 3;
- // For mips-only, instructions are always 4 bytes, so scan previous 4
- // bytes only.
- else
- loop_count = 2;
- }
-
- // Create Disassembler Instance
- lldb::DisassemblerSP disasm_sp(
- Disassembler::FindPlugin(m_arch.GetSpec(), nullptr, nullptr));
-
- ExecutionContext exe_ctx;
- CalculateExecutionContext(exe_ctx);
- InstructionList instruction_list;
- InstructionSP prev_insn;
- bool prefer_file_cache = true; // Read from file
- uint32_t inst_to_choose = 0;
-
- for (uint32_t i = 1; i <= loop_count; i++) {
- // Adjust the address to read from.
- resolved_addr.Slide(-2);
- AddressRange range(resolved_addr, i * 2);
- uint32_t insn_size = 0;
-
- disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache);
-
- uint32_t num_insns = disasm_sp->GetInstructionList().GetSize();
- if (num_insns) {
- prev_insn = disasm_sp->GetInstructionList().GetInstructionAtIndex(0);
- insn_size = prev_insn->GetOpcode().GetByteSize();
- if (i == 1 && insn_size == 2) {
- // This looks like a valid 2-byte instruction (but it could be a part
- // of upper 4 byte instruction).
- instruction_list.Append(prev_insn);
- inst_to_choose = 1;
- } else if (i == 2) {
- // Here we may get one 4-byte instruction or two 2-byte instructions.
- if (num_insns == 2) {
- // Looks like there are two 2-byte instructions above our
- // breakpoint target address. Now the upper 2-byte instruction is
- // either a valid 2-byte instruction or could be a part of it's
- // upper 4-byte instruction. In both cases we don't care because in
- // this case lower 2-byte instruction is definitely a valid
- // instruction and whatever i=1 iteration has found out is true.
- inst_to_choose = 1;
- break;
- } else if (insn_size == 4) {
- // This instruction claims its a valid 4-byte instruction. But it
- // could be a part of it's upper 4-byte instruction. Lets try
- // scanning upper 2 bytes to verify this.
- instruction_list.Append(prev_insn);
- inst_to_choose = 2;
- }
- } else if (i == 3) {
- if (insn_size == 4)
- // FIXME: We reached here that means instruction at [target - 4] has
- // already claimed to be a 4-byte instruction, and now instruction
- // at [target - 6] is also claiming that it's a 4-byte instruction.
- // This can not be true. In this case we can not decide the valid
- // previous instruction so we let lldb set the breakpoint at the
- // address given by user.
- inst_to_choose = 0;
- else
- // This is straight-forward
- inst_to_choose = 2;
- break;
- }
- } else {
- // Decode failed, bytes do not form a valid instruction. So whatever
- // previous iteration has found out is true.
- if (i > 1) {
- inst_to_choose = i - 1;
- break;
- }
- }
- }
-
- // Check if we are able to find any valid instruction.
- if (inst_to_choose) {
- if (inst_to_choose > instruction_list.GetSize())
- inst_to_choose--;
- prev_insn = instruction_list.GetInstructionAtIndex(inst_to_choose - 1);
-
- if (prev_insn->HasDelaySlot()) {
- uint32_t shift_size = prev_insn->GetOpcode().GetByteSize();
- // Adjust the breakable address
- breakable_addr = addr - shift_size;
- if (log)
- log->Printf("Target::%s Breakpoint at 0x%8.8" PRIx64
- " is adjusted to 0x%8.8" PRIx64 " due to delay slot\n",
- __FUNCTION__, addr, breakable_addr);
- }
- }
- break;
- }
- }
- return breakable_addr;
+ auto arch_plugin = GetArchitecturePlugin();
+ return arch_plugin ?
+ arch_plugin->GetBreakableLoadAddress(addr, *this) : addr;
}
SourceManager &Target::GetSourceManager() {
@@ -2971,18 +2834,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
PlatformSP platform_sp(GetPlatform());
- // Finalize the file actions, and if none were given, default to opening up a
- // pseudo terminal
- const bool default_to_use_pty = platform_sp ? platform_sp->IsHost() : false;
- if (log)
- log->Printf("Target::%s have platform=%s, platform_sp->IsHost()=%s, "
- "default_to_use_pty=%s",
- __FUNCTION__, platform_sp ? "true" : "false",
- platform_sp ? (platform_sp->IsHost() ? "true" : "false")
- : "n/a",
- default_to_use_pty ? "true" : "false");
-
- launch_info.FinalizeFileActions(this, default_to_use_pty);
+ FinalizeFileActions(launch_info);
if (state == eStateConnected) {
if (launch_info.GetFlags().Test(eLaunchFlagLaunchInTTY)) {
@@ -3003,22 +2855,15 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
log->Printf("Target::%s asking the platform to debug the process",
__FUNCTION__);
- // Get a weak pointer to the previous process if we have one
- ProcessWP process_wp;
- if (m_process_sp)
- process_wp = m_process_sp;
+ // If there was a previous process, delete it before we make the new one.
+ // One subtle point, we delete the process before we release the reference
+ // to m_process_sp. That way even if we are the last owner, the process
+ // will get Finalized before it gets destroyed.
+ DeleteCurrentProcess();
+
m_process_sp =
GetPlatform()->DebugProcess(launch_info, debugger, this, error);
- // Cleanup the old process since someone might still have a strong
- // reference to this process and we would like to allow it to cleanup as
- // much as it can without the object being destroyed. We try to lock the
- // shared pointer and if that works, then someone else still has a strong
- // reference to the process.
-
- ProcessSP old_process_sp(process_wp.lock());
- if (old_process_sp)
- old_process_sp->Finalize();
} else {
if (log)
log->Printf("Target::%s the platform doesn't know how to debug a "
@@ -3030,8 +2875,7 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
} else {
// Use a Process plugin to construct the process.
const char *plugin_name = launch_info.GetProcessPluginName();
- CreateProcess(launch_info.GetListenerForProcess(debugger), plugin_name,
- nullptr);
+ CreateProcess(launch_info.GetListener(), plugin_name, nullptr);
}
// Since we didn't have a platform launch the process, launch it here.
@@ -3206,6 +3050,86 @@ Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
return error;
}
+void Target::FinalizeFileActions(ProcessLaunchInfo &info) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Finalize the file actions, and if none were given, default to opening up a
+ // pseudo terminal
+ PlatformSP platform_sp = GetPlatform();
+ const bool default_to_use_pty =
+ m_platform_sp ? m_platform_sp->IsHost() : false;
+ LLDB_LOG(
+ log,
+ "have platform={0}, platform_sp->IsHost()={1}, default_to_use_pty={2}",
+ bool(platform_sp),
+ platform_sp ? (platform_sp->IsHost() ? "true" : "false") : "n/a",
+ default_to_use_pty);
+
+ // If nothing for stdin or stdout or stderr was specified, then check the
+ // process for any default settings that were set with "settings set"
+ if (info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
+ info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
+ info.GetFileActionForFD(STDERR_FILENO) == nullptr) {
+ LLDB_LOG(log, "at least one of stdin/stdout/stderr was not set, evaluating "
+ "default handling");
+
+ if (info.GetFlags().Test(eLaunchFlagLaunchInTTY)) {
+ // Do nothing, if we are launching in a remote terminal no file actions
+ // should be done at all.
+ return;
+ }
+
+ if (info.GetFlags().Test(eLaunchFlagDisableSTDIO)) {
+ LLDB_LOG(log, "eLaunchFlagDisableSTDIO set, adding suppression action "
+ "for stdin, stdout and stderr");
+ info.AppendSuppressFileAction(STDIN_FILENO, true, false);
+ info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
+ info.AppendSuppressFileAction(STDERR_FILENO, false, true);
+ } else {
+ // Check for any values that might have gotten set with any of: (lldb)
+ // settings set target.input-path (lldb) settings set target.output-path
+ // (lldb) settings set target.error-path
+ FileSpec in_file_spec;
+ FileSpec out_file_spec;
+ FileSpec err_file_spec;
+ // Only override with the target settings if we don't already have an
+ // action for in, out or error
+ if (info.GetFileActionForFD(STDIN_FILENO) == nullptr)
+ in_file_spec = GetStandardInputPath();
+ if (info.GetFileActionForFD(STDOUT_FILENO) == nullptr)
+ out_file_spec = GetStandardOutputPath();
+ if (info.GetFileActionForFD(STDERR_FILENO) == nullptr)
+ err_file_spec = GetStandardErrorPath();
+
+ LLDB_LOG(log, "target stdin='{0}', target stdout='{1}', stderr='{1}'",
+ in_file_spec, out_file_spec, err_file_spec);
+
+ if (in_file_spec) {
+ info.AppendOpenFileAction(STDIN_FILENO, in_file_spec, true, false);
+ LLDB_LOG(log, "appended stdin open file action for {0}", in_file_spec);
+ }
+
+ if (out_file_spec) {
+ info.AppendOpenFileAction(STDOUT_FILENO, out_file_spec, false, true);
+ LLDB_LOG(log, "appended stdout open file action for {0}",
+ out_file_spec);
+ }
+
+ if (err_file_spec) {
+ info.AppendOpenFileAction(STDERR_FILENO, err_file_spec, false, true);
+ LLDB_LOG(log, "appended stderr open file action for {0}",
+ err_file_spec);
+ }
+
+ if (default_to_use_pty &&
+ (!in_file_spec || !out_file_spec || !err_file_spec)) {
+ llvm::Error Err = info.SetUpPtyRedirection();
+ LLDB_LOG_ERROR(log, std::move(Err), "SetUpPtyRedirection failed: {0}");
+ }
+ }
+ }
+}
+
//--------------------------------------------------------------
// Target::StopHook
//--------------------------------------------------------------
@@ -3275,16 +3199,20 @@ void Target::StopHook::GetDescription(Stream *s,
// class TargetProperties
//--------------------------------------------------------------
-OptionEnumValueElement lldb_private::g_dynamic_value_types[] = {
+// clang-format off
+static constexpr OptionEnumValueElement g_dynamic_value_types[] = {
{eNoDynamicValues, "no-dynamic-values",
"Don't calculate the dynamic type of values"},
{eDynamicCanRunTarget, "run-target", "Calculate the dynamic type of values "
"even if you have to run the target."},
{eDynamicDontRunTarget, "no-run-target",
- "Calculate the dynamic type of values, but don't run the target."},
- {0, nullptr, nullptr}};
+ "Calculate the dynamic type of values, but don't run the target."} };
+
+OptionEnumValues lldb_private::GetDynamicValueTypes() {
+ return OptionEnumValues(g_dynamic_value_types);
+}
-static OptionEnumValueElement g_inline_breakpoint_enums[] = {
+static constexpr OptionEnumValueElement g_inline_breakpoint_enums[] = {
{eInlineBreakpointsNever, "never", "Never look for inline breakpoint "
"locations (fastest). This setting "
"should only be used if you know that "
@@ -3295,8 +3223,7 @@ static OptionEnumValueElement g_inline_breakpoint_enums[] = {
"files (default)."},
{eInlineBreakpointsAlways, "always",
"Always look for inline breakpoint locations when setting file and line "
- "breakpoints (slower but most accurate)."},
- {0, nullptr, nullptr}};
+ "breakpoints (slower but most accurate)."} };
typedef enum x86DisassemblyFlavor {
eX86DisFlavorDefault,
@@ -3304,36 +3231,33 @@ typedef enum x86DisassemblyFlavor {
eX86DisFlavorATT
} x86DisassemblyFlavor;
-static OptionEnumValueElement g_x86_dis_flavor_value_types[] = {
+static constexpr OptionEnumValueElement g_x86_dis_flavor_value_types[] = {
{eX86DisFlavorDefault, "default", "Disassembler default (currently att)."},
{eX86DisFlavorIntel, "intel", "Intel disassembler flavor."},
- {eX86DisFlavorATT, "att", "AT&T disassembler flavor."},
- {0, nullptr, nullptr}};
+ {eX86DisFlavorATT, "att", "AT&T disassembler flavor."} };
-static OptionEnumValueElement g_hex_immediate_style_values[] = {
+static constexpr OptionEnumValueElement g_hex_immediate_style_values[] = {
{Disassembler::eHexStyleC, "c", "C-style (0xffff)."},
- {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."},
- {0, nullptr, nullptr}};
+ {Disassembler::eHexStyleAsm, "asm", "Asm-style (0ffffh)."} };
-static OptionEnumValueElement g_load_script_from_sym_file_values[] = {
+static constexpr OptionEnumValueElement g_load_script_from_sym_file_values[] = {
{eLoadScriptFromSymFileTrue, "true",
"Load debug scripts inside symbol files"},
{eLoadScriptFromSymFileFalse, "false",
"Do not load debug scripts inside symbol files."},
{eLoadScriptFromSymFileWarn, "warn",
- "Warn about debug scripts inside symbol files but do not load them."},
- {0, nullptr, nullptr}};
+ "Warn about debug scripts inside symbol files but do not load them."} };
-static OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = {
+static constexpr
+OptionEnumValueElement g_load_current_working_dir_lldbinit_values[] = {
{eLoadCWDlldbinitTrue, "true",
"Load .lldbinit files from current directory"},
{eLoadCWDlldbinitFalse, "false",
"Do not load .lldbinit files from current directory"},
{eLoadCWDlldbinitWarn, "warn",
- "Warn about loading .lldbinit files from current directory"},
- {0, nullptr, nullptr}};
+ "Warn about loading .lldbinit files from current directory"} };
-static OptionEnumValueElement g_memory_module_load_level_values[] = {
+static constexpr OptionEnumValueElement g_memory_module_load_level_values[] = {
{eMemoryModuleLoadLevelMinimal, "minimal",
"Load minimal information when loading modules from memory. Currently "
"this setting loads sections only."},
@@ -3342,28 +3266,27 @@ static OptionEnumValueElement g_memory_module_load_level_values[] = {
"this setting loads sections and function bounds."},
{eMemoryModuleLoadLevelComplete, "complete",
"Load complete information when loading modules from memory. Currently "
- "this setting loads sections and all symbols."},
- {0, nullptr, nullptr}};
+ "this setting loads sections and all symbols."} };
-static PropertyDefinition g_properties[] = {
- {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, nullptr,
+static constexpr PropertyDefinition g_properties[] = {
+ {"default-arch", OptionValue::eTypeArch, true, 0, nullptr, {},
"Default architecture to choose, when there's a choice."},
{"move-to-nearest-code", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Move breakpoints to nearest code."},
+ {}, "Move breakpoints to nearest code."},
{"language", OptionValue::eTypeLanguage, false, eLanguageTypeUnknown,
- nullptr, nullptr,
+ nullptr, {},
"The language to use when interpreting expressions entered in commands."},
- {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"expr-prefix", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"Path to a file containing expressions to be prepended to all "
"expressions."},
{"prefer-dynamic-value", OptionValue::eTypeEnum, false,
- eDynamicDontRunTarget, nullptr, g_dynamic_value_types,
+ eDynamicDontRunTarget, nullptr, OptionEnumValues(g_dynamic_value_types),
"Should printed values be shown as their dynamic value."},
{"enable-synthetic-value", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Should synthetic values be used by default whenever available."},
- {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ {}, "Should synthetic values be used by default whenever available."},
+ {"skip-prologue", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Skip function prologues when setting breakpoints by name."},
- {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, nullptr,
+ {"source-map", OptionValue::eTypePathMap, false, 0, nullptr, {},
"Source path remappings are used to track the change of location between "
"a source file when built, and "
"where it exists on the current system. It consists of an array of "
@@ -3375,66 +3298,68 @@ static PropertyDefinition g_properties[] = {
"Each element of the array is checked in order and the first one that "
"results in a match wins."},
{"exec-search-paths", OptionValue::eTypeFileSpecList, false, 0, nullptr,
- nullptr, "Executable search paths to use when locating executable files "
- "whose paths don't match the local file system."},
+ {}, "Executable search paths to use when locating executable files "
+ "whose paths don't match the local file system."},
{"debug-file-search-paths", OptionValue::eTypeFileSpecList, false, 0,
- nullptr, nullptr,
- "List of directories to be searched when locating debug symbol files."},
+ nullptr, {},
+ "List of directories to be searched when locating debug symbol files. "
+ "See also symbols.enable-external-lookup."},
{"clang-module-search-paths", OptionValue::eTypeFileSpecList, false, 0,
- nullptr, nullptr,
+ nullptr, {},
"List of directories to be searched when locating modules for Clang."},
{"auto-import-clang-modules", OptionValue::eTypeBoolean, false, true,
- nullptr, nullptr,
+ nullptr, {},
"Automatically load Clang modules referred to by the program."},
{"auto-apply-fixits", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Automatically apply fix-it hints to expressions."},
+ {}, "Automatically apply fix-it hints to expressions."},
{"notify-about-fixits", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Print the fixed expression text."},
+ {}, "Print the fixed expression text."},
{"save-jit-objects", OptionValue::eTypeBoolean, false, false, nullptr,
- nullptr, "Save intermediate object files generated by the LLVM JIT"},
+ {}, "Save intermediate object files generated by the LLVM JIT"},
{"max-children-count", OptionValue::eTypeSInt64, false, 256, nullptr,
- nullptr, "Maximum number of children to expand in any level of depth."},
+ {}, "Maximum number of children to expand in any level of depth."},
{"max-string-summary-length", OptionValue::eTypeSInt64, false, 1024,
- nullptr, nullptr,
+ nullptr, {},
"Maximum number of characters to show when using %s in summary strings."},
{"max-memory-read-size", OptionValue::eTypeSInt64, false, 1024, nullptr,
- nullptr, "Maximum number of bytes that 'memory read' will fetch before "
- "--force must be specified."},
+ {}, "Maximum number of bytes that 'memory read' will fetch before "
+ "--force must be specified."},
{"breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean, false,
- true, nullptr, nullptr, "Consult the platform module avoid list when "
- "setting non-module specific breakpoints."},
- {"arg0", OptionValue::eTypeString, false, 0, nullptr, nullptr,
+ true, nullptr, {}, "Consult the platform module avoid list when "
+ "setting non-module specific breakpoints."},
+ {"arg0", OptionValue::eTypeString, false, 0, nullptr, {},
"The first argument passed to the program in the argument array which can "
"be different from the executable itself."},
- {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, nullptr,
+ {"run-args", OptionValue::eTypeArgs, false, 0, nullptr, {},
"A list containing all the arguments to be passed to the executable when "
"it is run. Note that this does NOT include the argv[0] which is in "
"target.arg0."},
{"env-vars", OptionValue::eTypeDictionary, false, OptionValue::eTypeString,
- nullptr, nullptr, "A list of all the environment variables to be passed "
- "to the executable's environment, and their values."},
- {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ nullptr, {}, "A list of all the environment variables to be passed "
+ "to the executable's environment, and their values."},
+ {"inherit-env", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Inherit the environment from the process that is running LLDB."},
- {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"input-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"The file/path to be used by the executable program for reading its "
"standard input."},
- {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"output-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"The file/path to be used by the executable program for writing its "
"standard output."},
- {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, nullptr,
+ {"error-path", OptionValue::eTypeFileSpec, false, 0, nullptr, {},
"The file/path to be used by the executable program for writing its "
"standard error."},
{"detach-on-error", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "debugserver will detach (rather than killing) a process if it "
+ {}, "debugserver will detach (rather than killing) a process if it "
"loses connection with lldb."},
- {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ {"preload-symbols", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Enable loading of symbol tables before they are needed."},
- {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, nullptr,
+ {"disable-aslr", OptionValue::eTypeBoolean, false, true, nullptr, {},
"Disable Address Space Layout Randomization (ASLR)"},
- {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
+ {"disable-stdio", OptionValue::eTypeBoolean, false, false, nullptr, {},
"Disable stdin/stdout for process (e.g. for a GUI application)"},
{"inline-breakpoint-strategy", OptionValue::eTypeEnum, false,
- eInlineBreakpointsAlways, nullptr, g_inline_breakpoint_enums,
+ eInlineBreakpointsAlways, nullptr,
+ OptionEnumValues(g_inline_breakpoint_enums),
"The strategy to use when settings breakpoints by file and line. "
"Breakpoint locations can end up being inlined by the compiler, so that a "
"compile unit 'a.c' might contain an inlined function from another source "
@@ -3454,25 +3379,29 @@ static PropertyDefinition g_properties[] = {
// FIXME: This is the wrong way to do per-architecture settings, but we
// don't have a general per architecture settings system in place yet.
{"x86-disassembly-flavor", OptionValue::eTypeEnum, false,
- eX86DisFlavorDefault, nullptr, g_x86_dis_flavor_value_types,
+ eX86DisFlavorDefault, nullptr,
+ OptionEnumValues(g_x86_dis_flavor_value_types),
"The default disassembly flavor to use for x86 or x86-64 targets."},
{"use-hex-immediates", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Show immediates in disassembly as hexadecimal."},
+ {}, "Show immediates in disassembly as hexadecimal."},
{"hex-immediate-style", OptionValue::eTypeEnum, false,
- Disassembler::eHexStyleC, nullptr, g_hex_immediate_style_values,
+ Disassembler::eHexStyleC, nullptr,
+ OptionEnumValues(g_hex_immediate_style_values),
"Which style to use for printing hexadecimal disassembly values."},
{"use-fast-stepping", OptionValue::eTypeBoolean, false, true, nullptr,
- nullptr, "Use a fast stepping algorithm based on running from branch to "
- "branch rather than instruction single-stepping."},
+ {}, "Use a fast stepping algorithm based on running from branch to "
+ "branch rather than instruction single-stepping."},
{"load-script-from-symbol-file", OptionValue::eTypeEnum, false,
- eLoadScriptFromSymFileWarn, nullptr, g_load_script_from_sym_file_values,
+ eLoadScriptFromSymFileWarn, nullptr,
+ OptionEnumValues(g_load_script_from_sym_file_values),
"Allow LLDB to load scripting resources embedded in symbol files when "
"available."},
{"load-cwd-lldbinit", OptionValue::eTypeEnum, false, eLoadCWDlldbinitWarn,
- nullptr, g_load_current_working_dir_lldbinit_values,
+ nullptr, OptionEnumValues(g_load_current_working_dir_lldbinit_values),
"Allow LLDB to .lldbinit files from the current directory automatically."},
{"memory-module-load-level", OptionValue::eTypeEnum, false,
- eMemoryModuleLoadLevelComplete, nullptr, g_memory_module_load_level_values,
+ eMemoryModuleLoadLevelComplete, nullptr,
+ OptionEnumValues(g_memory_module_load_level_values),
"Loading modules from memory can be slow as reading the symbol tables and "
"other data can take a long time depending on your connection to the "
"debug target. "
@@ -3488,20 +3417,23 @@ static PropertyDefinition g_properties[] = {
"symbols, but should rarely be used as stack frames in these memory "
"regions will be inaccurate and not provide any context (fastest). "},
{"display-expression-in-crashlogs", OptionValue::eTypeBoolean, false, false,
- nullptr, nullptr, "Expressions that crash will show up in crash logs if "
- "the host system supports executable specific crash log "
- "strings and this setting is set to true."},
+ nullptr, {}, "Expressions that crash will show up in crash logs if "
+ "the host system supports executable specific crash log "
+ "strings and this setting is set to true."},
{"trap-handler-names", OptionValue::eTypeArray, true,
- OptionValue::eTypeString, nullptr, nullptr,
+ OptionValue::eTypeString, nullptr, {},
"A list of trap handler function names, e.g. a common Unix user process "
"one is _sigtramp."},
{"display-runtime-support-values", OptionValue::eTypeBoolean, false, false,
- nullptr, nullptr, "If true, LLDB will show variables that are meant to "
- "support the operation of a language's runtime "
- "support."},
- {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, nullptr,
+ nullptr, {}, "If true, LLDB will show variables that are meant to "
+ "support the operation of a language's runtime support."},
+ {"display-recognized-arguments", OptionValue::eTypeBoolean, false, false,
+ nullptr, {}, "Show recognized arguments in variable listings by default."},
+ {"non-stop-mode", OptionValue::eTypeBoolean, false, 0, nullptr, {},
"Disable lock-step debugging, instead control threads independently."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {"require-hardware-breakpoint", OptionValue::eTypeBoolean, false, 0,
+ nullptr, {}, "Require all breakpoints to be hardware breakpoints."}};
+// clang-format on
enum {
ePropertyDefaultArch,
@@ -3545,8 +3477,10 @@ enum {
ePropertyDisplayExpressionsInCrashlogs,
ePropertyTrapHandlerNames,
ePropertyDisplayRuntimeSupportValues,
+ ePropertyDisplayRecognizedArguments,
ePropertyNonStopModeEnabled,
- ePropertyExperimental
+ ePropertyRequireHardwareBreakpoints,
+ ePropertyExperimental,
};
class TargetOptionValueProperties : public OptionValueProperties {
@@ -3623,16 +3557,15 @@ protected:
//----------------------------------------------------------------------
// TargetProperties
//----------------------------------------------------------------------
-static PropertyDefinition g_experimental_properties[]{
+static constexpr PropertyDefinition g_experimental_properties[]{
{"inject-local-vars", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
+ {},
"If true, inject local variables explicitly into the expression text. "
"This will fix symbol resolution when there are name collisions between "
"ivars and local variables. "
"But it can make expressions run much more slowly."},
{"use-modern-type-lookup", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, use Clang's modern type lookup infrastructure."},
- {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}};
+ {}, "If true, use Clang's modern type lookup infrastructure."}};
enum { ePropertyInjectLocalVars = 0, ePropertyUseModernTypeLookup };
@@ -4104,6 +4037,16 @@ void TargetProperties::SetDisplayRuntimeSupportValues(bool b) {
m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
}
+bool TargetProperties::GetDisplayRecognizedArguments() const {
+ const uint32_t idx = ePropertyDisplayRecognizedArguments;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
+}
+
+void TargetProperties::SetDisplayRecognizedArguments(bool b) {
+ const uint32_t idx = ePropertyDisplayRecognizedArguments;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
bool TargetProperties::GetNonStopModeEnabled() const {
const uint32_t idx = ePropertyNonStopModeEnabled;
return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, false);
@@ -4145,6 +4088,17 @@ void TargetProperties::SetProcessLaunchInfo(
SetDisableSTDIO(launch_info.GetFlags().Test(lldb::eLaunchFlagDisableSTDIO));
}
+bool TargetProperties::GetRequireHardwareBreakpoints() const {
+ const uint32_t idx = ePropertyRequireHardwareBreakpoints;
+ return m_collection_sp->GetPropertyAtIndexAsBoolean(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
+void TargetProperties::SetRequireHardwareBreakpoints(bool b) {
+ const uint32_t idx = ePropertyRequireHardwareBreakpoints;
+ m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b);
+}
+
void TargetProperties::Arg0ValueChangedCallback(void *target_property_ptr,
OptionValue *) {
TargetProperties *this_ =
diff --git a/source/Target/TargetList.cpp b/source/Target/TargetList.cpp
index b9c852b414e2..5b262509cae7 100644
--- a/source/Target/TargetList.cpp
+++ b/source/Target/TargetList.cpp
@@ -7,14 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "lldb/Target/TargetList.h"
-#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/Event.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
-#include "lldb/Core/State.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Interpreter/CommandInterpreter.h"
@@ -22,10 +18,12 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/TildeExpressionResolver.h"
#include "lldb/Utility/Timer.h"
-// Other libraries and framework includes
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/FileSystem.h"
@@ -58,27 +56,27 @@ TargetList::~TargetList() {
Status TargetList::CreateTarget(Debugger &debugger,
llvm::StringRef user_exe_path,
llvm::StringRef triple_str,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options,
TargetSP &target_sp) {
return CreateTargetInternal(debugger, user_exe_path, triple_str,
- get_dependent_files, platform_options, target_sp,
+ load_dependent_files, platform_options, target_sp,
false);
}
Status TargetList::CreateTarget(Debugger &debugger,
llvm::StringRef user_exe_path,
const ArchSpec &specified_arch,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
PlatformSP &platform_sp, TargetSP &target_sp) {
return CreateTargetInternal(debugger, user_exe_path, specified_arch,
- get_dependent_files, platform_sp, target_sp,
+ load_dependent_files, platform_sp, target_sp,
false);
}
Status TargetList::CreateTargetInternal(
Debugger &debugger, llvm::StringRef user_exe_path,
- llvm::StringRef triple_str, bool get_dependent_files,
+ llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
const OptionGroupPlatform *platform_options, TargetSP &target_sp,
bool is_dummy_target) {
Status error;
@@ -120,8 +118,8 @@ Status TargetList::CreateTargetInternal(
if (!user_exe_path.empty()) {
ModuleSpecList module_specs;
ModuleSpec module_spec;
- module_spec.GetFileSpec().SetFile(user_exe_path, true,
- FileSpec::Style::native);
+ module_spec.GetFileSpec().SetFile(user_exe_path, FileSpec::Style::native);
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
// Resolve the executable in case we are given a path to a application
// bundle like a .app bundle on MacOSX
@@ -236,7 +234,7 @@ Status TargetList::CreateTargetInternal(
// All platforms for all modules in the executable match, so we can
// select this platform
platform_sp = platforms.front();
- } else if (more_than_one_platforms == false) {
+ } else if (!more_than_one_platforms) {
// No platforms claim to support this file
error.SetErrorString("No matching platforms found for this file, "
"specify one with the --platform option");
@@ -292,7 +290,7 @@ Status TargetList::CreateTargetInternal(
platform_arch = arch;
error = TargetList::CreateTargetInternal(
- debugger, user_exe_path, platform_arch, get_dependent_files, platform_sp,
+ debugger, user_exe_path, platform_arch, load_dependent_files, platform_sp,
target_sp, is_dummy_target);
return error;
}
@@ -315,14 +313,14 @@ Status TargetList::CreateDummyTarget(Debugger &debugger,
lldb::TargetSP &target_sp) {
PlatformSP host_platform_sp(Platform::GetHostPlatform());
return CreateTargetInternal(
- debugger, (const char *)nullptr, specified_arch_name, false,
+ debugger, (const char *)nullptr, specified_arch_name, eLoadDependentsNo,
(const OptionGroupPlatform *)nullptr, target_sp, true);
}
Status TargetList::CreateTargetInternal(Debugger &debugger,
llvm::StringRef user_exe_path,
const ArchSpec &specified_arch,
- bool get_dependent_files,
+ LoadDependentFiles load_dependent_files,
lldb::PlatformSP &platform_sp,
lldb::TargetSP &target_sp,
bool is_dummy_target) {
@@ -346,8 +344,8 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
if (!arch.IsValid())
arch = specified_arch;
- FileSpec file(user_exe_path, false);
- if (!file.Exists() && user_exe_path.startswith("~")) {
+ FileSpec file(user_exe_path);
+ if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) {
// we want to expand the tilde but we don't want to resolve any symbolic
// links so we can't use the FileSpec constructor's resolve flag
llvm::SmallString<64> unglobbed_path;
@@ -355,24 +353,24 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
if (unglobbed_path.empty())
- file = FileSpec(user_exe_path, false);
+ file = FileSpec(user_exe_path);
else
- file = FileSpec(unglobbed_path.c_str(), false);
+ file = FileSpec(unglobbed_path.c_str());
}
bool user_exe_path_is_bundle = false;
char resolved_bundle_exe_path[PATH_MAX];
resolved_bundle_exe_path[0] = '\0';
if (file) {
- if (llvm::sys::fs::is_directory(file.GetPath()))
+ if (FileSystem::Instance().IsDirectory(file))
user_exe_path_is_bundle = true;
if (file.IsRelative() && !user_exe_path.empty()) {
llvm::SmallString<64> cwd;
if (! llvm::sys::fs::current_path(cwd)) {
- FileSpec cwd_file(cwd.c_str(), false);
+ FileSpec cwd_file(cwd.c_str());
cwd_file.AppendPathComponent(file);
- if (cwd_file.Exists())
+ if (FileSystem::Instance().Exists(cwd_file))
file = cwd_file;
}
}
@@ -401,7 +399,7 @@ Status TargetList::CreateTargetInternal(Debugger &debugger,
return error;
}
target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
- target_sp->SetExecutableModule(exe_module_sp, get_dependent_files);
+ target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
if (user_exe_path_is_bundle)
exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
sizeof(resolved_bundle_exe_path));
diff --git a/source/Target/Thread.cpp b/source/Target/Thread.cpp
index 5ac1de7ae01b..569d7a0a0f9e 100644
--- a/source/Target/Thread.cpp
+++ b/source/Target/Thread.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Thread.h"
#include "Plugins/Process/Utility/UnwindLLDB.h"
#include "Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h"
@@ -18,7 +14,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FormatEntity.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/OptionValueFileSpecList.h"
@@ -28,8 +23,10 @@
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrameRecognizer.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
@@ -49,6 +46,7 @@
#include "lldb/Target/Unwind.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegularExpression.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/lldb-enumerations.h"
@@ -64,30 +62,31 @@ const ThreadPropertiesSP &Thread::GetGlobalProperties() {
return *g_settings_sp_ptr;
}
-static PropertyDefinition g_properties[] = {
+static constexpr PropertyDefinition g_properties[] = {
{"step-in-avoid-nodebug", OptionValue::eTypeBoolean, true, true, nullptr,
- nullptr,
+ {},
"If true, step-in will not stop in functions with no debug information."},
{"step-out-avoid-nodebug", OptionValue::eTypeBoolean, true, false, nullptr,
- nullptr, "If true, when step-in/step-out/step-over leave the current "
- "frame, they will continue to step out till they come to a "
- "function with "
- "debug information. Passing a frame argument to step-out will "
- "override this option."},
- {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", nullptr,
+ {}, "If true, when step-in/step-out/step-over leave the current frame, "
+ "they will continue to step out till they come to a function with "
+ "debug information. Passing a frame argument to step-out will "
+ "override this option."},
+ {"step-avoid-regexp", OptionValue::eTypeRegex, true, 0, "^std::", {},
"A regular expression defining functions step-in won't stop in."},
{"step-avoid-libraries", OptionValue::eTypeFileSpecList, true, 0, nullptr,
- nullptr, "A list of libraries that source stepping won't stop in."},
- {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
+ {}, "A list of libraries that source stepping won't stop in."},
+ {"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, {},
"If true, this thread will single-step and log execution."},
- {nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
+ {"max-backtrace-depth", OptionValue::eTypeUInt64, false, 300000, nullptr,
+ {}, "Maximum number of frames to backtrace."}};
enum {
ePropertyStepInAvoidsNoDebug,
ePropertyStepOutAvoidsNoDebug,
ePropertyStepAvoidRegex,
ePropertyStepAvoidLibraries,
- ePropertyEnableThreadTrace
+ ePropertyEnableThreadTrace,
+ ePropertyMaxBacktraceDepth
};
class ThreadOptionValueProperties : public OptionValueProperties {
@@ -165,6 +164,12 @@ bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
nullptr, idx, g_properties[idx].default_uint_value != 0);
}
+uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
+ const uint32_t idx = ePropertyMaxBacktraceDepth;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ nullptr, idx, g_properties[idx].default_uint_value != 0);
+}
+
//------------------------------------------------------------------
// Thread Event Data
//------------------------------------------------------------------
@@ -259,6 +264,7 @@ Thread::Thread(Process &process, lldb::tid_t tid, bool use_invalid_index_id)
static_cast<void *>(this), GetID());
CheckInWithManager();
+
QueueFundamentalPlan(true);
}
@@ -392,13 +398,14 @@ lldb::StopInfoSP Thread::GetStopInfo() {
m_stop_info_sp ->IsValid() &&
m_stop_info_stop_id == stop_id;
bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded();
+ bool plan_failed = completed_plan_sp && !completed_plan_sp->PlanSucceeded();
bool plan_overrides_trace =
have_valid_stop_info && have_valid_completed_plan
&& (m_stop_info_sp->GetStopReason() == eStopReasonTrace);
- if (have_valid_stop_info && !plan_overrides_trace) {
+ if (have_valid_stop_info && !plan_overrides_trace && !plan_failed) {
return m_stop_info_sp;
- } else if (have_valid_completed_plan) {
+ } else if (completed_plan_sp) {
return StopInfo::CreateStopReasonWithPlan(
completed_plan_sp, GetReturnValueObject(), GetExpressionVariable());
} else {
@@ -1031,9 +1038,11 @@ void Thread::PushPlan(ThreadPlanSP &thread_plan_sp) {
if (thread_plan_sp) {
// If the thread plan doesn't already have a tracer, give it its parent's
// tracer:
- if (!thread_plan_sp->GetThreadPlanTracer())
+ if (!thread_plan_sp->GetThreadPlanTracer()) {
+ assert(!m_plan_stack.empty());
thread_plan_sp->SetThreadPlanTracer(
m_plan_stack.back()->GetThreadPlanTracer());
+ }
m_plan_stack.push_back(thread_plan_sp);
thread_plan_sp->DidPush();
@@ -1170,12 +1179,34 @@ ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) {
return nullptr;
}
-void Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
- bool abort_other_plans) {
+Status Thread::QueueThreadPlan(ThreadPlanSP &thread_plan_sp,
+ bool abort_other_plans) {
+ Status status;
+ StreamString s;
+ if (!thread_plan_sp->ValidatePlan(&s)) {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ thread_plan_sp.reset();
+ status.SetErrorString(s.GetString());
+ return status;
+ }
+
if (abort_other_plans)
DiscardThreadPlans(true);
PushPlan(thread_plan_sp);
+
+ // This seems a little funny, but I don't want to have to split up the
+ // constructor and the DidPush in the scripted plan, that seems annoying.
+ // That means the constructor has to be in DidPush. So I have to validate the
+ // plan AFTER pushing it, and then take it off again...
+ if (!thread_plan_sp->ValidatePlan(&s)) {
+ DiscardThreadPlansUpToPlan(thread_plan_sp);
+ thread_plan_sp.reset();
+ status.SetErrorString(s.GetString());
+ return status;
+ }
+
+ return status;
}
void Thread::EnableTracer(bool value, bool single_stepping) {
@@ -1340,23 +1371,24 @@ ThreadPlanSP Thread::QueueFundamentalPlan(bool abort_other_plans) {
}
ThreadPlanSP Thread::QueueThreadPlanForStepSingleInstruction(
- bool step_over, bool abort_other_plans, bool stop_other_threads) {
+ bool step_over, bool abort_other_plans, bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepInstruction(
*this, step_over, stop_other_threads, eVoteNoOpinion, eVoteNoOpinion));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
- LazyBool step_out_avoids_code_withoug_debug_info) {
+ Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
ThreadPlanSP thread_plan_sp;
thread_plan_sp.reset(new ThreadPlanStepOverRange(
*this, range, addr_context, stop_other_threads,
step_out_avoids_code_withoug_debug_info));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1365,17 +1397,17 @@ ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
ThreadPlanSP Thread::QueueThreadPlanForStepOverRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, lldb::RunMode stop_other_threads,
- LazyBool step_out_avoids_code_withoug_debug_info) {
+ Status &status, LazyBool step_out_avoids_code_withoug_debug_info) {
return QueueThreadPlanForStepOverRange(
abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
- addr_context, stop_other_threads,
+ addr_context, stop_other_threads, status,
step_out_avoids_code_withoug_debug_info);
}
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const AddressRange &range,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_other_threads,
+ lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info) {
ThreadPlanSP thread_plan_sp(
@@ -1388,7 +1420,7 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
if (step_in_target)
plan->SetStepInTarget(step_in_target);
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
@@ -1396,12 +1428,12 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
bool abort_other_plans, const LineEntry &line_entry,
const SymbolContext &addr_context, const char *step_in_target,
- lldb::RunMode stop_other_threads,
+ lldb::RunMode stop_other_threads, Status &status,
LazyBool step_in_avoids_code_without_debug_info,
LazyBool step_out_avoids_code_without_debug_info) {
return QueueThreadPlanForStepInRange(
abort_other_plans, line_entry.GetSameLineContiguousAddressRange(),
- addr_context, step_in_target, stop_other_threads,
+ addr_context, step_in_target, stop_other_threads, status,
step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
}
@@ -1409,23 +1441,19 @@ ThreadPlanSP Thread::QueueThreadPlanForStepInRange(
ThreadPlanSP Thread::QueueThreadPlanForStepOut(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- LazyBool step_out_avoids_code_without_debug_info) {
+ Status &status, LazyBool step_out_avoids_code_without_debug_info) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
*this, addr_context, first_insn, stop_other_threads, stop_vote, run_vote,
frame_idx, step_out_avoids_code_without_debug_info));
- if (thread_plan_sp->ValidatePlan(nullptr)) {
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
- } else {
- return ThreadPlanSP();
- }
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
bool abort_other_plans, SymbolContext *addr_context, bool first_insn,
bool stop_other_threads, Vote stop_vote, Vote run_vote, uint32_t frame_idx,
- bool continue_to_next_branch) {
+ Status &status, bool continue_to_next_branch) {
const bool calculate_return_value =
false; // No need to calculate the return value here.
ThreadPlanSP thread_plan_sp(new ThreadPlanStepOut(
@@ -1436,59 +1464,51 @@ ThreadPlanSP Thread::QueueThreadPlanForStepOutNoShouldStop(
static_cast<ThreadPlanStepOut *>(thread_plan_sp.get());
new_plan->ClearShouldStopHereCallbacks();
- if (thread_plan_sp->ValidatePlan(nullptr)) {
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- return thread_plan_sp;
- } else {
- return ThreadPlanSP();
- }
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id,
bool abort_other_plans,
- bool stop_other_threads) {
+ bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(
new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads));
if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr))
return ThreadPlanSP();
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
ThreadPlanSP Thread::QueueThreadPlanForRunToAddress(bool abort_other_plans,
Address &target_addr,
- bool stop_other_threads) {
+ bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(
new ThreadPlanRunToAddress(*this, target_addr, stop_other_threads));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
-ThreadPlanSP Thread::QueueThreadPlanForStepUntil(bool abort_other_plans,
- lldb::addr_t *address_list,
- size_t num_addresses,
- bool stop_other_threads,
- uint32_t frame_idx) {
+ThreadPlanSP Thread::QueueThreadPlanForStepUntil(
+ bool abort_other_plans, lldb::addr_t *address_list, size_t num_addresses,
+ bool stop_other_threads, uint32_t frame_idx, Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanStepUntil(
*this, address_list, num_addresses, stop_other_threads, frame_idx));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
return thread_plan_sp;
}
lldb::ThreadPlanSP Thread::QueueThreadPlanForStepScripted(
- bool abort_other_plans, const char *class_name, bool stop_other_threads) {
+ bool abort_other_plans, const char *class_name, bool stop_other_threads,
+ Status &status) {
ThreadPlanSP thread_plan_sp(new ThreadPlanPython(*this, class_name));
- QueueThreadPlan(thread_plan_sp, abort_other_plans);
- // This seems a little funny, but I don't want to have to split up the
- // constructor and the DidPush in the scripted plan, that seems annoying.
- // That means the constructor has to be in DidPush. So I have to validate the
- // plan AFTER pushing it, and then take it off again...
- if (!thread_plan_sp->ValidatePlan(nullptr)) {
- DiscardThreadPlansUpToPlan(thread_plan_sp);
- return ThreadPlanSP();
- } else
- return thread_plan_sp;
+
+ status = QueueThreadPlan(thread_plan_sp, abort_other_plans);
+ return thread_plan_sp;
}
uint32_t Thread::GetIndexID() const { return m_index_id; }
@@ -2107,12 +2127,12 @@ Status Thread::StepIn(bool source_step,
if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepInRange(
- abort_other_plans, sc.line_entry, sc, nullptr, run_mode,
+ abort_other_plans, sc.line_entry, sc, nullptr, run_mode, error,
step_in_avoids_code_without_debug_info,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- false, abort_other_plans, run_mode);
+ false, abort_other_plans, run_mode, error);
}
new_plan_sp->SetIsMasterPlan(true);
@@ -2141,11 +2161,11 @@ Status Thread::StepOver(bool source_step,
if (source_step && frame_sp && frame_sp->HasDebugInformation()) {
SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
new_plan_sp = QueueThreadPlanForStepOverRange(
- abort_other_plans, sc.line_entry, sc, run_mode,
+ abort_other_plans, sc.line_entry, sc, run_mode, error,
step_out_avoids_code_without_debug_info);
} else {
new_plan_sp = QueueThreadPlanForStepSingleInstruction(
- true, abort_other_plans, run_mode);
+ true, abort_other_plans, run_mode, error);
}
new_plan_sp->SetIsMasterPlan(true);
@@ -2170,7 +2190,7 @@ Status Thread::StepOut() {
ThreadPlanSP new_plan_sp(QueueThreadPlanForStepOut(
abort_other_plans, nullptr, first_instruction, stop_other_threads,
- eVoteYes, eVoteNoOpinion, 0));
+ eVoteYes, eVoteNoOpinion, 0, error));
new_plan_sp->SetIsMasterPlan(true);
new_plan_sp->SetOkayToDiscard(false);
@@ -2183,3 +2203,32 @@ Status Thread::StepOut() {
}
return error;
}
+
+ValueObjectSP Thread::GetCurrentException() {
+ if (auto frame_sp = GetStackFrameAtIndex(0))
+ if (auto recognized_frame = frame_sp->GetRecognizedFrame())
+ if (auto e = recognized_frame->GetExceptionObject())
+ return e;
+
+ // FIXME: For now, only ObjC exceptions are supported. This should really
+ // iterate over all language runtimes and ask them all to give us the current
+ // exception.
+ if (auto runtime = GetProcess()->GetObjCLanguageRuntime())
+ if (auto e = runtime->GetExceptionObjectForThread(shared_from_this()))
+ return e;
+
+ return ValueObjectSP();
+}
+
+ThreadSP Thread::GetCurrentExceptionBacktrace() {
+ ValueObjectSP exception = GetCurrentException();
+ if (!exception) return ThreadSP();
+
+ // FIXME: For now, only ObjC exceptions are supported. This should really
+ // iterate over all language runtimes and ask them all to give us the current
+ // exception.
+ auto runtime = GetProcess()->GetObjCLanguageRuntime();
+ if (!runtime) return ThreadSP();
+
+ return runtime->GetBacktraceThreadFromException(exception);
+}
diff --git a/source/Target/ThreadList.cpp b/source/Target/ThreadList.cpp
index ee57a401f742..20c285963882 100644
--- a/source/Target/ThreadList.cpp
+++ b/source/Target/ThreadList.cpp
@@ -7,15 +7,10 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <stdlib.h>
-// C++ Includes
#include <algorithm>
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h"
@@ -23,6 +18,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/ThreadPlan.cpp b/source/Target/ThreadPlan.cpp
index 31ee1e922494..1f2c69c6e8a6 100644
--- a/source/Target/ThreadPlan.cpp
+++ b/source/Target/ThreadPlan.cpp
@@ -7,18 +7,14 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -29,6 +25,7 @@ using namespace lldb_private;
ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread,
Vote stop_vote, Vote run_vote)
: m_thread(thread), m_stop_vote(stop_vote), m_run_vote(run_vote),
+ m_takes_iteration_count(false), m_could_not_resolve_hw_bp(false),
m_kind(kind), m_name(name), m_plan_complete_mutex(),
m_cached_plan_explains_stop(eLazyBoolCalculate), m_plan_complete(false),
m_plan_private(false), m_okay_to_discard(true), m_is_master_plan(false),
diff --git a/source/Target/ThreadPlanBase.cpp b/source/Target/ThreadPlanBase.cpp
index 65b114584177..058d1468e241 100644
--- a/source/Target/ThreadPlanBase.cpp
+++ b/source/Target/ThreadPlanBase.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/ThreadPlanBase.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
//
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
@@ -61,10 +57,7 @@ bool ThreadPlanBase::ValidatePlan(Stream *error) { return true; }
bool ThreadPlanBase::DoPlanExplainsStop(Event *event_ptr) {
// The base plan should defer to its tracer, since by default it always
// handles the stop.
- if (TracerExplainsStop())
- return false;
- else
- return true;
+ return !TracerExplainsStop();
}
Vote ThreadPlanBase::ShouldReportStop(Event *event_ptr) {
diff --git a/source/Target/ThreadPlanCallFunction.cpp b/source/Target/ThreadPlanCallFunction.cpp
index 18beda42fb64..1131ec939b89 100644
--- a/source/Target/ThreadPlanCallFunction.cpp
+++ b/source/Target/ThreadPlanCallFunction.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanCallFunction.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
diff --git a/source/Target/ThreadPlanCallFunctionUsingABI.cpp b/source/Target/ThreadPlanCallFunctionUsingABI.cpp
index b90fd9edd766..08604d2c411a 100644
--- a/source/Target/ThreadPlanCallFunctionUsingABI.cpp
+++ b/source/Target/ThreadPlanCallFunctionUsingABI.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanCallFunctionUsingABI.h"
#include "lldb/Core/Address.h"
#include "lldb/Target/Process.h"
diff --git a/source/Target/ThreadPlanCallOnFunctionExit.cpp b/source/Target/ThreadPlanCallOnFunctionExit.cpp
index e8ea73f3c6a0..2ea083dac45e 100644
--- a/source/Target/ThreadPlanCallOnFunctionExit.cpp
+++ b/source/Target/ThreadPlanCallOnFunctionExit.cpp
@@ -27,17 +27,18 @@ void ThreadPlanCallOnFunctionExit::DidPush() {
// completes.
// Set stop vote to eVoteNo.
+ Status status;
m_step_out_threadplan_sp = GetThread().QueueThreadPlanForStepOut(
false, // abort other plans
nullptr, // addr_context
true, // first instruction
true, // stop other threads
eVoteNo, // do not say "we're stopping"
- eVoteNoOpinion, // don't care about
- // run state broadcasting
+ eVoteNoOpinion, // don't care about run state broadcasting
0, // frame_idx
+ status, // status
eLazyBoolCalculate // avoid code w/o debinfo
- );
+ );
}
// -------------------------------------------------------------------------
diff --git a/source/Target/ThreadPlanCallUserExpression.cpp b/source/Target/ThreadPlanCallUserExpression.cpp
index 7bf0dd39993e..1fbd346feeea 100644
--- a/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/source/Target/ThreadPlanCallUserExpression.cpp
@@ -9,11 +9,7 @@
#include "lldb/Target/ThreadPlanCallUserExpression.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/Address.h"
diff --git a/source/Target/ThreadPlanPython.cpp b/source/Target/ThreadPlanPython.cpp
index 7796b8a0ab20..84b93bdc6583 100644
--- a/source/Target/ThreadPlanPython.cpp
+++ b/source/Target/ThreadPlanPython.cpp
@@ -9,12 +9,7 @@
#include "lldb/Target/ThreadPlan.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Debugger.h"
-#include "lldb/Core/State.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
#include "lldb/Target/Process.h"
@@ -24,6 +19,7 @@
#include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanPython.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
@@ -35,7 +31,7 @@ using namespace lldb_private;
ThreadPlanPython::ThreadPlanPython(Thread &thread, const char *class_name)
: ThreadPlan(ThreadPlan::eKindPython, "Python based Thread Plan", thread,
eVoteNoOpinion, eVoteNoOpinion),
- m_class_name(class_name) {
+ m_class_name(class_name), m_did_push(false) {
SetIsMasterPlan(true);
SetOkayToDiscard(true);
SetPrivate(false);
@@ -47,20 +43,22 @@ ThreadPlanPython::~ThreadPlanPython() {
}
bool ThreadPlanPython::ValidatePlan(Stream *error) {
- // I have to postpone setting up the implementation till after the constructor
- // because I need to call
- // shared_from_this, which you can't do in the constructor. So I'll do it
- // here.
- if (m_implementation_sp)
+ if (!m_did_push)
return true;
- else
+
+ if (!m_implementation_sp) {
+ if (error)
+ error->Printf("Python thread plan does not have an implementation");
return false;
+ }
+
+ return true;
}
void ThreadPlanPython::DidPush() {
// We set up the script side in DidPush, so that it can push other plans in
// the constructor, and doesn't have to care about the details of DidPush.
-
+ m_did_push = true;
if (!m_class_name.empty()) {
ScriptInterpreter *script_interp = m_thread.GetProcess()
->GetTarget()
diff --git a/source/Target/ThreadPlanRunToAddress.cpp b/source/Target/ThreadPlanRunToAddress.cpp
index 6d1a8b5c27ff..bd11f8b82f78 100644
--- a/source/Target/ThreadPlanRunToAddress.cpp
+++ b/source/Target/ThreadPlanRunToAddress.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -73,6 +69,8 @@ void ThreadPlanRunToAddress::SetInitialBreakpoints() {
->CreateBreakpoint(m_addresses[i], true, false)
.get();
if (breakpoint != nullptr) {
+ if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
m_break_ids[i] = breakpoint->GetID();
breakpoint->SetThreadID(m_thread.GetID());
breakpoint->SetBreakpointKind("run-to-address");
@@ -85,6 +83,7 @@ ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
for (size_t i = 0; i < num_break_ids; i++) {
m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
}
+ m_could_not_resolve_hw_bp = false;
}
void ThreadPlanRunToAddress::GetDescription(Stream *s,
@@ -133,10 +132,15 @@ void ThreadPlanRunToAddress::GetDescription(Stream *s,
}
bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->Printf("Could not set hardware breakpoint(s)");
+ return false;
+ }
+
// If we couldn't set the breakpoint for some reason, then this won't work.
bool all_bps_good = true;
size_t num_break_ids = m_break_ids.size();
-
for (size_t i = 0; i < num_break_ids; i++) {
if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
all_bps_good = false;
diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp
index c7afe0d9a8a7..8062d8059c14 100644
--- a/source/Target/ThreadPlanShouldStopHere.cpp
+++ b/source/Target/ThreadPlanShouldStopHere.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanShouldStopHere.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/RegisterContext.h"
@@ -43,11 +39,11 @@ ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(
ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() = default;
bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(
- FrameComparison operation) {
+ FrameComparison operation, Status &status) {
bool should_stop_here = true;
if (m_callbacks.should_stop_here_callback) {
should_stop_here = m_callbacks.should_stop_here_callback(
- m_owner, m_flags, operation, m_baton);
+ m_owner, m_flags, operation, status, m_baton);
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
if (log) {
lldb::addr_t current_addr =
@@ -63,7 +59,7 @@ bool ThreadPlanShouldStopHere::InvokeShouldStopHereCallback(
bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
- void *baton) {
+ Status &status, void *baton) {
bool should_stop_here = true;
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
if (!frame)
@@ -100,7 +96,7 @@ bool ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
- void *baton) {
+ Status &status, void *baton) {
const bool stop_others = false;
const size_t frame_index = 0;
ThreadPlanSP return_plan_sp;
@@ -137,8 +133,8 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
"Queueing StepInRange plan to step through line 0 code.");
return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepInRange(
- false, range, sc, NULL, eOnlyDuringStepping, eLazyBoolCalculate,
- eLazyBoolNo);
+ false, range, sc, NULL, eOnlyDuringStepping, status,
+ eLazyBoolCalculate, eLazyBoolNo);
}
}
@@ -146,24 +142,25 @@ ThreadPlanSP ThreadPlanShouldStopHere::DefaultStepFromHereCallback(
return_plan_sp =
current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop(
false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion,
- frame_index, true);
+ frame_index, status, true);
return return_plan_sp;
}
ThreadPlanSP ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(
- lldb_private::Flags &flags, lldb::FrameComparison operation) {
+ lldb_private::Flags &flags, lldb::FrameComparison operation,
+ Status &status) {
ThreadPlanSP return_plan_sp;
if (m_callbacks.step_from_here_callback) {
- return_plan_sp =
- m_callbacks.step_from_here_callback(m_owner, flags, operation, m_baton);
+ return_plan_sp = m_callbacks.step_from_here_callback(
+ m_owner, flags, operation, status, m_baton);
}
return return_plan_sp;
}
lldb::ThreadPlanSP ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut(
- lldb::FrameComparison operation) {
- if (!InvokeShouldStopHereCallback(operation))
- return QueueStepOutFromHerePlan(m_flags, operation);
+ lldb::FrameComparison operation, Status &status) {
+ if (!InvokeShouldStopHereCallback(operation, status))
+ return QueueStepOutFromHerePlan(m_flags, operation, status);
else
return ThreadPlanSP();
}
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
index 6405c135a33e..8f9889a9d68c 100644
--- a/source/Target/ThreadPlanStepInRange.cpp
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepInRange.h"
#include "lldb/Core/Architecture.h"
#include "lldb/Core/Module.h"
@@ -112,8 +108,16 @@ void ThreadPlanStepInRange::SetupAvoidNoDebug(
void ThreadPlanStepInRange::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
+
+ auto PrintFailureIfAny = [&]() {
+ if (m_status.Success())
+ return;
+ s->Printf(" failed (%s)", m_status.AsCString());
+ };
+
if (level == lldb::eDescriptionLevelBrief) {
s->Printf("step in");
+ PrintFailureIfAny();
return;
}
@@ -134,6 +138,8 @@ void ThreadPlanStepInRange::GetDescription(Stream *s,
DumpRanges(s);
}
+ PrintFailureIfAny();
+
s->PutChar('.');
}
@@ -166,7 +172,8 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// ShouldStopHere plan, and otherwise we're done.
// FIXME - This can be both a step in and a step out. Probably should
// record which in the m_virtual_step.
- m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
+ m_sub_plan_sp =
+ CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger, m_status);
} else {
// Stepping through should be done running other threads in general, since
// we're setting a breakpoint and continuing. So only stop others if we
@@ -185,11 +192,12 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// I'm going to make the assumption that you wouldn't RETURN to a
// trampoline. So if we are in a trampoline we think the frame is older
// because the trampoline confused the backtracer.
- m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
if (!m_sub_plan_sp) {
// Otherwise check the ShouldStopHere for step out:
- m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ m_sub_plan_sp =
+ CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
if (log) {
if (m_sub_plan_sp)
log->Printf("ShouldStopHere found plan to step out of this frame.");
@@ -227,8 +235,8 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// We may have set the plan up above in the FrameIsOlder section:
if (!m_sub_plan_sp)
- m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
if (log) {
if (m_sub_plan_sp)
@@ -240,7 +248,7 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
// If not, give the "should_stop" callback a chance to push a plan to get
// us out of here. But only do that if we actually have stepped in.
if (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
- m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
// If we've stepped in and we are going to stop here, check to see if we
// were asked to run past the prologue, and if so do that.
@@ -288,7 +296,7 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) {
log->Printf("Pushing past prologue ");
m_sub_plan_sp = m_thread.QueueThreadPlanForRunToAddress(
- false, func_start_address, true);
+ false, func_start_address, true, m_status);
}
}
}
@@ -384,7 +392,7 @@ bool ThreadPlanStepInRange::FrameMatchesAvoidCriteria() {
bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
ThreadPlan *current_plan, Flags &flags, FrameComparison operation,
- void *baton) {
+ Status &status, void *baton) {
bool should_stop_here = true;
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -392,7 +400,7 @@ bool ThreadPlanStepInRange::DefaultShouldStopHereCallback(
// First see if the ThreadPlanShouldStopHere default implementation thinks we
// should get out of here:
should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback(
- current_plan, flags, operation, baton);
+ current_plan, flags, operation, status, baton);
if (!should_stop_here)
return should_stop_here;
diff --git a/source/Target/ThreadPlanStepInstruction.cpp b/source/Target/ThreadPlanStepInstruction.cpp
index dd8f129a935b..7707454c9798 100644
--- a/source/Target/ThreadPlanStepInstruction.cpp
+++ b/source/Target/ThreadPlanStepInstruction.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepInstruction.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
@@ -57,11 +53,19 @@ void ThreadPlanStepInstruction::SetUpState() {
void ThreadPlanStepInstruction::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
+ auto PrintFailureIfAny = [&]() {
+ if (m_status.Success())
+ return;
+ s->Printf(" failed (%s)", m_status.AsCString());
+ };
+
if (level == lldb::eDescriptionLevelBrief) {
if (m_step_over)
s->Printf("instruction step over");
else
s->Printf("instruction step into");
+
+ PrintFailureIfAny();
} else {
s->Printf("Stepping one instruction past ");
s->Address(m_instruction_addr, sizeof(addr_t));
@@ -72,6 +76,8 @@ void ThreadPlanStepInstruction::GetDescription(Stream *s,
s->Printf(" stepping over calls");
else
s->Printf(" stepping into calls");
+
+ PrintFailureIfAny();
}
}
@@ -192,7 +198,8 @@ bool ThreadPlanStepInstruction::ShouldStop(Event *event_ptr) {
// for now it is safer to run others.
const bool stop_others = false;
m_thread.QueueThreadPlanForStepOutNoShouldStop(
- false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0);
+ false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
+ m_status);
return false;
} else {
if (log) {
diff --git a/source/Target/ThreadPlanStepOut.cpp b/source/Target/ThreadPlanStepOut.cpp
index f2db6e4b6f42..378de53fafd7 100644
--- a/source/Target/ThreadPlanStepOut.cpp
+++ b/source/Target/ThreadPlanStepOut.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepOut.h"
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/Core/Value.h"
@@ -48,18 +44,36 @@ ThreadPlanStepOut::ThreadPlanStepOut(
m_return_addr(LLDB_INVALID_ADDRESS), m_stop_others(stop_others),
m_immediate_step_from_function(nullptr),
m_calculate_return_value(gather_return_value) {
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
SetFlagsToDefault();
SetupAvoidNoDebug(step_out_avoids_code_without_debug_info);
m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
- StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1));
+ uint32_t return_frame_index = frame_idx + 1;
+ StackFrameSP return_frame_sp(
+ m_thread.GetStackFrameAtIndex(return_frame_index));
StackFrameSP immediate_return_from_sp(
m_thread.GetStackFrameAtIndex(frame_idx));
if (!return_frame_sp || !immediate_return_from_sp)
return; // we can't do anything here. ValidatePlan() will return false.
+ // While stepping out, behave as-if artificial frames are not present.
+ while (return_frame_sp->IsArtificial()) {
+ m_stepped_past_frames.push_back(return_frame_sp);
+
+ ++return_frame_index;
+ return_frame_sp = m_thread.GetStackFrameAtIndex(return_frame_index);
+
+ // We never expect to see an artificial frame without a regular ancestor.
+ // If this happens, log the issue and defensively refuse to step out.
+ if (!return_frame_sp) {
+ LLDB_LOG(log, "Can't step out of frame with artificial ancestors");
+ return;
+ }
+ }
+
m_step_out_to_id = return_frame_sp->GetStackID();
m_immediate_step_from_id = immediate_return_from_sp->GetStackID();
@@ -67,7 +81,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
// have to be a little more careful. It is non-trivial to determine the real
// "return code address" for an inlined frame, so we have to work our way to
// that frame and then step out.
- if (immediate_return_from_sp && immediate_return_from_sp->IsInlined()) {
+ if (immediate_return_from_sp->IsInlined()) {
if (frame_idx > 0) {
// First queue a plan that gets us to this inlined frame, and when we get
// there we'll queue a second plan that walks us out of this frame.
@@ -82,7 +96,7 @@ ThreadPlanStepOut::ThreadPlanStepOut(
// just do that now.
QueueInlinedStepPlan(false);
}
- } else if (return_frame_sp) {
+ } else {
// Find the return address and set a breakpoint there:
// FIXME - can we do this more securely if we know first_insn?
@@ -115,7 +129,10 @@ ThreadPlanStepOut::ThreadPlanStepOut(
Breakpoint *return_bp = m_thread.CalculateTarget()
->CreateBreakpoint(m_return_addr, true, false)
.get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(m_thread.GetID());
m_return_bp_id = return_bp->GetID();
return_bp->SetBreakpointKind("step-out");
@@ -198,19 +215,35 @@ void ThreadPlanStepOut::GetDescription(Stream *s,
s->Printf(" using breakpoint site %d", m_return_bp_id);
}
}
+
+ s->Printf("\n");
+ for (StackFrameSP frame_sp : m_stepped_past_frames) {
+ s->Printf("Stepped out past: ");
+ frame_sp->DumpUsingSettingsFormat(s);
+ }
}
bool ThreadPlanStepOut::ValidatePlan(Stream *error) {
if (m_step_out_to_inline_plan_sp)
return m_step_out_to_inline_plan_sp->ValidatePlan(error);
- else if (m_step_through_inline_plan_sp)
+
+ if (m_step_through_inline_plan_sp)
return m_step_through_inline_plan_sp->ValidatePlan(error);
- else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
+
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+
+ if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
if (error)
error->PutCString("Could not create return address breakpoint.");
return false;
- } else
- return true;
+ }
+
+ return true;
}
bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
@@ -257,7 +290,7 @@ bool ThreadPlanStepOut::DoPlanExplainsStop(Event *event_ptr) {
}
if (done) {
- if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
+ if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
CalculateReturnValue();
SetPlanComplete();
}
@@ -319,12 +352,12 @@ bool ThreadPlanStepOut::ShouldStop(Event *event_ptr) {
// is consult the ShouldStopHere, and we are done.
if (done) {
- if (InvokeShouldStopHereCallback(eFrameCompareOlder)) {
+ if (InvokeShouldStopHereCallback(eFrameCompareOlder, m_status)) {
CalculateReturnValue();
SetPlanComplete();
} else {
m_step_out_further_plan_sp =
- QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder);
+ QueueStepOutFromHerePlan(m_flags, eFrameCompareOlder, m_status);
done = false;
}
}
diff --git a/source/Target/ThreadPlanStepOverBreakpoint.cpp b/source/Target/ThreadPlanStepOverBreakpoint.cpp
index 7497dbff1729..8b24bf94973b 100644
--- a/source/Target/ThreadPlanStepOverBreakpoint.cpp
+++ b/source/Target/ThreadPlanStepOverBreakpoint.cpp
@@ -9,10 +9,6 @@
#include "lldb/Target/ThreadPlanStepOverBreakpoint.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/Log.h"
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index b88d25b707eb..129f30371f8d 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/source/Target/ThreadPlanStepOverRange.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepOverRange.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -51,10 +47,18 @@ ThreadPlanStepOverRange::~ThreadPlanStepOverRange() = default;
void ThreadPlanStepOverRange::GetDescription(Stream *s,
lldb::DescriptionLevel level) {
+ auto PrintFailureIfAny = [&]() {
+ if (m_status.Success())
+ return;
+ s->Printf(" failed (%s)", m_status.AsCString());
+ };
+
if (level == lldb::eDescriptionLevelBrief) {
s->Printf("step over");
+ PrintFailureIfAny();
return;
}
+
s->Printf("Stepping over");
bool printed_line_info = false;
if (m_addr_context.line_entry.IsValid()) {
@@ -68,6 +72,8 @@ void ThreadPlanStepOverRange::GetDescription(Stream *s,
DumpRanges(s);
}
+ PrintFailureIfAny();
+
s->PutChar('.');
}
@@ -117,10 +123,7 @@ bool ThreadPlanStepOverRange::IsEquivalentContext(
}
}
// Fall back to symbol if we have no decision from comp_unit/function/block.
- if (m_addr_context.symbol && m_addr_context.symbol == context.symbol) {
- return true;
- }
- return false;
+ return m_addr_context.symbol && m_addr_context.symbol == context.symbol;
}
bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
@@ -151,8 +154,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// because the trampoline confused the backtracer. As below, we step
// through first, and then try to figure out how to get back out again.
- new_plan_sp =
- m_thread.QueueThreadPlanForStepThrough(m_stack_id, false, stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
+ stop_others, m_status);
if (new_plan_sp && log)
log->Printf(
@@ -173,11 +176,11 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (IsEquivalentContext(older_context)) {
new_plan_sp = m_thread.QueueThreadPlanForStepOutNoShouldStop(
false, nullptr, true, stop_others, eVoteNo, eVoteNoOpinion, 0,
- true);
+ m_status, true);
break;
} else {
- new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
// If we found a way through, then we should stop recursing.
if (new_plan_sp)
break;
@@ -196,8 +199,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// we are in a stub then it's likely going to be hard to get out from
// here. It is probably easiest to step into the stub, and then it will
// be straight-forward to step out.
- new_plan_sp = m_thread.QueueThreadPlanForStepThrough(m_stack_id, false,
- stop_others);
+ new_plan_sp = m_thread.QueueThreadPlanForStepThrough(
+ m_stack_id, false, stop_others, m_status);
} else {
// The current clang (at least through 424) doesn't always get the
// address range for the DW_TAG_inlined_subroutines right, so that when
@@ -287,8 +290,8 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
cur_pc);
new_plan_sp = m_thread.QueueThreadPlanForStepOverRange(
- abort_other_plans, step_range, sc,
- stop_other_threads);
+ abort_other_plans, step_range, sc, stop_other_threads,
+ m_status);
break;
}
look_ahead_step++;
@@ -309,7 +312,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
// If we haven't figured out something to do yet, then ask the ShouldStopHere
// callback:
if (!new_plan_sp) {
- new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ new_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order, m_status);
}
if (!new_plan_sp)
@@ -323,7 +326,7 @@ bool ThreadPlanStepOverRange::ShouldStop(Event *event_ptr) {
if (!new_plan_sp) {
// For efficiencies sake, we know we're done here so we don't have to do
// this calculation again in MischiefManaged.
- SetPlanComplete();
+ SetPlanComplete(m_status.Success());
return true;
} else
return false;
diff --git a/source/Target/ThreadPlanStepRange.cpp b/source/Target/ThreadPlanStepRange.cpp
index 5a71119015eb..7ba68ee84981 100644
--- a/source/Target/ThreadPlanStepRange.cpp
+++ b/source/Target/ThreadPlanStepRange.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepRange.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/BreakpointSite.h"
@@ -61,7 +57,15 @@ void ThreadPlanStepRange::DidPush() {
SetNextBranchBreakpoint();
}
-bool ThreadPlanStepRange::ValidatePlan(Stream *error) { return true; }
+bool ThreadPlanStepRange::ValidatePlan(Stream *error) {
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+ return true;
+}
Vote ThreadPlanStepRange::ShouldReportStop(Event *event_ptr) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -285,6 +289,7 @@ void ThreadPlanStepRange::ClearNextBranchBreakpoint() {
m_next_branch_bp_sp->GetID());
GetTarget().RemoveBreakpointByID(m_next_branch_bp_sp->GetID());
m_next_branch_bp_sp.reset();
+ m_could_not_resolve_hw_bp = false;
}
}
@@ -335,6 +340,11 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
m_next_branch_bp_sp =
GetTarget().CreateBreakpoint(run_to_address, is_internal, false);
if (m_next_branch_bp_sp) {
+
+ if (m_next_branch_bp_sp->IsHardware() &&
+ !m_next_branch_bp_sp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
+
if (log) {
lldb::break_id_t bp_site_id = LLDB_INVALID_BREAK_ID;
BreakpointLocationSP bp_loc =
@@ -351,8 +361,10 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
run_to_address.GetLoadAddress(
&m_thread.GetProcess()->GetTarget()));
}
+
m_next_branch_bp_sp->SetThreadID(m_thread.GetID());
m_next_branch_bp_sp->SetBreakpointKind("next-branch-location");
+
return true;
} else
return false;
diff --git a/source/Target/ThreadPlanStepThrough.cpp b/source/Target/ThreadPlanStepThrough.cpp
index c039a32f5515..d1f3c2219f6d 100644
--- a/source/Target/ThreadPlanStepThrough.cpp
+++ b/source/Target/ThreadPlanStepThrough.cpp
@@ -7,12 +7,9 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepThrough.h"
#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -61,7 +58,10 @@ ThreadPlanStepThrough::ThreadPlanStepThrough(Thread &thread,
->GetTarget()
.CreateBreakpoint(m_backstop_addr, true, false)
.get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(m_thread.GetID());
m_backstop_bkpt_id = return_bp->GetID();
return_bp->SetBreakpointKind("step-through-backstop");
@@ -95,6 +95,15 @@ void ThreadPlanStepThrough::LookForPlanToStepThroughFromCurrentPC() {
if (objc_runtime)
m_sub_plan_sp =
objc_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
+
+ CPPLanguageRuntime *cpp_runtime =
+ m_thread.GetProcess()->GetCPPLanguageRuntime();
+
+ // If the ObjC runtime did not provide us with a step though plan then if we
+ // have it check the C++ runtime for a step though plan.
+ if (!m_sub_plan_sp.get() && cpp_runtime)
+ m_sub_plan_sp =
+ cpp_runtime->GetStepThroughTrampolinePlan(m_thread, m_stop_others);
}
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
@@ -129,7 +138,26 @@ void ThreadPlanStepThrough::GetDescription(Stream *s,
}
bool ThreadPlanStepThrough::ValidatePlan(Stream *error) {
- return m_sub_plan_sp.get() != nullptr;
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ }
+
+ if (m_backstop_bkpt_id == LLDB_INVALID_BREAK_ID) {
+ if (error)
+ error->PutCString("Could not create backstop breakpoint.");
+ return false;
+ }
+
+ if (!m_sub_plan_sp.get()) {
+ if (error)
+ error->PutCString("Does not have a subplan.");
+ return false;
+ }
+
+ return true;
}
bool ThreadPlanStepThrough::DoPlanExplainsStop(Event *event_ptr) {
@@ -205,6 +233,7 @@ void ThreadPlanStepThrough::ClearBackstopBreakpoint() {
if (m_backstop_bkpt_id != LLDB_INVALID_BREAK_ID) {
m_thread.GetProcess()->GetTarget().RemoveBreakpointByID(m_backstop_bkpt_id);
m_backstop_bkpt_id = LLDB_INVALID_BREAK_ID;
+ m_could_not_resolve_hw_bp = false;
}
}
diff --git a/source/Target/ThreadPlanStepUntil.cpp b/source/Target/ThreadPlanStepUntil.cpp
index 9984ee925c86..1335c62ba94c 100644
--- a/source/Target/ThreadPlanStepUntil.cpp
+++ b/source/Target/ThreadPlanStepUntil.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadPlanStepUntil.h"
#include "lldb/Breakpoint/Breakpoint.h"
@@ -57,7 +53,10 @@ ThreadPlanStepUntil::ThreadPlanStepUntil(Thread &thread,
m_return_addr = return_frame_sp->GetStackID().GetPC();
Breakpoint *return_bp =
target_sp->CreateBreakpoint(m_return_addr, true, false).get();
+
if (return_bp != nullptr) {
+ if (return_bp->IsHardware() && !return_bp->HasResolvedLocations())
+ m_could_not_resolve_hw_bp = true;
return_bp->SetThreadID(thread_id);
m_return_bp_id = return_bp->GetID();
return_bp->SetBreakpointKind("until-return-backstop");
@@ -97,6 +96,7 @@ void ThreadPlanStepUntil::Clear() {
}
}
m_until_points.clear();
+ m_could_not_resolve_hw_bp = false;
}
void ThreadPlanStepUntil::GetDescription(Stream *s,
@@ -127,9 +127,16 @@ void ThreadPlanStepUntil::GetDescription(Stream *s,
}
bool ThreadPlanStepUntil::ValidatePlan(Stream *error) {
- if (m_return_bp_id == LLDB_INVALID_BREAK_ID)
+ if (m_could_not_resolve_hw_bp) {
+ if (error)
+ error->PutCString(
+ "Could not create hardware breakpoint for thread plan.");
+ return false;
+ } else if (m_return_bp_id == LLDB_INVALID_BREAK_ID) {
+ if (error)
+ error->PutCString("Could not create return breakpoint.");
return false;
- else {
+ } else {
until_collection::iterator pos, end = m_until_points.end();
for (pos = m_until_points.begin(); pos != end; pos++) {
if (!LLDB_BREAK_ID_IS_VALID((*pos).second))
diff --git a/source/Target/ThreadPlanTracer.cpp b/source/Target/ThreadPlanTracer.cpp
index acbbd4d8bcc2..04e29fd26080 100644
--- a/source/Target/ThreadPlanTracer.cpp
+++ b/source/Target/ThreadPlanTracer.cpp
@@ -7,15 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
#include <cstring>
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/DumpRegisterValue.h"
#include "lldb/Core/Module.h"
-#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
#include "lldb/Symbol/TypeList.h"
@@ -30,6 +27,7 @@
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Target/ThreadSpec.cpp b/source/Target/ThreadSpec.cpp
index 444a5a5b262a..bae3d0b2238f 100644
--- a/source/Target/ThreadSpec.cpp
+++ b/source/Target/ThreadSpec.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/ThreadSpec.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/StructuredData.h"
diff --git a/source/Target/UnixSignals.cpp b/source/Target/UnixSignals.cpp
index 9cfb1b74adee..1448535b8be4 100644
--- a/source/Target/UnixSignals.cpp
+++ b/source/Target/UnixSignals.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnixSignals.h"
#include "Plugins/Process/Utility/FreeBSDSignals.h"
#include "Plugins/Process/Utility/LinuxSignals.h"
@@ -88,7 +84,7 @@ void UnixSignals::Reset() {
AddSignal(10, "SIGBUS", false, true, true, "bus error");
AddSignal(11, "SIGSEGV", false, true, true, "segmentation violation");
AddSignal(12, "SIGSYS", false, true, true, "bad argument to system call");
- AddSignal(13, "SIGPIPE", false, true, true,
+ AddSignal(13, "SIGPIPE", false, false, false,
"write on a pipe with no one to read it");
AddSignal(14, "SIGALRM", false, false, false, "alarm clock");
AddSignal(15, "SIGTERM", false, true, true,
diff --git a/source/Target/UnwindAssembly.cpp b/source/Target/UnwindAssembly.cpp
index 3b2b7bf17025..06b6aef28da7 100644
--- a/source/Target/UnwindAssembly.cpp
+++ b/source/Target/UnwindAssembly.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Target/UnwindAssembly.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/PluginManager.h"
diff --git a/source/Utility/ArchSpec.cpp b/source/Utility/ArchSpec.cpp
index 1c50c313e0d1..752fb182d79a 100644
--- a/source/Utility/ArchSpec.cpp
+++ b/source/Utility/ArchSpec.cpp
@@ -11,15 +11,15 @@
#include "lldb/Utility/Log.h"
#include "lldb/Utility/NameMatches.h"
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_C...
+#include "lldb/lldb-defines.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Twine.h" // for Twine
+#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/BinaryFormat/MachO.h" // for CPUType::CPU_T...
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
+#include "llvm/BinaryFormat/MachO.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/Host.h"
using namespace lldb;
@@ -610,10 +610,8 @@ const char *ArchSpec::GetArchitectureName() const {
bool ArchSpec::IsMIPS() const {
const llvm::Triple::ArchType machine = GetMachine();
- if (machine == llvm::Triple::mips || machine == llvm::Triple::mipsel ||
- machine == llvm::Triple::mips64 || machine == llvm::Triple::mips64el)
- return true;
- return false;
+ return machine == llvm::Triple::mips || machine == llvm::Triple::mipsel ||
+ machine == llvm::Triple::mips64 || machine == llvm::Triple::mips64el;
}
std::string ArchSpec::GetTargetABI() const {
@@ -815,6 +813,7 @@ bool ArchSpec::CharIsSignedByDefault() const {
case llvm::Triple::ppc64le:
case llvm::Triple::systemz:
case llvm::Triple::xcore:
+ case llvm::Triple::arc:
return false;
}
}
@@ -946,13 +945,13 @@ bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu,
m_triple.setVendor(llvm::Triple::Apple);
// Don't set the OS. It could be simulator, macosx, ios, watchos,
- // tvos. We could get close with the cpu type - but we can't get it
- // right all of the time. Better to leave this unset so other
- // sections of code will set it when they have more information.
- // NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets
- // the OSName to
- // "unknown" and the ArchSpec::TripleVendorWasSpecified() method says
- // that any OSName setting means it was specified.
+ // tvos, bridgeos. We could get close with the cpu type - but we
+ // can't get it right all of the time. Better to leave this unset
+ // so other sections of code will set it when they have more
+ // information. NB: don't call m_triple.setOS (llvm::Triple::UnknownOS).
+ // That sets the OSName to "unknown" and the
+ // ArchSpec::TripleVendorWasSpecified() method says that any OSName
+ // setting means it was specified.
} else if (arch_type == eArchTypeELF) {
switch (os) {
case llvm::ELF::ELFOSABI_AIX:
@@ -1018,7 +1017,7 @@ bool ArchSpec::IsCompatibleMatch(const ArchSpec &rhs) const {
return IsEqualTo(rhs, false);
}
-static bool isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs,
+static bool IsCompatibleEnvironment(llvm::Triple::EnvironmentType lhs,
llvm::Triple::EnvironmentType rhs) {
if (lhs == rhs)
return true;
@@ -1095,9 +1094,7 @@ bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const {
const llvm::Triple::EnvironmentType rhs_triple_env =
rhs_triple.getEnvironment();
- if (!isCompatibleEnvironment(lhs_triple_env, rhs_triple_env))
- return false;
- return true;
+ return IsCompatibleEnvironment(lhs_triple_env, rhs_triple_env);
}
return false;
}
@@ -1477,7 +1474,10 @@ bool ArchSpec::IsAlwaysThumbInstructions() const {
if (GetCore() == ArchSpec::Core::eCore_arm_armv7m ||
GetCore() == ArchSpec::Core::eCore_arm_armv7em ||
- GetCore() == ArchSpec::Core::eCore_arm_armv6m) {
+ GetCore() == ArchSpec::Core::eCore_arm_armv6m ||
+ GetCore() == ArchSpec::Core::eCore_thumbv7m ||
+ GetCore() == ArchSpec::Core::eCore_thumbv7em ||
+ GetCore() == ArchSpec::Core::eCore_thumbv6m) {
return true;
}
}
diff --git a/source/Core/Broadcaster.cpp b/source/Utility/Broadcaster.cpp
index 198434b46c29..5b9b99801b22 100644
--- a/source/Core/Broadcaster.cpp
+++ b/source/Utility/Broadcaster.cpp
@@ -7,21 +7,21 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Broadcaster.h"
+#include "lldb/Utility/Broadcaster.h"
-#include "lldb/Core/Event.h"
-#include "lldb/Core/Listener.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/Listener.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAnyCategoriesSet, Get...
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Logging.h"
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include <algorithm> // for find_if
-#include <memory> // for make_shared
-#include <type_traits> // for move
+#include <algorithm>
+#include <memory>
+#include <type_traits>
-#include <assert.h> // for assert
-#include <stddef.h> // for size_t
+#include <assert.h>
+#include <stddef.h>
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Utility/CMakeLists.txt b/source/Utility/CMakeLists.txt
index 91f3c8773731..008054a0ae6e 100644
--- a/source/Utility/CMakeLists.txt
+++ b/source/Utility/CMakeLists.txt
@@ -9,7 +9,7 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
endif ()
if (NOT LLDB_DISABLE_LIBEDIT)
- list(APPEND LLDB_SYSTEM_LIBS edit)
+ list(APPEND LLDB_SYSTEM_LIBS ${libedit_LIBRARIES})
endif()
if (NOT LLDB_DISABLE_CURSES)
list(APPEND LLDB_SYSTEM_LIBS ${CURSES_LIBRARIES})
@@ -22,7 +22,9 @@ if (NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB )
list(APPEND LLDB_SYSTEM_LIBS atomic)
endif()
-list(APPEND LLDB_SYSTEM_LIBS ${Backtrace_LIBRARY})
+if(Backtrace_FOUND)
+ list(APPEND LLDB_SYSTEM_LIBS ${Backtrace_LIBRARY})
+endif()
if (NOT LLDB_DISABLE_PYTHON AND NOT LLVM_BUILD_STATIC)
list(APPEND LLDB_SYSTEM_LIBS ${PYTHON_LIBRARIES})
@@ -43,6 +45,7 @@ add_lldb_library(lldbUtility
ArchSpec.cpp
Args.cpp
Baton.cpp
+ Broadcaster.cpp
Connection.cpp
ConstString.cpp
CompletionRequest.cpp
@@ -51,18 +54,22 @@ add_lldb_library(lldbUtility
DataEncoder.cpp
DataExtractor.cpp
Environment.cpp
- FastDemangle.cpp
+ Event.cpp
FileSpec.cpp
IOObject.cpp
JSON.cpp
LLDBAssert.cpp
+ Listener.cpp
Log.cpp
Logging.cpp
NameMatches.cpp
- Range.cpp
+ RegisterValue.cpp
RegularExpression.cpp
+ Reproducer.cpp
+ Scalar.cpp
SelectHelper.cpp
SharingPtr.cpp
+ State.cpp
Status.cpp
Stream.cpp
StreamCallback.cpp
diff --git a/source/Utility/CompletionRequest.cpp b/source/Utility/CompletionRequest.cpp
index c88747e2abe3..096661b7e99f 100644
--- a/source/Utility/CompletionRequest.cpp
+++ b/source/Utility/CompletionRequest.cpp
@@ -16,11 +16,10 @@ CompletionRequest::CompletionRequest(llvm::StringRef command_line,
unsigned raw_cursor_pos,
int match_start_point,
int max_return_elements,
- StringList &matches)
+ CompletionResult &result)
: m_command(command_line), m_raw_cursor_pos(raw_cursor_pos),
m_match_start_point(match_start_point),
- m_max_return_elements(max_return_elements), m_matches(&matches) {
- matches.Clear();
+ m_max_return_elements(max_return_elements), m_result(result) {
// We parse the argument up to the cursor, so the last argument in
// parsed_line is the one containing the cursor, and the cursor is after the
@@ -36,8 +35,6 @@ CompletionRequest::CompletionRequest(llvm::StringRef command_line,
m_cursor_char_position =
strlen(m_partial_parsed_line.GetArgumentAtIndex(m_cursor_index));
- matches.Clear();
-
const char *cursor = command_line.data() + raw_cursor_pos;
if (raw_cursor_pos > 0 && cursor[-1] == ' ') {
// We are just after a space. If we are in an argument, then we will
@@ -58,3 +55,39 @@ CompletionRequest::CompletionRequest(llvm::StringRef command_line,
}
}
}
+
+std::string CompletionResult::Completion::GetUniqueKey() const {
+
+ // We build a unique key for this pair of completion:description. We
+ // prefix the key with the length of the completion string. This prevents
+ // that we could get any collisions from completions pairs such as these:
+ // "foo:", "bar" would be "foo:bar", but will now be: "4foo:bar"
+ // "foo", ":bar" would be "foo:bar", but will now be: "3foo:bar"
+
+ std::string result;
+ result.append(std::to_string(m_completion.size()));
+ result.append(m_completion);
+ result.append(m_descripton);
+ return result;
+}
+
+void CompletionResult::AddResult(llvm::StringRef completion,
+ llvm::StringRef description) {
+ Completion r(completion, description);
+
+ // Add the completion if we haven't seen the same value before.
+ if (m_added_values.insert(r.GetUniqueKey()).second)
+ m_results.push_back(r);
+}
+
+void CompletionResult::GetMatches(StringList &matches) const {
+ matches.Clear();
+ for (const Completion &completion : m_results)
+ matches.AppendString(completion.m_completion);
+}
+
+void CompletionResult::GetDescriptions(StringList &descriptions) const {
+ descriptions.Clear();
+ for (const Completion &completion : m_results)
+ descriptions.AppendString(completion.m_descripton);
+}
diff --git a/source/Utility/ConstString.cpp b/source/Utility/ConstString.cpp
index 5ef4b2faa3b8..9b8bea71e2ad 100644
--- a/source/Utility/ConstString.cpp
+++ b/source/Utility/ConstString.cpp
@@ -12,20 +12,20 @@
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/iterator.h" // for iterator_facade_base
-#include "llvm/Support/Allocator.h" // for BumpPtrAllocator
-#include "llvm/Support/DJB.h" // for djbHash
-#include "llvm/Support/FormatProviders.h" // for format_provider
+#include "llvm/ADT/iterator.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/DJB.h"
+#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/RWMutex.h"
#include "llvm/Support/Threading.h"
-#include <algorithm> // for min
+#include <algorithm>
#include <array>
-#include <utility> // for make_pair, pair
+#include <utility>
-#include <inttypes.h> // for PRIu64
-#include <stdint.h> // for uint8_t, uint32_t, uint64_t
-#include <string.h> // for size_t, strlen
+#include <inttypes.h>
+#include <stdint.h>
+#include <string.h>
using namespace lldb_private;
@@ -111,38 +111,34 @@ public:
}
const char *
- GetConstCStringAndSetMangledCounterPart(const char *demangled_cstr,
+ GetConstCStringAndSetMangledCounterPart(llvm::StringRef demangled,
const char *mangled_ccstr) {
- if (demangled_cstr != nullptr) {
- const char *demangled_ccstr = nullptr;
+ const char *demangled_ccstr = nullptr;
- {
- llvm::StringRef string_ref(demangled_cstr);
- const uint8_t h = hash(string_ref);
- llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ {
+ const uint8_t h = hash(demangled);
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
- // Make string pool entry with the mangled counterpart already set
- StringPoolEntryType &entry =
- *m_string_pools[h]
- .m_string_map.insert(std::make_pair(string_ref, mangled_ccstr))
- .first;
+ // Make or update string pool entry with the mangled counterpart
+ StringPool &map = m_string_pools[h].m_string_map;
+ StringPoolEntryType &entry = *map.try_emplace(demangled).first;
- // Extract the const version of the demangled_cstr
- demangled_ccstr = entry.getKeyData();
- }
+ entry.second = mangled_ccstr;
- {
- // Now assign the demangled const string as the counterpart of the
- // mangled const string...
- const uint8_t h = hash(llvm::StringRef(mangled_ccstr));
- llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
- GetStringMapEntryFromKeyData(mangled_ccstr).setValue(demangled_ccstr);
- }
+ // Extract the const version of the demangled_cstr
+ demangled_ccstr = entry.getKeyData();
+ }
- // Return the constant demangled C string
- return demangled_ccstr;
+ {
+ // Now assign the demangled const string as the counterpart of the
+ // mangled const string...
+ const uint8_t h = hash(llvm::StringRef(mangled_ccstr));
+ llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex);
+ GetStringMapEntryFromKeyData(mangled_ccstr).setValue(demangled_ccstr);
}
- return nullptr;
+
+ // Return the constant demangled C string
+ return demangled_ccstr;
}
const char *GetConstTrimmedCStringWithLength(const char *cstr,
@@ -306,7 +302,7 @@ void ConstString::SetString(const llvm::StringRef &s) {
m_string = StringPool().GetConstCStringWithLength(s.data(), s.size());
}
-void ConstString::SetCStringWithMangledCounterpart(const char *demangled,
+void ConstString::SetStringWithMangledCounterpart(llvm::StringRef demangled,
const ConstString &mangled) {
m_string = StringPool().GetConstCStringAndSetMangledCounterPart(
demangled, mangled.m_string);
diff --git a/source/Utility/DataBufferHeap.cpp b/source/Utility/DataBufferHeap.cpp
index e686ee8d35e5..36cac0079ac0 100644
--- a/source/Utility/DataBufferHeap.cpp
+++ b/source/Utility/DataBufferHeap.cpp
@@ -9,10 +9,6 @@
#include "lldb/Utility/DataBufferHeap.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
using namespace lldb_private;
diff --git a/source/Utility/DataBufferLLVM.cpp b/source/Utility/DataBufferLLVM.cpp
index 713c3c2814ea..0ab3fe5afd46 100644
--- a/source/Utility/DataBufferLLVM.cpp
+++ b/source/Utility/DataBufferLLVM.cpp
@@ -13,8 +13,8 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
-#include <assert.h> // for assert
-#include <type_traits> // for move
+#include <assert.h>
+#include <type_traits>
using namespace lldb_private;
@@ -27,34 +27,6 @@ DataBufferLLVM::DataBufferLLVM(
DataBufferLLVM::~DataBufferLLVM() {}
-std::shared_ptr<DataBufferLLVM>
-DataBufferLLVM::CreateSliceFromPath(const llvm::Twine &Path, uint64_t Size,
- uint64_t Offset) {
- // If the file resides non-locally, pass the volatile flag so that we don't
- // mmap it.
- bool IsVolatile = !llvm::sys::fs::is_local(Path);
-
- auto Buffer =
- llvm::WritableMemoryBuffer::getFileSlice(Path, Size, Offset, IsVolatile);
- if (!Buffer)
- return nullptr;
- return std::shared_ptr<DataBufferLLVM>(
- new DataBufferLLVM(std::move(*Buffer)));
-}
-
-std::shared_ptr<DataBufferLLVM>
-DataBufferLLVM::CreateFromPath(const llvm::Twine &Path) {
- // If the file resides non-locally, pass the volatile flag so that we don't
- // mmap it.
- bool IsVolatile = !llvm::sys::fs::is_local(Path);
-
- auto Buffer = llvm::WritableMemoryBuffer::getFile(Path, -1, IsVolatile);
- if (!Buffer)
- return nullptr;
- return std::shared_ptr<DataBufferLLVM>(
- new DataBufferLLVM(std::move(*Buffer)));
-}
-
uint8_t *DataBufferLLVM::GetBytes() {
return reinterpret_cast<uint8_t *>(Buffer->getBufferStart());
}
diff --git a/source/Utility/DataEncoder.cpp b/source/Utility/DataEncoder.cpp
index 7edee3c2f279..c26c0fa63ab3 100644
--- a/source/Utility/DataEncoder.cpp
+++ b/source/Utility/DataEncoder.cpp
@@ -13,7 +13,7 @@
#include "lldb/Utility/Endian.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h" // for llvm_unreachable
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include <cassert>
diff --git a/source/Utility/DataExtractor.cpp b/source/Utility/DataExtractor.cpp
index 947232943aa7..ae5a3f9b7d8f 100644
--- a/source/Utility/DataExtractor.cpp
+++ b/source/Utility/DataExtractor.cpp
@@ -9,10 +9,10 @@
#include "lldb/Utility/DataExtractor.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-enumerations.h" // for ByteOrder::eByteOrderBig
-#include "lldb/lldb-forward.h" // for DataBufferSP
-#include "lldb/lldb-types.h" // for offset_t
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/DataBufferHeap.h"
@@ -28,15 +28,15 @@
#include "llvm/Support/MD5.h"
#include "llvm/Support/MathExtras.h"
-#include <algorithm> // for min
-#include <array> // for array
+#include <algorithm>
+#include <array>
#include <cassert>
-#include <cstdint> // for uint8_t, uint32_t, uint64_t
+#include <cstdint>
#include <string>
-#include <ctype.h> // for isprint
-#include <inttypes.h> // for PRIx64, PRId64
-#include <string.h> // for memcpy, memset, memchr
+#include <ctype.h>
+#include <inttypes.h>
+#include <string.h>
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Core/Event.cpp b/source/Utility/Event.cpp
index 3ebad7acdef7..ad9f6e340f8c 100644
--- a/source/Core/Event.cpp
+++ b/source/Utility/Event.cpp
@@ -7,18 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Event.h"
+#include "lldb/Utility/Event.h"
-#include "lldb/Core/Broadcaster.h"
+#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/StreamString.h" // for StreamString
-#include "lldb/lldb-enumerations.h" // for Format::eFormatBytes
+#include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-enumerations.h"
#include <algorithm>
-#include <ctype.h> // for isprint
+#include <ctype.h>
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Utility/FastDemangle.cpp b/source/Utility/FastDemangle.cpp
deleted file mode 100644
index d92670a9199b..000000000000
--- a/source/Utility/FastDemangle.cpp
+++ /dev/null
@@ -1,2393 +0,0 @@
-//===-- FastDemangle.cpp ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "lldb/Utility/FastDemangle.h"
-
-#include "llvm/Support/Compiler.h" // for LLVM_FALLTHROUGH
-
-#include <functional>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-//#define DEBUG_FAILURES 1
-//#define DEBUG_SUBSTITUTIONS 1
-//#define DEBUG_TEMPLATE_ARGS 1
-//#define DEBUG_HIGHWATER 1
-//#define DEBUG_REORDERING 1
-
-namespace {
-
-/// Represents the collection of qualifiers on a type
-
-enum Qualifiers {
- QualifierNone = 0,
- QualifierConst = 1,
- QualifierRestrict = 2,
- QualifierVolatile = 4,
- QualifierReference = 8,
- QualifierRValueReference = 16,
- QualifierPointer = 32
-};
-
-/// Categorizes the recognized operators
-
-enum class OperatorKind {
- Unary,
- Postfix,
- Binary,
- Ternary,
- Other,
- ConversionOperator,
- Vendor,
- NoMatch
-};
-
-/// Represents one of the recognized two-character operator abbreviations used
-/// when parsing operators as names and expressions
-
-struct Operator {
- const char *name;
- OperatorKind kind;
-};
-
-/// Represents a range of characters in the output buffer, typically for use
-/// with RewriteRange()
-
-struct BufferRange {
- int offset;
- int length;
-};
-
-/// Transient state required while parsing a name
-
-struct NameState {
- bool parse_function_params;
- bool is_last_generic;
- bool has_no_return_type;
- BufferRange last_name_range;
-};
-
-/// LLDB's fast C++ demangler
-///
-/// This is an incomplete implementation designed to speed up the demangling
-/// process that is often a bottleneck when LLDB stops a process for the first
-/// time. Where the implementation doesn't know how to demangle a symbol it
-/// fails gracefully to allow the caller to fall back to the existing
-/// demangler.
-///
-/// Over time the full mangling spec should be supported without compromising
-/// performance for the most common cases.
-
-class SymbolDemangler {
-public:
- //----------------------------------------------------
- // Public API
- //----------------------------------------------------
-
- /// Create a SymbolDemangler
- ///
- /// The newly created demangler allocates and owns scratch memory sufficient
- /// for demangling typical symbols. Additional memory will be allocated if
- /// needed and managed by the demangler instance.
-
- SymbolDemangler() {
- m_buffer = (char *)malloc(8192);
- m_buffer_end = m_buffer + 8192;
- m_owns_buffer = true;
-
- m_rewrite_ranges = (BufferRange *)malloc(128 * sizeof(BufferRange));
- m_rewrite_ranges_size = 128;
- m_owns_m_rewrite_ranges = true;
- }
-
- /// Create a SymbolDemangler that uses provided scratch memory
- ///
- /// The provided memory is not owned by the demangler. It will be
- /// overwritten during calls to GetDemangledCopy() but can be used for other
- /// purposes between calls. The provided memory will not be freed when this
- /// instance is destroyed.
- ///
- /// If demangling a symbol requires additional space it will be allocated
- /// and managed by the demangler instance.
- ///
- /// @param storage_ptr Valid pointer to at least storage_size bytes of space
- /// that the SymbolDemangler can use during demangling
- ///
- /// @param storage_size Number of bytes of space available scratch memory
- /// referenced by storage_ptr
-
- SymbolDemangler(void *storage_ptr, size_t storage_size,
- std::function<void(const char *)> builtins_hook = nullptr)
- : m_builtins_hook(builtins_hook) {
- // Use up to 1/8th of the provided space for rewrite ranges
- m_rewrite_ranges_size = (storage_size >> 3) / sizeof(BufferRange);
- m_rewrite_ranges = (BufferRange *)storage_ptr;
- m_owns_m_rewrite_ranges = false;
-
- // Use the rest for the character buffer
- m_buffer =
- (char *)storage_ptr + m_rewrite_ranges_size * sizeof(BufferRange);
- m_buffer_end = (const char *)storage_ptr + storage_size;
- m_owns_buffer = false;
- }
-
- /// Destroys the SymbolDemangler and deallocates any scratch memory that it
- /// owns
-
- ~SymbolDemangler() {
- if (m_owns_buffer)
- free(m_buffer);
- if (m_owns_m_rewrite_ranges)
- free(m_rewrite_ranges);
- }
-
-#ifdef DEBUG_HIGHWATER
- int highwater_store = 0;
- int highwater_buffer = 0;
-#endif
-
- /// Parses the provided mangled name and returns a newly allocated
- /// demangling
- ///
- /// @param mangled_name Valid null-terminated C++ mangled name following the
- /// Itanium C++ ABI mangling specification as implemented by Clang
- ///
- /// @result Newly allocated null-terminated demangled name when demangling
- /// is successful, and nullptr when demangling fails. The caller is
- /// responsible for freeing the allocated memory.
-
- char *GetDemangledCopy(const char *mangled_name,
- long mangled_name_length = 0) {
- if (!ParseMangling(mangled_name, mangled_name_length))
- return nullptr;
-
-#ifdef DEBUG_HIGHWATER
- int rewrite_count = m_next_substitute_index +
- (m_rewrite_ranges_size - 1 - m_next_template_arg_index);
- int buffer_size = (int)(m_write_ptr - m_buffer);
- if (rewrite_count > highwater_store)
- highwater_store = rewrite_count;
- if (buffer_size > highwater_buffer)
- highwater_buffer = buffer_size;
-#endif
-
- int length = (int)(m_write_ptr - m_buffer);
- char *copy = (char *)malloc(length + 1);
- memcpy(copy, m_buffer, length);
- copy[length] = '\0';
- return copy;
- }
-
-private:
- //----------------------------------------------------
- // Grow methods
- //
- // Manage the storage used during demangling
- //----------------------------------------------------
-
- void GrowBuffer(long min_growth = 0) {
- // By default, double the size of the buffer
- long growth = m_buffer_end - m_buffer;
-
- // Avoid growing by more than 1MB at a time
- if (growth > 1 << 20)
- growth = 1 << 20;
-
- // ... but never grow by less than requested, or 1K, whichever is greater
- if (min_growth < 1024)
- min_growth = 1024;
- if (growth < min_growth)
- growth = min_growth;
-
- // Allocate the new m_buffer and migrate content
- long new_size = (m_buffer_end - m_buffer) + growth;
- char *new_buffer = (char *)malloc(new_size);
- memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer);
- if (m_owns_buffer)
- free(m_buffer);
- m_owns_buffer = true;
-
- // Update references to the new buffer
- m_write_ptr = new_buffer + (m_write_ptr - m_buffer);
- m_buffer = new_buffer;
- m_buffer_end = m_buffer + new_size;
- }
-
- void GrowRewriteRanges() {
- // By default, double the size of the array
- int growth = m_rewrite_ranges_size;
-
- // Apply reasonable minimum and maximum sizes for growth
- if (growth > 128)
- growth = 128;
- if (growth < 16)
- growth = 16;
-
- // Allocate the new array and migrate content
- int bytes = (m_rewrite_ranges_size + growth) * sizeof(BufferRange);
- BufferRange *new_ranges = (BufferRange *)malloc(bytes);
- for (int index = 0; index < m_next_substitute_index; index++) {
- new_ranges[index] = m_rewrite_ranges[index];
- }
- for (int index = m_rewrite_ranges_size - 1;
- index > m_next_template_arg_index; index--) {
- new_ranges[index + growth] = m_rewrite_ranges[index];
- }
- if (m_owns_m_rewrite_ranges)
- free(m_rewrite_ranges);
- m_owns_m_rewrite_ranges = true;
-
- // Update references to the new array
- m_rewrite_ranges = new_ranges;
- m_rewrite_ranges_size += growth;
- m_next_template_arg_index += growth;
- }
-
- //----------------------------------------------------
- // Range and state management
- //----------------------------------------------------
-
- int GetStartCookie() { return (int)(m_write_ptr - m_buffer); }
-
- BufferRange EndRange(int start_cookie) {
- return {start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie))};
- }
-
- void ReorderRange(BufferRange source_range, int insertion_point_cookie) {
- // Ensure there's room the preserve the source range
- if (m_write_ptr + source_range.length > m_buffer_end) {
- GrowBuffer(m_write_ptr + source_range.length - m_buffer_end);
- }
-
- // Reorder the content
- memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length);
- memmove(m_buffer + insertion_point_cookie + source_range.length,
- m_buffer + insertion_point_cookie,
- source_range.offset - insertion_point_cookie);
- memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length);
-
- // Fix up rewritable ranges, covering both substitutions and templates
- int index = 0;
- while (true) {
- if (index == m_next_substitute_index)
- index = m_next_template_arg_index + 1;
- if (index == m_rewrite_ranges_size)
- break;
-
- // Affected ranges are either shuffled forward when after the insertion
- // but before the source, or backward when inside the source
- int candidate_offset = m_rewrite_ranges[index].offset;
- if (candidate_offset >= insertion_point_cookie) {
- if (candidate_offset < source_range.offset) {
- m_rewrite_ranges[index].offset += source_range.length;
- } else if (candidate_offset >= source_range.offset) {
- m_rewrite_ranges[index].offset -=
- (source_range.offset - insertion_point_cookie);
- }
- }
- ++index;
- }
- }
-
- void EndSubstitution(int start_cookie) {
- if (m_next_substitute_index == m_next_template_arg_index)
- GrowRewriteRanges();
-
- int index = m_next_substitute_index++;
- m_rewrite_ranges[index] = EndRange(start_cookie);
-#ifdef DEBUG_SUBSTITUTIONS
- printf("Saved substitution # %d = %.*s\n", index,
- m_rewrite_ranges[index].length, m_buffer + start_cookie);
-#endif
- }
-
- void EndTemplateArg(int start_cookie) {
- if (m_next_substitute_index == m_next_template_arg_index)
- GrowRewriteRanges();
-
- int index = m_next_template_arg_index--;
- m_rewrite_ranges[index] = EndRange(start_cookie);
-#ifdef DEBUG_TEMPLATE_ARGS
- printf("Saved template arg # %d = %.*s\n",
- m_rewrite_ranges_size - index - 1, m_rewrite_ranges[index].length,
- m_buffer + start_cookie);
-#endif
- }
-
- void ResetTemplateArgs() {
- // TODO: this works, but is it the right thing to do?
- // Should we push/pop somehow at the call sites?
- m_next_template_arg_index = m_rewrite_ranges_size - 1;
- }
-
- //----------------------------------------------------
- // Write methods
- //
- // Appends content to the existing output buffer
- //----------------------------------------------------
-
- void Write(char character) {
- if (m_write_ptr == m_buffer_end)
- GrowBuffer();
- *m_write_ptr++ = character;
- }
-
- void Write(const char *content) { Write(content, strlen(content)); }
-
- void Write(const char *content, long content_length) {
- char *end_m_write_ptr = m_write_ptr + content_length;
- if (end_m_write_ptr > m_buffer_end) {
- if (content >= m_buffer && content < m_buffer_end) {
- long offset = content - m_buffer;
- GrowBuffer(end_m_write_ptr - m_buffer_end);
- content = m_buffer + offset;
- } else {
- GrowBuffer(end_m_write_ptr - m_buffer_end);
- }
- end_m_write_ptr = m_write_ptr + content_length;
- }
- memcpy(m_write_ptr, content, content_length);
- m_write_ptr = end_m_write_ptr;
- }
-#define WRITE(x) Write(x, sizeof(x) - 1)
-
- void WriteTemplateStart() { Write('<'); }
-
- void WriteTemplateEnd() {
- // Put a space between terminal > characters when nesting templates
- if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>')
- WRITE(" >");
- else
- Write('>');
- }
-
- void WriteCommaSpace() { WRITE(", "); }
-
- void WriteNamespaceSeparator() { WRITE("::"); }
-
- void WriteStdPrefix() { WRITE("std::"); }
-
- void WriteQualifiers(int qualifiers, bool space_before_reference = true) {
- if (qualifiers & QualifierPointer)
- Write('*');
- if (qualifiers & QualifierConst)
- WRITE(" const");
- if (qualifiers & QualifierVolatile)
- WRITE(" volatile");
- if (qualifiers & QualifierRestrict)
- WRITE(" restrict");
- if (qualifiers & QualifierReference) {
- if (space_before_reference)
- WRITE(" &");
- else
- Write('&');
- }
- if (qualifiers & QualifierRValueReference) {
- if (space_before_reference)
- WRITE(" &&");
- else
- WRITE("&&");
- }
- }
-
- //----------------------------------------------------
- // Rewrite methods
- //
- // Write another copy of content already present earlier in the output buffer
- //----------------------------------------------------
-
- void RewriteRange(BufferRange range) {
- Write(m_buffer + range.offset, range.length);
- }
-
- bool RewriteSubstitution(int index) {
- if (index < 0 || index >= m_next_substitute_index) {
-#ifdef DEBUG_FAILURES
- printf("*** Invalid substitution #%d\n", index);
-#endif
- return false;
- }
- RewriteRange(m_rewrite_ranges[index]);
- return true;
- }
-
- bool RewriteTemplateArg(int template_index) {
- int index = m_rewrite_ranges_size - 1 - template_index;
- if (template_index < 0 || index <= m_next_template_arg_index) {
-#ifdef DEBUG_FAILURES
- printf("*** Invalid template arg reference #%d\n", template_index);
-#endif
- return false;
- }
- RewriteRange(m_rewrite_ranges[index]);
- return true;
- }
-
- //----------------------------------------------------
- // TryParse methods
- //
- // Provide information with return values instead of writing to the output
- // buffer
- //
- // Values indicating failure guarantee that the pre- call m_read_ptr is
- // unchanged
- //----------------------------------------------------
-
- int TryParseNumber() {
- unsigned char digit = *m_read_ptr - '0';
- if (digit > 9)
- return -1;
-
- int count = digit;
- while (true) {
- digit = *++m_read_ptr - '0';
- if (digit > 9)
- break;
-
- count = count * 10 + digit;
- }
- return count;
- }
-
- int TryParseBase36Number() {
- char digit = *m_read_ptr;
- int count;
- if (digit >= '0' && digit <= '9')
- count = digit -= '0';
- else if (digit >= 'A' && digit <= 'Z')
- count = digit -= ('A' - 10);
- else
- return -1;
-
- while (true) {
- digit = *++m_read_ptr;
- if (digit >= '0' && digit <= '9')
- digit -= '0';
- else if (digit >= 'A' && digit <= 'Z')
- digit -= ('A' - 10);
- else
- break;
-
- count = count * 36 + digit;
- }
- return count;
- }
-
- // <builtin-type> ::= v # void
- // ::= w # wchar_t
- // ::= b # bool
- // ::= c # char
- // ::= a # signed char
- // ::= h # unsigned char
- // ::= s # short
- // ::= t # unsigned short
- // ::= i # int
- // ::= j # unsigned int
- // ::= l # long
- // ::= m # unsigned long
- // ::= x # long long, __int64
- // ::= y # unsigned long long, __int64
- // ::= n # __int128
- // ::= o # unsigned __int128
- // ::= f # float
- // ::= d # double
- // ::= e # long double, __float80
- // ::= g # __float128
- // ::= z # ellipsis
- // ::= Dd # IEEE 754r decimal floating point (64 bits)
- // ::= De # IEEE 754r decimal floating point (128 bits)
- // ::= Df # IEEE 754r decimal floating point (32 bits)
- // ::= Dh # IEEE 754r half-precision floating point (16 bits)
- // ::= Di # char32_t
- // ::= Ds # char16_t
- // ::= Da # auto (in dependent new-expressions)
- // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))
- // ::= u <source-name> # vendor extended type
-
- const char *TryParseBuiltinType() {
- if (m_builtins_hook)
- m_builtins_hook(m_read_ptr);
-
- switch (*m_read_ptr++) {
- case 'v':
- return "void";
- case 'w':
- return "wchar_t";
- case 'b':
- return "bool";
- case 'c':
- return "char";
- case 'a':
- return "signed char";
- case 'h':
- return "unsigned char";
- case 's':
- return "short";
- case 't':
- return "unsigned short";
- case 'i':
- return "int";
- case 'j':
- return "unsigned int";
- case 'l':
- return "long";
- case 'm':
- return "unsigned long";
- case 'x':
- return "long long";
- case 'y':
- return "unsigned long long";
- case 'n':
- return "__int128";
- case 'o':
- return "unsigned __int128";
- case 'f':
- return "float";
- case 'd':
- return "double";
- case 'e':
- return "long double";
- case 'g':
- return "__float128";
- case 'z':
- return "...";
- case 'D': {
- switch (*m_read_ptr++) {
- case 'd':
- return "decimal64";
- case 'e':
- return "decimal128";
- case 'f':
- return "decimal32";
- case 'h':
- return "decimal16";
- case 'i':
- return "char32_t";
- case 's':
- return "char16_t";
- case 'a':
- return "auto";
- case 'c':
- return "decltype(auto)";
- case 'n':
- return "std::nullptr_t";
- default:
- --m_read_ptr;
- }
- }
- }
- --m_read_ptr;
- return nullptr;
- }
-
- // <operator-name>
- // ::= aa # &&
- // ::= ad # & (unary)
- // ::= an # &
- // ::= aN # &=
- // ::= aS # =
- // ::= cl # ()
- // ::= cm # ,
- // ::= co # ~
- // ::= da # delete[]
- // ::= de # * (unary)
- // ::= dl # delete
- // ::= dv # /
- // ::= dV # /=
- // ::= eo # ^
- // ::= eO # ^=
- // ::= eq # ==
- // ::= ge # >=
- // ::= gt # >
- // ::= ix # []
- // ::= le # <=
- // ::= ls # <<
- // ::= lS # <<=
- // ::= lt # <
- // ::= mi # -
- // ::= mI # -=
- // ::= ml # *
- // ::= mL # *=
- // ::= mm # -- (postfix in <expression> context)
- // ::= na # new[]
- // ::= ne # !=
- // ::= ng # - (unary)
- // ::= nt # !
- // ::= nw # new
- // ::= oo # ||
- // ::= or # |
- // ::= oR # |=
- // ::= pm # ->*
- // ::= pl # +
- // ::= pL # +=
- // ::= pp # ++ (postfix in <expression> context)
- // ::= ps # + (unary)
- // ::= pt # ->
- // ::= qu # ?
- // ::= rm # %
- // ::= rM # %=
- // ::= rs # >>
- // ::= rS # >>=
- // ::= cv <type> # (cast)
- // ::= v <digit> <source-name> # vendor extended
- // operator
-
- Operator TryParseOperator() {
- switch (*m_read_ptr++) {
- case 'a':
- switch (*m_read_ptr++) {
- case 'a':
- return {"&&", OperatorKind::Binary};
- case 'd':
- return {"&", OperatorKind::Unary};
- case 'n':
- return {"&", OperatorKind::Binary};
- case 'N':
- return {"&=", OperatorKind::Binary};
- case 'S':
- return {"=", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'c':
- switch (*m_read_ptr++) {
- case 'l':
- return {"()", OperatorKind::Other};
- case 'm':
- return {",", OperatorKind::Other};
- case 'o':
- return {"~", OperatorKind::Unary};
- case 'v':
- return {nullptr, OperatorKind::ConversionOperator};
- }
- --m_read_ptr;
- break;
- case 'd':
- switch (*m_read_ptr++) {
- case 'a':
- return {" delete[]", OperatorKind::Other};
- case 'e':
- return {"*", OperatorKind::Unary};
- case 'l':
- return {" delete", OperatorKind::Other};
- case 'v':
- return {"/", OperatorKind::Binary};
- case 'V':
- return {"/=", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'e':
- switch (*m_read_ptr++) {
- case 'o':
- return {"^", OperatorKind::Binary};
- case 'O':
- return {"^=", OperatorKind::Binary};
- case 'q':
- return {"==", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'g':
- switch (*m_read_ptr++) {
- case 'e':
- return {">=", OperatorKind::Binary};
- case 't':
- return {">", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'i':
- switch (*m_read_ptr++) {
- case 'x':
- return {"[]", OperatorKind::Other};
- }
- --m_read_ptr;
- break;
- case 'l':
- switch (*m_read_ptr++) {
- case 'e':
- return {"<=", OperatorKind::Binary};
- case 's':
- return {"<<", OperatorKind::Binary};
- case 'S':
- return {"<<=", OperatorKind::Binary};
- case 't':
- return {"<", OperatorKind::Binary};
- // case 'i': return { "?", OperatorKind::Binary };
- }
- --m_read_ptr;
- break;
- case 'm':
- switch (*m_read_ptr++) {
- case 'i':
- return {"-", OperatorKind::Binary};
- case 'I':
- return {"-=", OperatorKind::Binary};
- case 'l':
- return {"*", OperatorKind::Binary};
- case 'L':
- return {"*=", OperatorKind::Binary};
- case 'm':
- return {"--", OperatorKind::Postfix};
- }
- --m_read_ptr;
- break;
- case 'n':
- switch (*m_read_ptr++) {
- case 'a':
- return {" new[]", OperatorKind::Other};
- case 'e':
- return {"!=", OperatorKind::Binary};
- case 'g':
- return {"-", OperatorKind::Unary};
- case 't':
- return {"!", OperatorKind::Unary};
- case 'w':
- return {" new", OperatorKind::Other};
- }
- --m_read_ptr;
- break;
- case 'o':
- switch (*m_read_ptr++) {
- case 'o':
- return {"||", OperatorKind::Binary};
- case 'r':
- return {"|", OperatorKind::Binary};
- case 'R':
- return {"|=", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'p':
- switch (*m_read_ptr++) {
- case 'm':
- return {"->*", OperatorKind::Binary};
- case 's':
- return {"+", OperatorKind::Unary};
- case 'l':
- return {"+", OperatorKind::Binary};
- case 'L':
- return {"+=", OperatorKind::Binary};
- case 'p':
- return {"++", OperatorKind::Postfix};
- case 't':
- return {"->", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'q':
- switch (*m_read_ptr++) {
- case 'u':
- return {"?", OperatorKind::Ternary};
- }
- --m_read_ptr;
- break;
- case 'r':
- switch (*m_read_ptr++) {
- case 'm':
- return {"%", OperatorKind::Binary};
- case 'M':
- return {"%=", OperatorKind::Binary};
- case 's':
- return {">>", OperatorKind::Binary};
- case 'S':
- return {">=", OperatorKind::Binary};
- }
- --m_read_ptr;
- break;
- case 'v':
- char digit = *m_read_ptr;
- if (digit >= '0' && digit <= '9') {
- m_read_ptr++;
- return {nullptr, OperatorKind::Vendor};
- }
- --m_read_ptr;
- break;
- }
- --m_read_ptr;
- return {nullptr, OperatorKind::NoMatch};
- }
-
- // <CV-qualifiers> ::= [r] [V] [K]
- // <ref-qualifier> ::= R # & ref-qualifier <ref-qualifier>
- // ::= O # && ref-qualifier
-
- int TryParseQualifiers(bool allow_cv, bool allow_ro) {
- int qualifiers = QualifierNone;
- char next = *m_read_ptr;
- if (allow_cv) {
- if (next == 'r') // restrict
- {
- qualifiers |= QualifierRestrict;
- next = *++m_read_ptr;
- }
- if (next == 'V') // volatile
- {
- qualifiers |= QualifierVolatile;
- next = *++m_read_ptr;
- }
- if (next == 'K') // const
- {
- qualifiers |= QualifierConst;
- next = *++m_read_ptr;
- }
- }
- if (allow_ro) {
- if (next == 'R') {
- ++m_read_ptr;
- qualifiers |= QualifierReference;
- } else if (next == 'O') {
- ++m_read_ptr;
- qualifiers |= QualifierRValueReference;
- }
- }
- return qualifiers;
- }
-
- // <discriminator> := _ <non-negative number> # when number < 10
- // := __ <non-negative number> _ # when number >= 10
- // extension := decimal-digit+
-
- int TryParseDiscriminator() {
- const char *discriminator_start = m_read_ptr;
-
- // Test the extension first, since it's what Clang uses
- int discriminator_value = TryParseNumber();
- if (discriminator_value != -1)
- return discriminator_value;
-
- char next = *m_read_ptr;
- if (next == '_') {
- next = *++m_read_ptr;
- if (next == '_') {
- ++m_read_ptr;
- discriminator_value = TryParseNumber();
- if (discriminator_value != -1 && *m_read_ptr++ != '_') {
- return discriminator_value;
- }
- } else if (next >= '0' && next <= '9') {
- ++m_read_ptr;
- return next - '0';
- }
- }
-
- // Not a valid discriminator
- m_read_ptr = discriminator_start;
- return -1;
- }
-
- //----------------------------------------------------
- // Parse methods
- //
- // Consume input starting from m_read_ptr and produce buffered output at
- // m_write_ptr
- //
- // Failures return false and may leave m_read_ptr in an indeterminate state
- //----------------------------------------------------
-
- bool Parse(char character) {
- if (*m_read_ptr++ == character)
- return true;
-#ifdef DEBUG_FAILURES
- printf("*** Expected '%c'\n", character);
-#endif
- return false;
- }
-
- // <number> ::= [n] <non-negative decimal integer>
-
- bool ParseNumber(bool allow_negative = false) {
- if (allow_negative && *m_read_ptr == 'n') {
- Write('-');
- ++m_read_ptr;
- }
- const char *before_digits = m_read_ptr;
- while (true) {
- unsigned char digit = *m_read_ptr - '0';
- if (digit > 9)
- break;
- ++m_read_ptr;
- }
- if (int digit_count = (int)(m_read_ptr - before_digits)) {
- Write(before_digits, digit_count);
- return true;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Expected number\n");
-#endif
- return false;
- }
-
- // <substitution> ::= S <seq-id> _
- // ::= S_
- // <substitution> ::= Sa # ::std::allocator <substitution> ::= Sb #
- // ::std::basic_string <substitution> ::= Ss # ::std::basic_string < char,
- // ::std::char_traits<char>,
- // ::std::allocator<char> >
- // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char>
- // > <substitution> ::= So # ::std::basic_ostream<char,
- // std::char_traits<char> > <substitution> ::= Sd #
- // ::std::basic_iostream<char, std::char_traits<char> >
-
- bool ParseSubstitution() {
- const char *substitution;
- switch (*m_read_ptr) {
- case 'a':
- substitution = "std::allocator";
- break;
- case 'b':
- substitution = "std::basic_string";
- break;
- case 's':
- substitution = "std::string";
- break;
- case 'i':
- substitution = "std::istream";
- break;
- case 'o':
- substitution = "std::ostream";
- break;
- case 'd':
- substitution = "std::iostream";
- break;
- default:
- // A failed attempt to parse a number will return -1 which turns out to be
- // perfect here as S_ is the first substitution, S0_ the next and so
- // forth
- int substitution_index = TryParseBase36Number();
- if (*m_read_ptr++ != '_') {
-#ifdef DEBUG_FAILURES
- printf("*** Expected terminal _ in substitution\n");
-#endif
- return false;
- }
- return RewriteSubstitution(substitution_index + 1);
- }
- Write(substitution);
- ++m_read_ptr;
- return true;
- }
-
- // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E
- //
- // <bare-function-type> ::= <signature type>+ # types are possible
- // return type, then parameter types
-
- bool ParseFunctionType(int inner_qualifiers = QualifierNone) {
-#ifdef DEBUG_FAILURES
- printf("*** Function types not supported\n");
-#endif
- // TODO: first steps toward an implementation follow, but they're far
- // from complete. Function types tend to bracket other types eg: int (*)()
- // when used as the type for "name" becomes int (*name)(). This makes
- // substitution et al ... interesting.
- return false;
-
-#if 0 // TODO
- if (*m_read_ptr == 'Y')
- ++m_read_ptr;
-
- int return_type_start_cookie = GetStartCookie();
- if (!ParseType())
- return false;
- Write(' ');
-
- int insert_cookie = GetStartCookie();
- Write('(');
- bool first_param = true;
- int qualifiers = QualifierNone;
- while (true)
- {
- switch (*m_read_ptr)
- {
- case 'E':
- ++m_read_ptr;
- Write(')');
- break;
- case 'v':
- ++m_read_ptr;
- continue;
- case 'R':
- case 'O':
- if (*(m_read_ptr + 1) == 'E')
- {
- qualifiers = TryParseQualifiers (false, true);
- Parse('E');
- break;
- }
- // fallthrough
- default:
- {
- if (first_param)
- first_param = false;
- else WriteCommaSpace();
-
- if (!ParseType())
- return false;
- continue;
- }
- }
- break;
- }
-
- if (qualifiers)
- {
- WriteQualifiers (qualifiers);
- EndSubstitution (return_type_start_cookie);
- }
-
- if (inner_qualifiers)
- {
- int qualifier_start_cookie = GetStartCookie();
- Write ('(');
- WriteQualifiers (inner_qualifiers);
- Write (')');
- ReorderRange (EndRange (qualifier_start_cookie), insert_cookie);
- }
- return true;
-#endif // TODO
- }
-
- // <array-type> ::= A <positive dimension number> _ <element type>
- // ::= A [<dimension expression>] _ <element type>
-
- bool ParseArrayType(int qualifiers = QualifierNone) {
-#ifdef DEBUG_FAILURES
- printf("*** Array type unsupported\n");
-#endif
- // TODO: We fail horribly when recalling these as substitutions or
- // templates and trying to constify them eg:
- // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_
- //
- // TODO: Chances are we don't do any better with references and pointers
- // that should be type (&) [] instead of type & []
-
- return false;
-
-#if 0 // TODO
- if (*m_read_ptr == '_')
- {
- ++m_read_ptr;
- if (!ParseType())
- return false;
- if (qualifiers)
- WriteQualifiers(qualifiers);
- WRITE(" []");
- return true;
- }
- else
- {
- const char *before_digits = m_read_ptr;
- if (TryParseNumber() != -1)
- {
- const char *after_digits = m_read_ptr;
- if (!Parse('_'))
- return false;
- if (!ParseType())
- return false;
- if (qualifiers)
- WriteQualifiers(qualifiers);
- Write(' ');
- Write('[');
- Write(before_digits, after_digits - before_digits);
- }
- else
- {
- int type_insertion_cookie = GetStartCookie();
- if (!ParseExpression())
- return false;
- if (!Parse('_'))
- return false;
-
- int type_start_cookie = GetStartCookie();
- if (!ParseType())
- return false;
- if (qualifiers)
- WriteQualifiers(qualifiers);
- Write(' ');
- Write('[');
- ReorderRange (EndRange (type_start_cookie), type_insertion_cookie);
- }
- Write(']');
- return true;
- }
-#endif // TODO
- }
-
- // <pointer-to-member-type> ::= M <class type> <member type>
-
- // TODO: Determine how to handle pointers to function members correctly,
- // currently not an issue because we don't have function types at all...
- bool ParsePointerToMemberType() {
- int insertion_cookie = GetStartCookie();
- Write(' ');
- if (!ParseType())
- return false;
- WRITE("::*");
-
- int type_cookie = GetStartCookie();
- if (!ParseType())
- return false;
- ReorderRange(EndRange(type_cookie), insertion_cookie);
- return true;
- }
-
- // <template-param> ::= T_ # first template parameter
- // ::= T <parameter-2 non-negative number> _
-
- bool ParseTemplateParam() {
- int count = TryParseNumber();
- if (!Parse('_'))
- return false;
-
- // When no number is present we get -1, which is convenient since T_ is the
- // zeroth element T0_ is element 1, and so on
- return RewriteTemplateArg(count + 1);
- }
-
- // <vector-type>
- // Dv <dimension number> _ <vector type>
- bool TryParseVectorType() {
- const int dimension = TryParseNumber();
- if (dimension == -1)
- return false;
-
- if (*m_read_ptr++ != '_')
- return false;
-
- char vec_dimens[32] = {'\0'};
- ::snprintf(vec_dimens, sizeof vec_dimens - 1, " __vector(%d)", dimension);
- ParseType();
- Write(vec_dimens);
- return true;
- }
-
- // <type> ::= <builtin-type>
- // ::= <function-type>
- // ::= <class-enum-type>
- // ::= <array-type>
- // ::= <pointer-to-member-type>
- // ::= <template-param>
- // ::= <template-template-param> <template-args>
- // ::= <decltype>
- // ::= <substitution>
- // ::= <CV-qualifiers> <type>
- // ::= P <type> # pointer-to
- // ::= R <type> # reference-to
- // ::= O <type> # rvalue reference-to (C++0x)
- // ::= C <type> # complex pair (C 2000)
- // ::= G <type> # imaginary (C 2000)
- // ::= Dp <type> # pack expansion (C++0x)
- // ::= U <source-name> <type> # vendor extended type qualifier
- // extension := U <objc-name> <objc-type> # objc-type<identifier> extension
- // := <vector-type> # <vector-type> starts with Dv
-
- // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 +
- // <number of digits in k1> + k1 <objc-type> := <source-name> #
- // PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-
- // name>
-
- bool ParseType() {
-#ifdef DEBUG_FAILURES
- const char *failed_type = m_read_ptr;
-#endif
- int type_start_cookie = GetStartCookie();
- bool suppress_substitution = false;
-
- int qualifiers = TryParseQualifiers(true, false);
- switch (*m_read_ptr) {
- case 'D':
- ++m_read_ptr;
- switch (*m_read_ptr++) {
- case 'p':
- if (!ParseType())
- return false;
- break;
- case 'v':
- if (!TryParseVectorType())
- return false;
- break;
- case 'T':
- case 't':
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported type: %.3s\n", failed_type);
-#endif
- return false;
- }
- break;
- case 'T':
- ++m_read_ptr;
- if (!ParseTemplateParam())
- return false;
- break;
- case 'M':
- ++m_read_ptr;
- if (!ParsePointerToMemberType())
- return false;
- break;
- case 'A':
- ++m_read_ptr;
- if (!ParseArrayType())
- return false;
- break;
- case 'F':
- ++m_read_ptr;
- if (!ParseFunctionType())
- return false;
- break;
- case 'S':
- if (*++m_read_ptr == 't') {
- ++m_read_ptr;
- WriteStdPrefix();
- if (!ParseName())
- return false;
- } else {
- suppress_substitution = true;
- if (!ParseSubstitution())
- return false;
- }
- break;
- case 'P': {
- switch (*++m_read_ptr) {
- case 'F':
- ++m_read_ptr;
- if (!ParseFunctionType(QualifierPointer))
- return false;
- break;
- default:
- if (!ParseType())
- return false;
- Write('*');
- break;
- }
- break;
- }
- case 'R': {
- ++m_read_ptr;
- if (!ParseType())
- return false;
- Write('&');
- break;
- }
- case 'O': {
- ++m_read_ptr;
- if (!ParseType())
- return false;
- Write('&');
- Write('&');
- break;
- }
- case 'C':
- case 'G':
- case 'U':
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported type: %.3s\n", failed_type);
-#endif
- return false;
- // Test for common cases to avoid TryParseBuiltinType() overhead
- case 'N':
- case 'Z':
- case 'L':
- if (!ParseName())
- return false;
- break;
- default:
- if (const char *builtin = TryParseBuiltinType()) {
- Write(builtin);
- suppress_substitution = true;
- } else {
- if (!ParseName())
- return false;
- }
- break;
- }
-
- // Allow base substitutions to be suppressed, but always record
- // substitutions for the qualified variant
- if (!suppress_substitution)
- EndSubstitution(type_start_cookie);
- if (qualifiers) {
- WriteQualifiers(qualifiers, false);
- EndSubstitution(type_start_cookie);
- }
- return true;
- }
-
- // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _
- // ::= <closure-type-name>
- //
- // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _
- //
- // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda
- // has no parameters
-
- bool ParseUnnamedTypeName(NameState &name_state) {
- switch (*m_read_ptr++) {
- case 't': {
- int cookie = GetStartCookie();
- WRITE("'unnamed");
- const char *before_digits = m_read_ptr;
- if (TryParseNumber() != -1)
- Write(before_digits, m_read_ptr - before_digits);
- if (!Parse('_'))
- return false;
- Write('\'');
- name_state.last_name_range = EndRange(cookie);
- return true;
- }
- case 'b': {
- int cookie = GetStartCookie();
- WRITE("'block");
- const char *before_digits = m_read_ptr;
- if (TryParseNumber() != -1)
- Write(before_digits, m_read_ptr - before_digits);
- if (!Parse('_'))
- return false;
- Write('\'');
- name_state.last_name_range = EndRange(cookie);
- return true;
- }
- case 'l':
-#ifdef DEBUG_FAILURES
- printf("*** Lambda type names unsupported\n");
-#endif
- return false;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2);
-#endif
- return false;
- }
-
- // <ctor-dtor-name> ::= C1 # complete object constructor
- // ::= C2 # base object constructor
- // ::= C3 # complete object allocating constructor
-
- bool ParseCtor(NameState &name_state) {
- char next = *m_read_ptr;
- if (next == '1' || next == '2' || next == '3' || next == '5') {
- RewriteRange(name_state.last_name_range);
- name_state.has_no_return_type = true;
- ++m_read_ptr;
- return true;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Broken constructor\n");
-#endif
- return false;
- }
-
- // <ctor-dtor-name> ::= D0 # deleting destructor
- // ::= D1 # complete object destructor
- // ::= D2 # base object destructor
-
- bool ParseDtor(NameState &name_state) {
- char next = *m_read_ptr;
- if (next == '0' || next == '1' || next == '2' || next == '5') {
- Write('~');
- RewriteRange(name_state.last_name_range);
- name_state.has_no_return_type = true;
- ++m_read_ptr;
- return true;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Broken destructor\n");
-#endif
- return false;
- }
-
- // See TryParseOperator()
-
- bool ParseOperatorName(NameState &name_state) {
-#ifdef DEBUG_FAILURES
- const char *operator_ptr = m_read_ptr;
-#endif
- Operator parsed_operator = TryParseOperator();
- if (parsed_operator.name) {
- WRITE("operator");
- Write(parsed_operator.name);
- return true;
- }
-
- // Handle special operators
- switch (parsed_operator.kind) {
- case OperatorKind::Vendor:
- WRITE("operator ");
- return ParseSourceName();
- case OperatorKind::ConversionOperator:
- ResetTemplateArgs();
- name_state.has_no_return_type = true;
- WRITE("operator ");
- return ParseType();
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unknown operator: %.2s\n", operator_ptr);
-#endif
- return false;
- }
- }
-
- // <source-name> ::= <positive length number> <identifier>
-
- bool ParseSourceName() {
- int count = TryParseNumber();
- if (count == -1) {
-#ifdef DEBUG_FAILURES
- printf("*** Malformed source name, missing length count\n");
-#endif
- return false;
- }
-
- const char *next_m_read_ptr = m_read_ptr + count;
- if (next_m_read_ptr > m_read_end) {
-#ifdef DEBUG_FAILURES
- printf("*** Malformed source name, premature termination\n");
-#endif
- return false;
- }
-
- if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0)
- WRITE("(anonymous namespace)");
- else
- Write(m_read_ptr, count);
-
- m_read_ptr = next_m_read_ptr;
- return true;
- }
-
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- // ::= <unnamed-type-name>
-
- bool ParseUnqualifiedName(NameState &name_state) {
- // Note that these are detected directly in ParseNestedName for performance
- // rather than switching on the same options twice
- char next = *m_read_ptr;
- switch (next) {
- case 'C':
- ++m_read_ptr;
- return ParseCtor(name_state);
- case 'D':
- ++m_read_ptr;
- return ParseDtor(name_state);
- case 'U':
- ++m_read_ptr;
- return ParseUnnamedTypeName(name_state);
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- int name_start_cookie = GetStartCookie();
- if (!ParseSourceName())
- return false;
- name_state.last_name_range = EndRange(name_start_cookie);
- return true;
- }
- default:
- return ParseOperatorName(name_state);
- };
- }
-
- // <unscoped-name> ::= <unqualified-name>
- // ::= St <unqualified-name> # ::std::
- // extension ::= StL<unqualified-name>
-
- bool ParseUnscopedName(NameState &name_state) {
- if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't') {
- WriteStdPrefix();
- if (*(m_read_ptr += 2) == 'L')
- ++m_read_ptr;
- }
- return ParseUnqualifiedName(name_state);
- }
-
- bool ParseIntegerLiteral(const char *prefix, const char *suffix,
- bool allow_negative) {
- if (prefix)
- Write(prefix);
- if (!ParseNumber(allow_negative))
- return false;
- if (suffix)
- Write(suffix);
- return Parse('E');
- }
-
- bool ParseBooleanLiteral() {
- switch (*m_read_ptr++) {
- case '0':
- WRITE("false");
- break;
- case '1':
- WRITE("true");
- break;
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Boolean literal not 0 or 1\n");
-#endif
- return false;
- }
- return Parse('E');
- }
-
- // <expr-primary> ::= L <type> <value number> E #
- // integer literal
- // ::= L <type> <value float> E #
- // floating literal
- // ::= L <string type> E #
- // string literal
- // ::= L <nullptr type> E #
- // nullptr literal (i.e., "LDnE")
- // ::= L <type> <real-part float> _ <imag-part float> E #
- // complex floating point literal (C 2000)
- // ::= L <mangled-name> E #
- // external name
-
- bool ParseExpressionPrimary() {
- switch (*m_read_ptr++) {
- case 'b':
- return ParseBooleanLiteral();
- case 'x':
- return ParseIntegerLiteral(nullptr, "ll", true);
- case 'l':
- return ParseIntegerLiteral(nullptr, "l", true);
- case 'i':
- return ParseIntegerLiteral(nullptr, nullptr, true);
- case 'n':
- return ParseIntegerLiteral("(__int128)", nullptr, true);
- case 'j':
- return ParseIntegerLiteral(nullptr, "u", false);
- case 'm':
- return ParseIntegerLiteral(nullptr, "ul", false);
- case 'y':
- return ParseIntegerLiteral(nullptr, "ull", false);
- case 'o':
- return ParseIntegerLiteral("(unsigned __int128)", nullptr, false);
- case '_':
- if (*m_read_ptr++ == 'Z') {
- if (!ParseEncoding())
- return false;
- return Parse('E');
- }
- --m_read_ptr;
- LLVM_FALLTHROUGH;
- case 'w':
- case 'c':
- case 'a':
- case 'h':
- case 's':
- case 't':
- case 'f':
- case 'd':
- case 'e':
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1);
-#endif
- return false;
- case 'T':
-// Invalid mangled name per
-// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html
-#ifdef DEBUG_FAILURES
- printf("*** Invalid primary expr encoding\n");
-#endif
- return false;
- default:
- --m_read_ptr;
- Write('(');
- if (!ParseType())
- return false;
- Write(')');
- if (!ParseNumber())
- return false;
- return Parse('E');
- }
- }
-
- // <unresolved-type> ::= <template-param>
- // ::= <decltype>
- // ::= <substitution>
-
- bool ParseUnresolvedType() {
- int type_start_cookie = GetStartCookie();
- switch (*m_read_ptr++) {
- case 'T':
- if (!ParseTemplateParam())
- return false;
- EndSubstitution(type_start_cookie);
- return true;
- case 'S': {
- if (*m_read_ptr != 't')
- return ParseSubstitution();
-
- ++m_read_ptr;
- WriteStdPrefix();
- NameState type_name = {};
- if (!ParseUnqualifiedName(type_name))
- return false;
- EndSubstitution(type_start_cookie);
- return true;
- }
- case 'D':
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1);
-#endif
- return false;
- }
- }
-
- // <base-unresolved-name> ::= <simple-id> #
- // unresolved name
- // extension ::= <operator-name> #
- // unresolved operator-function-id
- // extension ::= <operator-name> <template-args> #
- // unresolved operator template-id
- // ::= on <operator-name> #
- // unresolved operator-function-id
- // ::= on <operator-name> <template-args> #
- // unresolved operator template-id
- // ::= dn <destructor-name> #
- // destructor or pseudo-destructor;
- // #
- // e.g.
- // ~X
- // or
- // ~X<N-1>
-
- bool ParseBaseUnresolvedName() {
-#ifdef DEBUG_FAILURES
- printf("*** Base unresolved name unsupported\n");
-#endif
- return false;
- }
-
- // <unresolved-name>
- // extension ::= srN <unresolved-type> [<template-args>]
- // <unresolved-qualifier-level>* E <base-unresolved-name>
- // ::= [gs] <base-unresolved-name> # x
- // or (with "gs") ::x
- // ::= [gs] sr <unresolved-qualifier-level>+ E
- // <base-unresolved-name>
- // #
- // A::x,
- // N::y,
- // A<T>::z;
- // "gs"
- // means
- // leading
- // "::"
- // ::= sr <unresolved-type> <base-unresolved-name> #
- // T::x / decltype(p)::x
- // extension ::= sr <unresolved-type> <template-args>
- // <base-unresolved-name>
- // #
- // T::N::x
- // /decltype(p)::N::x
- // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+
- // E <base-unresolved-name>
-
- bool ParseUnresolvedName() {
-#ifdef DEBUG_FAILURES
- printf("*** Unresolved names not supported\n");
-#endif
- // TODO: grammar for all of this seems unclear...
- return false;
-
-#if 0 // TODO
- if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's')
- {
- m_read_ptr += 2;
- WriteNamespaceSeparator();
- }
-#endif // TODO
- }
-
- // <expression> ::= <unary operator-name> <expression>
- // ::= <binary operator-name> <expression> <expression>
- // ::= <ternary operator-name> <expression> <expression>
- // <expression>
- // ::= cl <expression>+ E #
- // call
- // ::= cv <type> <expression> #
- // conversion with one argument
- // ::= cv <type> _ <expression>* E #
- // conversion with a different number of arguments
- // ::= [gs] nw <expression>* _ <type> E # new
- // (expr-list) type
- // ::= [gs] nw <expression>* _ <type> <initializer> # new
- // (expr-list) type (init)
- // ::= [gs] na <expression>* _ <type> E #
- // new[] (expr-list) type
- // ::= [gs] na <expression>* _ <type> <initializer> #
- // new[] (expr-list) type (init)
- // ::= [gs] dl <expression> #
- // delete expression
- // ::= [gs] da <expression> #
- // delete[] expression
- // ::= pp_ <expression> #
- // prefix ++
- // ::= mm_ <expression> #
- // prefix --
- // ::= ti <type> #
- // typeid (type)
- // ::= te <expression> #
- // typeid (expression)
- // ::= dc <type> <expression> #
- // dynamic_cast<type> (expression)
- // ::= sc <type> <expression> #
- // static_cast<type> (expression)
- // ::= cc <type> <expression> #
- // const_cast<type> (expression)
- // ::= rc <type> <expression> #
- // reinterpret_cast<type> (expression)
- // ::= st <type> #
- // sizeof (a type)
- // ::= sz <expression> #
- // sizeof (an expression)
- // ::= at <type> #
- // alignof (a type)
- // ::= az <expression> #
- // alignof (an expression)
- // ::= nx <expression> #
- // noexcept (expression)
- // ::= <template-param>
- // ::= <function-param>
- // ::= dt <expression> <unresolved-name> #
- // expr.name
- // ::= pt <expression> <unresolved-name> #
- // expr->name
- // ::= ds <expression> <expression> #
- // expr.*expr
- // ::= sZ <template-param> #
- // size of a parameter pack
- // ::= sZ <function-param> #
- // size of a function parameter pack
- // ::= sp <expression> #
- // pack expansion
- // ::= tw <expression> #
- // throw expression
- // ::= tr #
- // throw with no operand (rethrow)
- // ::= <unresolved-name> #
- // f(p), N::f(p), ::f(p),
- // #
- // freestanding
- // dependent
- // name
- // (e.g.,
- // T::x),
- // #
- // objectless
- // nonstatic
- // member
- // reference
- // ::= <expr-primary>
-
- bool ParseExpression() {
- Operator expression_operator = TryParseOperator();
- switch (expression_operator.kind) {
- case OperatorKind::Unary:
- Write(expression_operator.name);
- Write('(');
- if (!ParseExpression())
- return false;
- Write(')');
- return true;
- case OperatorKind::Binary:
- if (!ParseExpression())
- return false;
- Write(expression_operator.name);
- return ParseExpression();
- case OperatorKind::Ternary:
- if (!ParseExpression())
- return false;
- Write('?');
- if (!ParseExpression())
- return false;
- Write(':');
- return ParseExpression();
- case OperatorKind::NoMatch:
- break;
- case OperatorKind::Other:
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported operator: %s\n", expression_operator.name);
-#endif
- return false;
- }
-
- switch (*m_read_ptr++) {
- case 'T':
- return ParseTemplateParam();
- case 'L':
- return ParseExpressionPrimary();
- case 's':
- if (*m_read_ptr++ == 'r')
- return ParseUnresolvedName();
- --m_read_ptr;
- LLVM_FALLTHROUGH;
- default:
- return ParseExpressionPrimary();
- }
- }
-
- // <template-arg> ::= <type> #
- // type or template
- // ::= X <expression> E #
- // expression
- // ::= <expr-primary> #
- // simple expressions
- // ::= J <template-arg>* E #
- // argument pack
- // ::= LZ <encoding> E #
- // extension
-
- bool ParseTemplateArg() {
- switch (*m_read_ptr) {
- case 'J':
-#ifdef DEBUG_FAILURES
- printf("*** Template argument packs unsupported\n");
-#endif
- return false;
- case 'X':
- ++m_read_ptr;
- if (!ParseExpression())
- return false;
- return Parse('E');
- case 'L':
- ++m_read_ptr;
- return ParseExpressionPrimary();
- default:
- return ParseType();
- }
- }
-
- // <template-args> ::= I <template-arg>* E
- // extension, the abi says <template-arg>+
-
- bool ParseTemplateArgs(bool record_template_args = false) {
- if (record_template_args)
- ResetTemplateArgs();
-
- bool first_arg = true;
- while (*m_read_ptr != 'E') {
- if (first_arg)
- first_arg = false;
- else
- WriteCommaSpace();
-
- int template_start_cookie = GetStartCookie();
- if (!ParseTemplateArg())
- return false;
- if (record_template_args)
- EndTemplateArg(template_start_cookie);
- }
- ++m_read_ptr;
- return true;
- }
-
- // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix>
- // <unqualified-name> E
- // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix>
- // <template-args> E
- //
- // <prefix> ::= <prefix> <unqualified-name>
- // ::= <template-prefix> <template-args>
- // ::= <template-param>
- // ::= <decltype>
- // ::= # empty
- // ::= <substitution>
- // ::= <prefix> <data-member-prefix>
- // extension ::= L
- //
- // <template-prefix> ::= <prefix> <template unqualified-name>
- // ::= <template-param>
- // ::= <substitution>
- //
- // <unqualified-name> ::= <operator-name>
- // ::= <ctor-dtor-name>
- // ::= <source-name>
- // ::= <unnamed-type-name>
-
- bool ParseNestedName(NameState &name_state,
- bool parse_discriminator = false) {
- int qualifiers = TryParseQualifiers(true, true);
- bool first_part = true;
- bool suppress_substitution = true;
- int name_start_cookie = GetStartCookie();
- while (true) {
- char next = *m_read_ptr;
- if (next == 'E') {
- ++m_read_ptr;
- break;
- }
-
- // Record a substitution candidate for all prefixes, but not the full
- // name
- if (suppress_substitution)
- suppress_substitution = false;
- else
- EndSubstitution(name_start_cookie);
-
- if (next == 'I') {
- ++m_read_ptr;
- name_state.is_last_generic = true;
- WriteTemplateStart();
- if (!ParseTemplateArgs(name_state.parse_function_params))
- return false;
- WriteTemplateEnd();
- continue;
- }
-
- if (first_part)
- first_part = false;
- else
- WriteNamespaceSeparator();
-
- name_state.is_last_generic = false;
- switch (next) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- int name_start_cookie = GetStartCookie();
- if (!ParseSourceName())
- return false;
- name_state.last_name_range = EndRange(name_start_cookie);
- continue;
- }
- case 'S':
- if (*++m_read_ptr == 't') {
- WriteStdPrefix();
- ++m_read_ptr;
- if (!ParseUnqualifiedName(name_state))
- return false;
- } else {
- if (!ParseSubstitution())
- return false;
- suppress_substitution = true;
- }
- continue;
- case 'T':
- ++m_read_ptr;
- if (!ParseTemplateParam())
- return false;
- continue;
- case 'C':
- ++m_read_ptr;
- if (!ParseCtor(name_state))
- return false;
- continue;
- case 'D': {
- switch (*(m_read_ptr + 1)) {
- case 't':
- case 'T':
-#ifdef DEBUG_FAILURES
- printf("*** Decltype unsupported\n");
-#endif
- return false;
- }
- ++m_read_ptr;
- if (!ParseDtor(name_state))
- return false;
- continue;
- }
- case 'U':
- ++m_read_ptr;
- if (!ParseUnnamedTypeName(name_state))
- return false;
- continue;
- case 'L':
- ++m_read_ptr;
- if (!ParseUnqualifiedName(name_state))
- return false;
- continue;
- default:
- if (!ParseOperatorName(name_state))
- return false;
- }
- }
-
- if (parse_discriminator)
- TryParseDiscriminator();
- if (name_state.parse_function_params &&
- !ParseFunctionArgs(name_state, name_start_cookie)) {
- return false;
- }
- if (qualifiers)
- WriteQualifiers(qualifiers);
- return true;
- }
-
- // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
- // := Z <function encoding> E s [<discriminator>]
- // := Z <function encoding> Ed [ <parameter number> ] _ <entity
- // name>
-
- bool ParseLocalName(bool parse_function_params) {
- if (!ParseEncoding())
- return false;
- if (!Parse('E'))
- return false;
-
- switch (*m_read_ptr) {
- case 's':
- ++m_read_ptr;
- TryParseDiscriminator(); // Optional and ignored
- WRITE("::string literal");
- break;
- case 'd':
- ++m_read_ptr;
- TryParseNumber(); // Optional and ignored
- if (!Parse('_'))
- return false;
- WriteNamespaceSeparator();
- if (!ParseName())
- return false;
- break;
- default:
- WriteNamespaceSeparator();
- if (!ParseName(parse_function_params, true))
- return false;
- TryParseDiscriminator(); // Optional and ignored
- }
- return true;
- }
-
- // <name> ::= <nested-name>
- // ::= <local-name>
- // ::= <unscoped-template-name> <template-args>
- // ::= <unscoped-name>
-
- // <unscoped-template-name> ::= <unscoped-name>
- // ::= <substitution>
-
- bool ParseName(bool parse_function_params = false,
- bool parse_discriminator = false) {
- NameState name_state = {parse_function_params, false, false, {0, 0}};
- int name_start_cookie = GetStartCookie();
-
- switch (*m_read_ptr) {
- case 'N':
- ++m_read_ptr;
- return ParseNestedName(name_state, parse_discriminator);
- case 'Z': {
- ++m_read_ptr;
- if (!ParseLocalName(parse_function_params))
- return false;
- break;
- }
- case 'L':
- ++m_read_ptr;
- LLVM_FALLTHROUGH;
- default: {
- if (!ParseUnscopedName(name_state))
- return false;
-
- if (*m_read_ptr == 'I') {
- EndSubstitution(name_start_cookie);
-
- ++m_read_ptr;
- name_state.is_last_generic = true;
- WriteTemplateStart();
- if (!ParseTemplateArgs(parse_function_params))
- return false;
- WriteTemplateEnd();
- }
- break;
- }
- }
- if (parse_discriminator)
- TryParseDiscriminator();
- if (parse_function_params &&
- !ParseFunctionArgs(name_state, name_start_cookie)) {
- return false;
- }
- return true;
- }
-
- // <call-offset> ::= h <nv-offset> _
- // ::= v <v-offset> _
- //
- // <nv-offset> ::= <offset number>
- // # non-virtual base override
- //
- // <v-offset> ::= <offset number> _ <virtual offset number>
- // # virtual base override, with vcall offset
-
- bool ParseCallOffset() {
- switch (*m_read_ptr++) {
- case 'h':
- if (*m_read_ptr == 'n')
- ++m_read_ptr;
- if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
- break;
- return true;
- case 'v':
- if (*m_read_ptr == 'n')
- ++m_read_ptr;
- if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
- break;
- if (*m_read_ptr == 'n')
- ++m_read_ptr;
- if (TryParseNumber() == -1 || *m_read_ptr++ != '_')
- break;
- return true;
- }
-#ifdef DEBUG_FAILURES
- printf("*** Malformed call offset\n");
-#endif
- return false;
- }
-
- // <special-name> ::= TV <type> # virtual table
- // ::= TT <type> # VTT structure (construction vtable index)
- // ::= TI <type> # typeinfo structure
- // ::= TS <type> # typeinfo name (null-terminated byte
- // string)
- // ::= Tc <call-offset> <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // # first call-offset is 'this' adjustment
- // # second call-offset is result adjustment
- // ::= T <call-offset> <base encoding>
- // # base is the nominal target function of thunk
- // extension ::= TC <first type> <number> _ <second type> # construction
- // vtable for second-in-first
-
- bool ParseSpecialNameT() {
- switch (*m_read_ptr++) {
- case 'V':
- WRITE("vtable for ");
- return ParseType();
- case 'T':
- WRITE("VTT for ");
- return ParseType();
- case 'I':
- WRITE("typeinfo for ");
- return ParseType();
- case 'S':
- WRITE("typeinfo name for ");
- return ParseType();
- case 'c':
- case 'C':
-#ifdef DEBUG_FAILURES
- printf("*** Unsupported thunk or construction vtable name: %.3s\n",
- m_read_ptr - 1);
-#endif
- return false;
- default:
- if (*--m_read_ptr == 'v') {
- WRITE("virtual thunk to ");
- } else {
- WRITE("non-virtual thunk to ");
- }
- if (!ParseCallOffset())
- return false;
- return ParseEncoding();
- }
- }
-
- // <special-name> ::= GV <object name> # Guard variable for one-time
- // initialization
- // # No <type>
- // extension ::= GR <object name> # reference temporary for object
-
- bool ParseSpecialNameG() {
- switch (*m_read_ptr++) {
- case 'V':
- WRITE("guard variable for ");
- if (!ParseName(true))
- return false;
- break;
- case 'R':
- WRITE("reference temporary for ");
- if (!ParseName(true))
- return false;
- break;
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unknown G encoding\n");
-#endif
- return false;
- }
- return true;
- }
-
- // <bare-function-type> ::= <signature type>+ # types are possible
- // return type, then parameter types
-
- bool ParseFunctionArgs(NameState &name_state, int return_insert_cookie) {
- char next = *m_read_ptr;
- if (next == 'E' || next == '\0' || next == '.')
- return true;
-
- // Clang has a bad habit of making unique manglings by just sticking
- // numbers on the end of a symbol, which is ambiguous with malformed source
- // name manglings
- const char *before_clang_uniquing_test = m_read_ptr;
- if (TryParseNumber()) {
- if (*m_read_ptr == '\0')
- return true;
- m_read_ptr = before_clang_uniquing_test;
- }
-
- if (name_state.is_last_generic && !name_state.has_no_return_type) {
- int return_type_start_cookie = GetStartCookie();
- if (!ParseType())
- return false;
- Write(' ');
- ReorderRange(EndRange(return_type_start_cookie), return_insert_cookie);
- }
-
- Write('(');
- bool first_param = true;
- while (true) {
- switch (*m_read_ptr) {
- case '\0':
- case 'E':
- case '.':
- break;
- case 'v':
- ++m_read_ptr;
- continue;
- case '_':
- // Not a formal part of the mangling specification, but clang emits
- // suffixes starting with _block_invoke
- if (strncmp(m_read_ptr, "_block_invoke", 13) == 0) {
- m_read_ptr += strlen(m_read_ptr);
- break;
- }
- LLVM_FALLTHROUGH;
- default:
- if (first_param)
- first_param = false;
- else
- WriteCommaSpace();
-
- if (!ParseType())
- return false;
- continue;
- }
- break;
- }
- Write(')');
- return true;
- }
-
- // <encoding> ::= <function name> <bare-function-type>
- // ::= <data name>
- // ::= <special-name>
-
- bool ParseEncoding() {
- switch (*m_read_ptr) {
- case 'T':
- ++m_read_ptr;
- if (!ParseSpecialNameT())
- return false;
- break;
- case 'G':
- ++m_read_ptr;
- if (!ParseSpecialNameG())
- return false;
- break;
- default:
- if (!ParseName(true))
- return false;
- break;
- }
- return true;
- }
-
- bool ParseMangling(const char *mangled_name, long mangled_name_length = 0) {
- if (!mangled_name_length)
- mangled_name_length = strlen(mangled_name);
- m_read_end = mangled_name + mangled_name_length;
- m_read_ptr = mangled_name;
- m_write_ptr = m_buffer;
- m_next_substitute_index = 0;
- m_next_template_arg_index = m_rewrite_ranges_size - 1;
-
- if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z') {
-#ifdef DEBUG_FAILURES
- printf("*** Missing _Z prefix\n");
-#endif
- return false;
- }
- if (!ParseEncoding())
- return false;
- switch (*m_read_ptr) {
- case '.':
- Write(' ');
- Write('(');
- Write(m_read_ptr, m_read_end - m_read_ptr);
- Write(')');
- LLVM_FALLTHROUGH;
- case '\0':
- return true;
- default:
-#ifdef DEBUG_FAILURES
- printf("*** Unparsed mangled content\n");
-#endif
- return false;
- }
- }
-
-private:
- // External scratch storage used during demanglings
-
- char *m_buffer;
- const char *m_buffer_end;
- BufferRange *m_rewrite_ranges;
- int m_rewrite_ranges_size;
- bool m_owns_buffer;
- bool m_owns_m_rewrite_ranges;
-
- // Internal state used during demangling
-
- const char *m_read_ptr;
- const char *m_read_end;
- char *m_write_ptr;
- int m_next_template_arg_index;
- int m_next_substitute_index;
- std::function<void(const char *s)> m_builtins_hook;
-};
-
-} // Anonymous namespace
-
-// Public entry points referenced from Mangled.cpp
-namespace lldb_private {
-char *FastDemangle(const char *mangled_name) {
- char buffer[16384];
- SymbolDemangler demangler(buffer, sizeof(buffer));
- return demangler.GetDemangledCopy(mangled_name);
-}
-
-char *FastDemangle(const char *mangled_name, size_t mangled_name_length,
- std::function<void(const char *s)> builtins_hook) {
- char buffer[16384];
- SymbolDemangler demangler(buffer, sizeof(buffer), builtins_hook);
- return demangler.GetDemangledCopy(mangled_name, mangled_name_length);
-}
-} // lldb_private namespace
diff --git a/source/Utility/FileSpec.cpp b/source/Utility/FileSpec.cpp
index b6952f7e3eb0..954968b7a8af 100644
--- a/source/Utility/FileSpec.cpp
+++ b/source/Utility/FileSpec.cpp
@@ -10,7 +10,6 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/Utility/TildeExpressionResolver.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -22,13 +21,14 @@
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
-#include <algorithm> // for replace, min, unique
-#include <system_error> // for error_code
-#include <vector> // for vector
+#include <algorithm>
+#include <system_error>
+#include <vector>
-#include <assert.h> // for assert
-#include <stdio.h> // for size_t, NULL, snpr...
-#include <string.h> // for strcmp
+#include <assert.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
using namespace lldb;
using namespace lldb_private;
@@ -66,38 +66,17 @@ void Denormalize(llvm::SmallVectorImpl<char> &path, FileSpec::Style style) {
} // end anonymous namespace
-void FileSpec::Resolve(llvm::SmallVectorImpl<char> &path) {
- if (path.empty())
- return;
-
- llvm::SmallString<32> Source(path.begin(), path.end());
- StandardTildeExpressionResolver Resolver;
- Resolver.ResolveFullPath(Source, path);
-
- // Save a copy of the original path that's passed in
- llvm::SmallString<128> original_path(path.begin(), path.end());
-
- llvm::sys::fs::make_absolute(path);
- if (!llvm::sys::fs::exists(path)) {
- path.clear();
- path.append(original_path.begin(), original_path.end());
- }
-}
-
FileSpec::FileSpec() : m_style(GetNativeStyle()) {}
//------------------------------------------------------------------
// Default constructor that can take an optional full path to a file on disk.
//------------------------------------------------------------------
-FileSpec::FileSpec(llvm::StringRef path, bool resolve_path, Style style)
- : m_style(style) {
- SetFile(path, resolve_path, style);
+FileSpec::FileSpec(llvm::StringRef path, Style style) : m_style(style) {
+ SetFile(path, style);
}
-FileSpec::FileSpec(llvm::StringRef path, bool resolve_path,
- const llvm::Triple &Triple)
- : FileSpec{path, resolve_path,
- Triple.isOSWindows() ? Style::windows : Style::posix} {}
+FileSpec::FileSpec(llvm::StringRef path, const llvm::Triple &Triple)
+ : FileSpec{path, Triple.isOSWindows() ? Style::windows : Style::posix} {}
//------------------------------------------------------------------
// Copy constructor
@@ -226,16 +205,14 @@ const FileSpec &FileSpec::operator=(const FileSpec &rhs) {
return *this;
}
-void FileSpec::SetFile(llvm::StringRef pathname, bool resolve) {
- SetFile(pathname, resolve, m_style);
-}
+void FileSpec::SetFile(llvm::StringRef pathname) { SetFile(pathname, m_style); }
//------------------------------------------------------------------
// Update the contents of this object with a new path. The path will be split
// up into a directory and filename and stored as uniqued string values for
// quick comparison and efficient memory usage.
//------------------------------------------------------------------
-void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, Style style) {
+void FileSpec::SetFile(llvm::StringRef pathname, Style style) {
m_filename.Clear();
m_directory.Clear();
m_is_resolved = false;
@@ -244,12 +221,7 @@ void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, Style style) {
if (pathname.empty())
return;
- llvm::SmallString<64> resolved(pathname);
-
- if (resolve) {
- FileSpec::Resolve(resolved);
- m_is_resolved = true;
- }
+ llvm::SmallString<128> resolved(pathname);
// Normalize the path by removing ".", ".." and other redundant components.
if (needsNormalization(resolved))
@@ -272,15 +244,14 @@ void FileSpec::SetFile(llvm::StringRef pathname, bool resolve, Style style) {
llvm::StringRef filename = llvm::sys::path::filename(resolved, m_style);
if(!filename.empty())
m_filename.SetString(filename);
+
llvm::StringRef directory = llvm::sys::path::parent_path(resolved, m_style);
if(!directory.empty())
m_directory.SetString(directory);
}
-void FileSpec::SetFile(llvm::StringRef path, bool resolve,
- const llvm::Triple &Triple) {
- return SetFile(path, resolve,
- Triple.isOSWindows() ? Style::windows : Style::posix);
+void FileSpec::SetFile(llvm::StringRef path, const llvm::Triple &Triple) {
+ return SetFile(path, Triple.isOSWindows() ? Style::windows : Style::posix);
}
//----------------------------------------------------------------------
@@ -315,49 +286,7 @@ bool FileSpec::FileEquals(const FileSpec &rhs) const {
// Equal to operator
//------------------------------------------------------------------
bool FileSpec::operator==(const FileSpec &rhs) const {
- if (!FileEquals(rhs))
- return false;
- if (DirectoryEquals(rhs))
- return true;
-
- // TODO: determine if we want to keep this code in here.
- // The code below was added to handle a case where we were trying to set a
- // file and line breakpoint and one path was resolved, and the other not and
- // the directory was in a mount point that resolved to a more complete path:
- // "/tmp/a.c" == "/private/tmp/a.c". I might end up pulling this out...
- if (IsResolved() && rhs.IsResolved()) {
- // Both paths are resolved, no need to look further...
- return false;
- }
-
- FileSpec resolved_lhs(*this);
-
- // If "this" isn't resolved, resolve it
- if (!IsResolved()) {
- if (resolved_lhs.ResolvePath()) {
- // This path wasn't resolved but now it is. Check if the resolved
- // directory is the same as our unresolved directory, and if so, we can
- // mark this object as resolved to avoid more future resolves
- m_is_resolved = (m_directory == resolved_lhs.m_directory);
- } else
- return false;
- }
-
- FileSpec resolved_rhs(rhs);
- if (!rhs.IsResolved()) {
- if (resolved_rhs.ResolvePath()) {
- // rhs's path wasn't resolved but now it is. Check if the resolved
- // directory is the same as rhs's unresolved directory, and if so, we can
- // mark this object as resolved to avoid more future resolves
- rhs.m_is_resolved = (rhs.m_directory == resolved_rhs.m_directory);
- } else
- return false;
- }
-
- // If we reach this point in the code we were able to resolve both paths and
- // since we only resolve the paths if the basenames are equal, then we can
- // just check if both directories are equal...
- return DirectoryEquals(rhs);
+ return FileEquals(rhs) && DirectoryEquals(rhs);
}
//------------------------------------------------------------------
@@ -452,78 +381,8 @@ void FileSpec::Dump(Stream *s) const {
}
}
-//------------------------------------------------------------------
-// Returns true if the file exists.
-//------------------------------------------------------------------
-bool FileSpec::Exists() const { return llvm::sys::fs::exists(GetPath()); }
-
-bool FileSpec::Readable() const {
- return GetPermissions() & llvm::sys::fs::perms::all_read;
-}
-
-bool FileSpec::ResolveExecutableLocation() {
- // CLEANUP: Use StringRef for string handling.
- if (!m_directory) {
- const char *file_cstr = m_filename.GetCString();
- if (file_cstr) {
- const std::string file_str(file_cstr);
- llvm::ErrorOr<std::string> error_or_path =
- llvm::sys::findProgramByName(file_str);
- if (!error_or_path)
- return false;
- std::string path = error_or_path.get();
- llvm::StringRef dir_ref = llvm::sys::path::parent_path(path);
- if (!dir_ref.empty()) {
- // FindProgramByName returns "." if it can't find the file.
- if (strcmp(".", dir_ref.data()) == 0)
- return false;
-
- m_directory.SetCString(dir_ref.data());
- if (Exists())
- return true;
- else {
- // If FindProgramByName found the file, it returns the directory +
- // filename in its return results. We need to separate them.
- FileSpec tmp_file(dir_ref.data(), false);
- if (tmp_file.Exists()) {
- m_directory = tmp_file.m_directory;
- return true;
- }
- }
- }
- }
- }
-
- return false;
-}
-
-bool FileSpec::ResolvePath() {
- if (m_is_resolved)
- return true; // We have already resolved this path
-
- // SetFile(...) will set m_is_resolved correctly if it can resolve the path
- SetFile(GetPath(false), true);
- return m_is_resolved;
-}
-
-uint64_t FileSpec::GetByteSize() const {
- uint64_t Size = 0;
- if (llvm::sys::fs::file_size(GetPath(), Size))
- return 0;
- return Size;
-}
-
FileSpec::Style FileSpec::GetPathStyle() const { return m_style; }
-uint32_t FileSpec::GetPermissions() const {
- namespace fs = llvm::sys::fs;
- fs::file_status st;
- if (fs::status(GetPath(), st, false))
- return fs::perms::perms_not_known;
-
- return st.permissions();
-}
-
//------------------------------------------------------------------
// Directory string get accessor.
//------------------------------------------------------------------
@@ -565,7 +424,7 @@ std::string FileSpec::GetPath(bool denormalize) const {
}
const char *FileSpec::GetCString(bool denormalize) const {
- return ConstString{GetPath(denormalize)}.AsCString(NULL);
+ return ConstString{GetPath(denormalize)}.AsCString(nullptr);
}
void FileSpec::GetPath(llvm::SmallVectorImpl<char> &path,
@@ -601,39 +460,6 @@ size_t FileSpec::MemorySize() const {
return m_filename.MemorySize() + m_directory.MemorySize();
}
-void FileSpec::EnumerateDirectory(llvm::StringRef dir_path,
- bool find_directories, bool find_files,
- bool find_other,
- EnumerateDirectoryCallbackType callback,
- void *callback_baton) {
- namespace fs = llvm::sys::fs;
- std::error_code EC;
- fs::recursive_directory_iterator Iter(dir_path, EC);
- fs::recursive_directory_iterator End;
- for (; Iter != End && !EC; Iter.increment(EC)) {
- const auto &Item = *Iter;
- llvm::ErrorOr<fs::basic_file_status> Status = Item.status();
- if (!Status)
- break;
- if (!find_files && fs::is_regular_file(*Status))
- continue;
- if (!find_directories && fs::is_directory(*Status))
- continue;
- if (!find_other && fs::is_other(*Status))
- continue;
-
- FileSpec Spec(Item.path(), false);
- auto Result = callback(callback_baton, Status->type(), Spec);
- if (Result == eEnumerateDirectoryResultQuit)
- return;
- if (Result == eEnumerateDirectoryResultNext) {
- // Default behavior is to recurse. Opt out if the callback doesn't want
- // this behavior.
- Iter.no_push();
- }
- }
-}
-
FileSpec
FileSpec::CopyByAppendingPathComponent(llvm::StringRef component) const {
FileSpec ret = *this;
@@ -645,7 +471,7 @@ FileSpec FileSpec::CopyByRemovingLastPathComponent() const {
llvm::SmallString<64> current_path;
GetPath(current_path, false);
if (llvm::sys::path::has_parent_path(current_path, m_style))
- return FileSpec(llvm::sys::path::parent_path(current_path, m_style), false,
+ return FileSpec(llvm::sys::path::parent_path(current_path, m_style),
m_style);
return *this;
}
@@ -663,7 +489,7 @@ void FileSpec::PrependPathComponent(llvm::StringRef component) {
llvm::sys::path::append(new_path,
llvm::sys::path::begin(current_path, m_style),
llvm::sys::path::end(current_path), m_style);
- SetFile(new_path, false, m_style);
+ SetFile(new_path, m_style);
}
void FileSpec::PrependPathComponent(const FileSpec &new_path) {
@@ -674,7 +500,7 @@ void FileSpec::AppendPathComponent(llvm::StringRef component) {
llvm::SmallString<64> current_path;
GetPath(current_path, false);
llvm::sys::path::append(current_path, m_style, component);
- SetFile(current_path, false, m_style);
+ SetFile(current_path, m_style);
}
void FileSpec::AppendPathComponent(const FileSpec &new_path) {
@@ -685,7 +511,7 @@ bool FileSpec::RemoveLastPathComponent() {
llvm::SmallString<64> current_path;
GetPath(current_path, false);
if (llvm::sys::path::has_parent_path(current_path, m_style)) {
- SetFile(llvm::sys::path::parent_path(current_path, m_style), false);
+ SetFile(llvm::sys::path::parent_path(current_path, m_style));
return true;
}
return false;
diff --git a/source/Utility/JSON.cpp b/source/Utility/JSON.cpp
index 7d70034ccabd..725ea97955c6 100644
--- a/source/Utility/JSON.cpp
+++ b/source/Utility/JSON.cpp
@@ -9,15 +9,15 @@
#include "lldb/Utility/JSON.h"
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
-#include <inttypes.h> // for PRIu64, PRId64
+#include <inttypes.h>
#include <limits.h>
-#include <stddef.h> // for size_t
-#include <utility> // for pair
+#include <stddef.h>
+#include <utility>
using namespace lldb_private;
diff --git a/source/Utility/LLDBAssert.cpp b/source/Utility/LLDBAssert.cpp
index 48c1b69e8947..3902c89b2c83 100644
--- a/source/Utility/LLDBAssert.cpp
+++ b/source/Utility/LLDBAssert.cpp
@@ -19,14 +19,14 @@ using namespace lldb_private;
void lldb_private::lldb_assert(bool expression, const char *expr_text,
const char *func, const char *file,
unsigned int line) {
- if (expression)
- ;
- else {
- errs() << format("Assertion failed: (%s), function %s, file %s, line %u\n",
- expr_text, func, file, line);
- errs() << "backtrace leading to the failure:\n";
- llvm::sys::PrintStackTrace(errs());
- errs() << "please file a bug report against lldb reporting this failure "
- "log, and as many details as possible\n";
- }
+ if (LLVM_LIKELY(expression))
+ return;
+
+ errs() << format("Assertion failed: (%s), function %s, file %s, line %u\n",
+ expr_text, func, file, line);
+ errs() << "backtrace leading to the failure:\n";
+ llvm::sys::PrintStackTrace(errs());
+ errs() << "please file a bug report against lldb reporting this failure "
+ "log, and as many details as possible\n";
+ abort();
}
diff --git a/source/Core/Listener.cpp b/source/Utility/Listener.cpp
index a39ce6121b32..a20859e53eeb 100644
--- a/source/Core/Listener.cpp
+++ b/source/Utility/Listener.cpp
@@ -7,19 +7,19 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Listener.h"
+#include "lldb/Utility/Listener.h"
-#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/Event.h"
-#include "lldb/Utility/ConstString.h" // for ConstString
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/ConstString.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Logging.h" // for GetLogIfAllCategoriesSet, LIBL...
+#include "lldb/Utility/Logging.h"
-#include "llvm/ADT/Optional.h" // for Optional
+#include "llvm/ADT/Optional.h"
#include <algorithm>
-#include <memory> // for make_shared
-#include <utility> // for pair, make_pair
+#include <memory>
+#include <utility>
using namespace lldb;
using namespace lldb_private;
@@ -251,9 +251,7 @@ public:
return false;
}
- if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType())
- return true;
- return false;
+ return m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType();
}
private:
diff --git a/source/Utility/Log.cpp b/source/Utility/Log.cpp
index eb026fb04752..2e8570b762af 100644
--- a/source/Utility/Log.cpp
+++ b/source/Utility/Log.cpp
@@ -12,24 +12,24 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/Twine.h" // for operator+, Twine
-#include "llvm/ADT/iterator.h" // for iterator_facade_base
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator.h"
#include "llvm/Support/Chrono.h"
-#include "llvm/Support/ManagedStatic.h" // for ManagedStatic
+#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
-#include <chrono> // for duration, system_clock, syst...
+#include <chrono>
#include <cstdarg>
#include <mutex>
-#include <utility> // for pair
+#include <utility>
-#include <assert.h> // for assert
+#include <assert.h>
#if defined(_WIN32)
-#include <process.h> // for getpid
+#include <process.h>
#else
#include <unistd.h>
#include <pthread.h>
diff --git a/source/Utility/Logging.cpp b/source/Utility/Logging.cpp
index c9a6ef1bd1ea..b97a88b5edcb 100644
--- a/source/Utility/Logging.cpp
+++ b/source/Utility/Logging.cpp
@@ -10,9 +10,9 @@
#include "lldb/Utility/Logging.h"
#include "lldb/Utility/Log.h"
-#include "llvm/ADT/ArrayRef.h" // for ArrayRef
+#include "llvm/ADT/ArrayRef.h"
-#include <stdarg.h> // for va_end, va_list, va_start
+#include <stdarg.h>
using namespace lldb_private;
diff --git a/source/Utility/Range.cpp b/source/Utility/Range.cpp
deleted file mode 100644
index 9d1d28ea484b..000000000000
--- a/source/Utility/Range.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-//===--------------------- Range.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/Range.h"
-
-#include <algorithm>
-#include <utility>
-
-using namespace lldb_utility;
-
-Range::Range(const Range &rng) : m_low(rng.m_low), m_high(rng.m_high) {
- InitRange();
-}
-
-Range::Range(Range::ValueType low, Range::ValueType high)
- : m_low(low), m_high(high) {
- InitRange();
-}
-
-void Range::InitRange() {
- if (m_low == OPEN_END) {
- if (m_high == OPEN_END)
- m_low = 0;
- else {
- // make an empty range
- m_low = 1;
- m_high = 0;
- }
- }
-}
-
-Range &Range::operator=(const Range &rhs) {
- if (&rhs != this) {
- this->m_low = rhs.m_low;
- this->m_high = rhs.m_high;
- }
- return *this;
-}
-
-void Range::Flip() { std::swap(m_high, m_low); }
-
-void Range::Intersection(const Range &other) {
- m_low = std::max(m_low, other.m_low);
- m_high = std::min(m_high, other.m_high);
-}
-
-void Range::Union(const Range &other) {
- m_low = std::min(m_low, other.m_low);
- m_high = std::max(m_high, other.m_high);
-}
-
-void Range::Iterate(RangeCallback callback) {
- ValueType counter = m_low;
- while (counter <= m_high) {
- bool should_continue = callback(counter);
- if (!should_continue)
- return;
- counter++;
- }
-}
-
-bool Range::IsEmpty() { return (m_low > m_high); }
-
-Range::ValueType Range::GetSize() {
- if (m_high == OPEN_END)
- return OPEN_END;
- if (m_high >= m_low)
- return m_high - m_low + 1;
- return 0;
-}
diff --git a/source/Core/RegisterValue.cpp b/source/Utility/RegisterValue.cpp
index 4f908609dde9..27bffde637fb 100644
--- a/source/Core/RegisterValue.cpp
+++ b/source/Utility/RegisterValue.cpp
@@ -7,28 +7,28 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/RegisterValue.h"
+#include "lldb/Utility/RegisterValue.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "lldb/lldb-defines.h" // for LLDB_INVALID_ADDRESS
-#include "lldb/lldb-private-types.h" // for RegisterInfo, type128
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-private-types.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
-#include <cstdint> // for uint8_t, uint32_t, uint64_t
-#include <string> // for string
-#include <tuple> // for tie, tuple
+#include <cstdint>
+#include <string>
+#include <tuple>
#include <vector>
-#include <assert.h> // for assert
-#include <inttypes.h> // for PRIx64
-#include <stdio.h> // for sscanf
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
using namespace lldb;
using namespace lldb_private;
@@ -380,7 +380,6 @@ Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
"unsupported unsigned integer byte size: %u", byte_size);
break;
}
- // TODO: Shouldn't we be setting m_type here?
break;
case eEncodingSint:
@@ -410,8 +409,6 @@ Status RegisterValue::SetValueFromString(const RegisterInfo *reg_info,
byte_size);
break;
}
-
- // TODO: Shouldn't we be setting m_type here?
break;
case eEncodingIEEE754: {
@@ -478,7 +475,7 @@ bool RegisterValue::SignExtend(uint32_t sign_bitpos) {
bool RegisterValue::CopyValue(const RegisterValue &rhs) {
if (this == &rhs)
- return rhs.m_type == eTypeInvalid ? false : true;
+ return rhs.m_type != eTypeInvalid;
m_type = rhs.m_type;
switch (m_type) {
@@ -796,32 +793,7 @@ bool RegisterValue::operator==(const RegisterValue &rhs) const {
}
bool RegisterValue::operator!=(const RegisterValue &rhs) const {
- if (m_type != rhs.m_type)
- return true;
- switch (m_type) {
- case eTypeInvalid:
- return false;
- case eTypeUInt8:
- case eTypeUInt16:
- case eTypeUInt32:
- case eTypeUInt64:
- case eTypeUInt128:
- case eTypeFloat:
- case eTypeDouble:
- case eTypeLongDouble:
- return m_scalar != rhs.m_scalar;
- case eTypeBytes:
- if (buffer.length != rhs.buffer.length) {
- return true;
- } else {
- uint8_t length = buffer.length;
- if (length > kMaxRegisterByteSize)
- length = kMaxRegisterByteSize;
- return memcmp(buffer.bytes, rhs.buffer.bytes, length) != 0;
- }
- break;
- }
- return true;
+ return !(*this == rhs);
}
bool RegisterValue::ClearBit(uint32_t bit) {
diff --git a/source/Utility/Reproducer.cpp b/source/Utility/Reproducer.cpp
new file mode 100644
index 000000000000..6e85ba41767a
--- /dev/null
+++ b/source/Utility/Reproducer.cpp
@@ -0,0 +1,225 @@
+//===-- Reproducer.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/Reproducer.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lldb_private;
+using namespace lldb_private::repro;
+using namespace llvm;
+using namespace llvm::yaml;
+
+Reproducer &Reproducer::Instance() { return *InstanceImpl(); }
+
+llvm::Error Reproducer::Initialize(ReproducerMode mode,
+ llvm::Optional<FileSpec> root) {
+ lldbassert(!InstanceImpl() && "Already initialized.");
+ InstanceImpl().emplace();
+
+ switch (mode) {
+ case ReproducerMode::Capture: {
+ if (!root) {
+ SmallString<128> repro_dir;
+ auto ec = sys::fs::createUniqueDirectory("reproducer", repro_dir);
+ if (ec)
+ return make_error<StringError>(
+ "unable to create unique reproducer directory", ec);
+ root.emplace(repro_dir);
+ } else {
+ auto ec = sys::fs::create_directory(root->GetPath());
+ if (ec)
+ return make_error<StringError>("unable to create reproducer directory",
+ ec);
+ }
+ return Instance().SetCapture(root);
+ } break;
+ case ReproducerMode::Replay:
+ return Instance().SetReplay(root);
+ case ReproducerMode::Off:
+ break;
+ };
+
+ return Error::success();
+}
+
+void Reproducer::Terminate() {
+ lldbassert(InstanceImpl() && "Already terminated.");
+ InstanceImpl().reset();
+}
+
+Optional<Reproducer> &Reproducer::InstanceImpl() {
+ static Optional<Reproducer> g_reproducer;
+ return g_reproducer;
+}
+
+const Generator *Reproducer::GetGenerator() const {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ if (m_generator)
+ return &(*m_generator);
+ return nullptr;
+}
+
+const Loader *Reproducer::GetLoader() const {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ if (m_loader)
+ return &(*m_loader);
+ return nullptr;
+}
+
+Generator *Reproducer::GetGenerator() {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ if (m_generator)
+ return &(*m_generator);
+ return nullptr;
+}
+
+Loader *Reproducer::GetLoader() {
+ std::lock_guard<std::mutex> guard(m_mutex);
+ if (m_loader)
+ return &(*m_loader);
+ return nullptr;
+}
+
+llvm::Error Reproducer::SetCapture(llvm::Optional<FileSpec> root) {
+ std::lock_guard<std::mutex> guard(m_mutex);
+
+ if (root && m_loader)
+ return make_error<StringError>(
+ "cannot generate a reproducer when replay one",
+ inconvertibleErrorCode());
+
+ if (!root) {
+ m_generator.reset();
+ return Error::success();
+ }
+
+ m_generator.emplace(*root);
+ return Error::success();
+}
+
+llvm::Error Reproducer::SetReplay(llvm::Optional<FileSpec> root) {
+ std::lock_guard<std::mutex> guard(m_mutex);
+
+ if (root && m_generator)
+ return make_error<StringError>(
+ "cannot replay a reproducer when generating one",
+ inconvertibleErrorCode());
+
+ if (!root) {
+ m_loader.reset();
+ return Error::success();
+ }
+
+ m_loader.emplace(*root);
+ if (auto e = m_loader->LoadIndex())
+ return e;
+
+ return Error::success();
+}
+
+FileSpec Reproducer::GetReproducerPath() const {
+ if (auto g = GetGenerator())
+ return g->GetRoot();
+ if (auto l = GetLoader())
+ return l->GetRoot();
+ return {};
+}
+
+Generator::Generator(const FileSpec &root) : m_root(root), m_done(false) {}
+
+Generator::~Generator() {}
+
+ProviderBase *Generator::Register(std::unique_ptr<ProviderBase> provider) {
+ std::lock_guard<std::mutex> lock(m_providers_mutex);
+ std::pair<const void *, std::unique_ptr<ProviderBase>> key_value(
+ provider->DynamicClassID(), std::move(provider));
+ auto e = m_providers.insert(std::move(key_value));
+ return e.first->getSecond().get();
+}
+
+void Generator::Keep() {
+ assert(!m_done);
+ m_done = true;
+
+ for (auto &provider : m_providers)
+ provider.second->Keep();
+
+ AddProvidersToIndex();
+}
+
+void Generator::Discard() {
+ assert(!m_done);
+ m_done = true;
+
+ for (auto &provider : m_providers)
+ provider.second->Discard();
+
+ llvm::sys::fs::remove_directories(m_root.GetPath());
+}
+
+const FileSpec &Generator::GetRoot() const { return m_root; }
+
+void Generator::AddProvidersToIndex() {
+ FileSpec index = m_root;
+ index.AppendPathComponent("index.yaml");
+
+ std::error_code EC;
+ auto strm = llvm::make_unique<raw_fd_ostream>(index.GetPath(), EC,
+ sys::fs::OpenFlags::F_None);
+ yaml::Output yout(*strm);
+
+ for (auto &provider : m_providers) {
+ auto &provider_info = provider.second->GetInfo();
+ yout << const_cast<ProviderInfo &>(provider_info);
+ }
+}
+
+Loader::Loader(const FileSpec &root) : m_root(root), m_loaded(false) {}
+
+llvm::Error Loader::LoadIndex() {
+ if (m_loaded)
+ return llvm::Error::success();
+
+ FileSpec index = m_root.CopyByAppendingPathComponent("index.yaml");
+
+ auto error_or_file = MemoryBuffer::getFile(index.GetPath());
+ if (auto err = error_or_file.getError())
+ return make_error<StringError>("unable to load reproducer index", err);
+
+ std::vector<ProviderInfo> provider_info;
+ yaml::Input yin((*error_or_file)->getBuffer());
+ yin >> provider_info;
+
+ if (auto err = yin.error())
+ return make_error<StringError>("unable to read reproducer index", err);
+
+ for (auto &info : provider_info)
+ m_provider_info[info.name] = info;
+
+ m_loaded = true;
+
+ return llvm::Error::success();
+}
+
+llvm::Optional<ProviderInfo> Loader::GetProviderInfo(StringRef name) {
+ assert(m_loaded);
+
+ auto it = m_provider_info.find(name);
+ if (it == m_provider_info.end())
+ return llvm::None;
+
+ return it->second;
+}
+
+void ProviderBase::anchor() {}
+char ProviderBase::ID = 0;
diff --git a/source/Core/Scalar.cpp b/source/Utility/Scalar.cpp
index 6a7186969ef2..a2bb86ffdb15 100644
--- a/source/Core/Scalar.cpp
+++ b/source/Utility/Scalar.cpp
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Scalar.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-types.h" // for offset_t
+#include "lldb/lldb-types.h"
#include "llvm/ADT/SmallString.h"
@@ -38,7 +38,7 @@ static Scalar::Type PromoteToMaxType(
const Scalar *&promoted_rhs_ptr // Pointer to the resulting possibly
// promoted value of rhs (at most one of
// lhs/rhs will get promoted)
- ) {
+) {
Scalar result;
// Initialize the promoted values for both the right and left hand side
// values to be the objects themselves. If no promotion is needed (both right
@@ -76,49 +76,6 @@ Scalar::Scalar() : m_type(e_void), m_float((float)0) {}
Scalar::Scalar(const Scalar &rhs)
: m_type(rhs.m_type), m_integer(rhs.m_integer), m_float(rhs.m_float) {}
-// Scalar::Scalar(const RegisterValue& reg) :
-// m_type(e_void),
-// m_data()
-//{
-// switch (reg.info.encoding)
-// {
-// case eEncodingUint: // unsigned integer
-// switch (reg.info.byte_size)
-// {
-// case 1: m_type = e_uint; m_data.uint = reg.value.uint8; break;
-// case 2: m_type = e_uint; m_data.uint = reg.value.uint16; break;
-// case 4: m_type = e_uint; m_data.uint = reg.value.uint32; break;
-// case 8: m_type = e_ulonglong; m_data.ulonglong = reg.value.uint64;
-// break;
-// break;
-// }
-// break;
-//
-// case eEncodingSint: // signed integer
-// switch (reg.info.byte_size)
-// {
-// case 1: m_type = e_sint; m_data.sint = reg.value.sint8; break;
-// case 2: m_type = e_sint; m_data.sint = reg.value.sint16; break;
-// case 4: m_type = e_sint; m_data.sint = reg.value.sint32; break;
-// case 8: m_type = e_slonglong; m_data.slonglong = reg.value.sint64;
-// break;
-// break;
-// }
-// break;
-//
-// case eEncodingIEEE754: // float
-// switch (reg.info.byte_size)
-// {
-// case 4: m_type = e_float; m_data.flt = reg.value.float32; break;
-// case 8: m_type = e_double; m_data.dbl = reg.value.float64; break;
-// break;
-// }
-// break;
-// case eEncodingVector: // vector registers
-// break;
-// }
-//}
-
bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const {
size_t byte_size = GetByteSize();
if (byte_size > 0) {
@@ -1490,8 +1447,13 @@ unsigned long long Scalar::ULongLong(unsigned long long fail_value) const {
.getZExtValue();
case e_float:
return (ulonglong_t)m_float.convertToFloat();
- case e_double:
- return (ulonglong_t)m_float.convertToDouble();
+ case e_double: {
+ double d_val = m_float.convertToDouble();
+ llvm::APInt rounded_double =
+ llvm::APIntOps::RoundDoubleToAPInt(d_val, sizeof(ulonglong_t) * 8);
+ return (ulonglong_t)(rounded_double.zextOrTrunc(sizeof(ulonglong_t) * 8))
+ .getZExtValue();
+ }
case e_long_double:
llvm::APInt ldbl_val = m_float.bitcastToAPInt();
return (ulonglong_t)(ldbl_val.zextOrTrunc(sizeof(ulonglong_t) * 8))
@@ -2636,37 +2598,7 @@ bool lldb_private::operator==(const Scalar &lhs, const Scalar &rhs) {
}
bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) {
- // If either entry is void then we can just compare the types
- if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
- return lhs.m_type != rhs.m_type;
-
- Scalar
- temp_value; // A temp value that might get a copy of either promoted value
- const Scalar *a;
- const Scalar *b;
- llvm::APFloat::cmpResult result;
- switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) {
- case Scalar::e_void:
- break;
- case Scalar::e_sint:
- case Scalar::e_uint:
- case Scalar::e_slong:
- case Scalar::e_ulong:
- case Scalar::e_slonglong:
- case Scalar::e_ulonglong:
- case Scalar::e_sint128:
- case Scalar::e_uint128:
- case Scalar::e_sint256:
- case Scalar::e_uint256:
- return a->m_integer != b->m_integer;
- case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
- result = a->m_float.compare(b->m_float);
- if (result != llvm::APFloat::cmpEqual)
- return true;
- }
- return true;
+ return !(lhs == rhs);
}
bool lldb_private::operator<(const Scalar &lhs, const Scalar &rhs) {
@@ -2703,104 +2635,15 @@ bool lldb_private::operator<(const Scalar &lhs, const Scalar &rhs) {
}
bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) {
- if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
- return false;
-
- Scalar temp_value;
- const Scalar *a;
- const Scalar *b;
- llvm::APFloat::cmpResult result;
- switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) {
- case Scalar::e_void:
- break;
- case Scalar::e_sint:
- case Scalar::e_slong:
- case Scalar::e_slonglong:
- case Scalar::e_sint128:
- case Scalar::e_sint256:
- return a->m_integer.sle(b->m_integer);
- case Scalar::e_uint:
- case Scalar::e_ulong:
- case Scalar::e_ulonglong:
- case Scalar::e_uint128:
- case Scalar::e_uint256:
- return a->m_integer.ule(b->m_integer);
- case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
- result = a->m_float.compare(b->m_float);
- if (result == llvm::APFloat::cmpLessThan ||
- result == llvm::APFloat::cmpEqual)
- return true;
- }
- return false;
+ return !(rhs < lhs);
}
bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) {
- if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
- return false;
-
- Scalar temp_value;
- const Scalar *a;
- const Scalar *b;
- llvm::APFloat::cmpResult result;
- switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) {
- case Scalar::e_void:
- break;
- case Scalar::e_sint:
- case Scalar::e_slong:
- case Scalar::e_slonglong:
- case Scalar::e_sint128:
- case Scalar::e_sint256:
- return a->m_integer.sgt(b->m_integer);
- case Scalar::e_uint:
- case Scalar::e_ulong:
- case Scalar::e_ulonglong:
- case Scalar::e_uint128:
- case Scalar::e_uint256:
- return a->m_integer.ugt(b->m_integer);
- case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
- result = a->m_float.compare(b->m_float);
- if (result == llvm::APFloat::cmpGreaterThan)
- return true;
- }
- return false;
+ return rhs < lhs;
}
bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) {
- if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void)
- return false;
-
- Scalar temp_value;
- const Scalar *a;
- const Scalar *b;
- llvm::APFloat::cmpResult result;
- switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) {
- case Scalar::e_void:
- break;
- case Scalar::e_sint:
- case Scalar::e_slong:
- case Scalar::e_slonglong:
- case Scalar::e_sint128:
- case Scalar::e_sint256:
- return a->m_integer.sge(b->m_integer);
- case Scalar::e_uint:
- case Scalar::e_ulong:
- case Scalar::e_ulonglong:
- case Scalar::e_uint128:
- case Scalar::e_uint256:
- return a->m_integer.uge(b->m_integer);
- case Scalar::e_float:
- case Scalar::e_double:
- case Scalar::e_long_double:
- result = a->m_float.compare(b->m_float);
- if (result == llvm::APFloat::cmpGreaterThan ||
- result == llvm::APFloat::cmpEqual)
- return true;
- }
- return false;
+ return !(lhs < rhs);
}
bool Scalar::ClearBit(uint32_t bit) {
diff --git a/source/Utility/SelectHelper.cpp b/source/Utility/SelectHelper.cpp
index 0f6a96309504..2979a67dc182 100644
--- a/source/Utility/SelectHelper.cpp
+++ b/source/Utility/SelectHelper.cpp
@@ -17,14 +17,14 @@
#include "lldb/Utility/SelectHelper.h"
#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Utility/Status.h"
-#include "lldb/lldb-enumerations.h" // for ErrorType::eErrorTypePOSIX
-#include "lldb/lldb-types.h" // for socket_t
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
-#include "llvm/ADT/DenseMap.h" // for DenseMapPair, DenseMap, Dense...
-#include "llvm/ADT/Optional.h" // for Optional
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
#include <algorithm>
-#include <chrono> // for microseconds, seconds, steady...
+#include <chrono>
#include <errno.h>
#if defined(_WIN32)
diff --git a/source/Core/State.cpp b/source/Utility/State.cpp
index 4697ca4b5f17..6ff8a4940b0f 100644
--- a/source/Core/State.cpp
+++ b/source/Utility/State.cpp
@@ -7,11 +7,7 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
-#include "lldb/Core/State.h"
+#include "lldb/Utility/State.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/source/Utility/Status.cpp b/source/Utility/Status.cpp
index f6dc228391b3..062bd261ea8b 100644
--- a/source/Utility/Status.cpp
+++ b/source/Utility/Status.cpp
@@ -11,23 +11,26 @@
#include "lldb/Utility/Status.h"
#include "lldb/Utility/VASPrintf.h"
-#include "lldb/lldb-defines.h" // for LLDB_GENERIC_ERROR
-#include "lldb/lldb-enumerations.h" // for ErrorType, ErrorType::eErr...
-#include "llvm/ADT/SmallString.h" // for SmallString
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errno.h"
-#include "llvm/Support/FormatProviders.h" // for format_provider
+#include "llvm/Support/FormatProviders.h"
#include <cerrno>
#include <cstdarg>
-#include <string> // for string
+#include <string>
#include <system_error>
#ifdef __APPLE__
#include <mach/mach.h>
#endif
-#include <stdint.h> // for uint32_t
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include <stdint.h>
namespace llvm {
class raw_ostream;
@@ -87,7 +90,8 @@ llvm::Error Status::ToError() const {
if (Success())
return llvm::Error::success();
if (m_type == ErrorType::eErrorTypePOSIX)
- return llvm::errorCodeToError(std::error_code(m_code, std::generic_category()));
+ return llvm::errorCodeToError(
+ std::error_code(m_code, std::generic_category()));
return llvm::make_error<llvm::StringError>(AsCString(),
llvm::inconvertibleErrorCode());
}
@@ -106,6 +110,23 @@ const Status &Status::operator=(const Status &rhs) {
Status::~Status() = default;
+#ifdef _WIN32
+static std::string RetrieveWin32ErrorString(uint32_t error_code) {
+ char *buffer = nullptr;
+ std::string message;
+ // Retrieve win32 system error.
+ if (::FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR)&buffer, 0, NULL)) {
+ message.assign(buffer);
+ ::LocalFree(buffer);
+ }
+ return message;
+}
+#endif
+
//----------------------------------------------------------------------
// Get the error value as a NULL C string. The error string will be fetched and
// cached on demand. The cached error string value will remain until the error
@@ -128,6 +149,12 @@ const char *Status::AsCString(const char *default_error_str) const {
m_string = llvm::sys::StrError(m_code);
break;
+ case eErrorTypeWin32:
+#if defined(_WIN32)
+ m_string = RetrieveWin32ErrorString(m_code);
+#endif
+ break;
+
default:
break;
}
diff --git a/source/Utility/Stream.cpp b/source/Utility/Stream.cpp
index 7df7f7008084..54691c7066db 100644
--- a/source/Utility/Stream.cpp
+++ b/source/Utility/Stream.cpp
@@ -11,7 +11,8 @@
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/VASPrintf.h"
-#include "llvm/ADT/SmallString.h" // for SmallString
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/LEB128.h"
#include <string>
@@ -23,11 +24,11 @@ using namespace lldb_private;
Stream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order)
: m_flags(flags), m_addr_size(addr_size), m_byte_order(byte_order),
- m_indent_level(0) {}
+ m_indent_level(0), m_forwarder(*this) {}
Stream::Stream()
: m_flags(0), m_addr_size(4), m_byte_order(endian::InlHostByteOrder()),
- m_indent_level(0) {}
+ m_indent_level(0), m_forwarder(*this) {}
//------------------------------------------------------------------
// Destructor
@@ -49,47 +50,20 @@ void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); }
// Put an SLEB128 "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
size_t Stream::PutSLEB128(int64_t sval) {
- size_t bytes_written = 0;
- if (m_flags.Test(eBinary)) {
- bool more = true;
- while (more) {
- uint8_t byte = sval & 0x7fu;
- sval >>= 7;
- /* sign bit of byte is 2nd high order bit (0x40) */
- if ((sval == 0 && !(byte & 0x40)) || (sval == -1 && (byte & 0x40)))
- more = false;
- else
- // more bytes to come
- byte |= 0x80u;
- bytes_written += Write(&byte, 1);
- }
- } else {
- bytes_written = Printf("0x%" PRIi64, sval);
- }
-
- return bytes_written;
+ if (m_flags.Test(eBinary))
+ return llvm::encodeSLEB128(sval, m_forwarder);
+ else
+ return Printf("0x%" PRIi64, sval);
}
//------------------------------------------------------------------
// Put an ULEB128 "uval" out to the stream using the printf format in "format".
//------------------------------------------------------------------
size_t Stream::PutULEB128(uint64_t uval) {
- size_t bytes_written = 0;
- if (m_flags.Test(eBinary)) {
- do {
-
- uint8_t byte = uval & 0x7fu;
- uval >>= 7;
- if (uval != 0) {
- // more bytes to come
- byte |= 0x80u;
- }
- bytes_written += Write(&byte, 1);
- } while (uval != 0);
- } else {
- bytes_written = Printf("0x%" PRIx64, uval);
- }
- return bytes_written;
+ if (m_flags.Test(eBinary))
+ return llvm::encodeULEB128(uval, m_forwarder);
+ else
+ return Printf("0x%" PRIx64, uval);
}
//------------------------------------------------------------------
@@ -119,9 +93,9 @@ void Stream::QuotedCString(const char *cstr, const char *format) {
//------------------------------------------------------------------
void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix,
const char *suffix) {
- if (prefix == NULL)
+ if (prefix == nullptr)
prefix = "";
- if (suffix == NULL)
+ if (suffix == nullptr)
suffix = "";
// int addr_width = m_addr_size << 1;
// Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix);
@@ -339,26 +313,25 @@ size_t Stream::PrintfAsRawHex8(const char *format, ...) {
llvm::SmallString<1024> buf;
VASprintf(buf, format, args);
- size_t length = 0;
+ ByteDelta delta(*this);
for (char C : buf)
- length += _PutHex8(C, false);
+ _PutHex8(C, false);
va_end(args);
- return length;
+ return *delta;
}
size_t Stream::PutNHex8(size_t n, uint8_t uvalue) {
- size_t bytes_written = 0;
+ ByteDelta delta(*this);
for (size_t i = 0; i < n; ++i)
- bytes_written += _PutHex8(uvalue, false);
- return bytes_written;
+ _PutHex8(uvalue, false);
+ return *delta;
}
-size_t Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
- size_t bytes_written = 0;
+void Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
if (m_flags.Test(eBinary)) {
- bytes_written = Write(&uvalue, 1);
+ Write(&uvalue, 1);
} else {
if (add_prefix)
PutCString("0x");
@@ -369,56 +342,62 @@ size_t Stream::_PutHex8(uint8_t uvalue, bool add_prefix) {
char nibble_chars[2];
nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf];
nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf];
- bytes_written = Write(nibble_chars, sizeof(nibble_chars));
+ Write(nibble_chars, sizeof(nibble_chars));
}
- return bytes_written;
}
-size_t Stream::PutHex8(uint8_t uvalue) { return _PutHex8(uvalue, false); }
+size_t Stream::PutHex8(uint8_t uvalue) {
+ ByteDelta delta(*this);
+ _PutHex8(uvalue, false);
+ return *delta;
+}
size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) {
+ ByteDelta delta(*this);
+
if (byte_order == eByteOrderInvalid)
byte_order = m_byte_order;
- size_t bytes_written = 0;
if (byte_order == eByteOrderLittle) {
for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
- bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
+ _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
} else {
for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
- bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
+ _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
}
- return bytes_written;
+ return *delta;
}
size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) {
+ ByteDelta delta(*this);
+
if (byte_order == eByteOrderInvalid)
byte_order = m_byte_order;
- size_t bytes_written = 0;
if (byte_order == eByteOrderLittle) {
for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
- bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
+ _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
} else {
for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
- bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
+ _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
}
- return bytes_written;
+ return *delta;
}
size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) {
+ ByteDelta delta(*this);
+
if (byte_order == eByteOrderInvalid)
byte_order = m_byte_order;
- size_t bytes_written = 0;
if (byte_order == eByteOrderLittle) {
for (size_t byte = 0; byte < sizeof(uvalue); ++byte)
- bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
+ _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
} else {
for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); --byte)
- bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
+ _PutHex8((uint8_t)(uvalue >> (byte * 8)), false);
}
- return bytes_written;
+ return *delta;
}
size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size,
@@ -427,11 +406,11 @@ size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size,
case 1:
return PutHex8((uint8_t)uvalue);
case 2:
- return PutHex16((uint16_t)uvalue);
+ return PutHex16((uint16_t)uvalue, byte_order);
case 4:
- return PutHex32((uint32_t)uvalue);
+ return PutHex32((uint32_t)uvalue, byte_order);
case 8:
- return PutHex64(uvalue);
+ return PutHex64(uvalue, byte_order);
}
return 0;
}
@@ -464,65 +443,66 @@ size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) {
size_t Stream::PutRawBytes(const void *s, size_t src_len,
ByteOrder src_byte_order, ByteOrder dst_byte_order) {
+ ByteDelta delta(*this);
+
if (src_byte_order == eByteOrderInvalid)
src_byte_order = m_byte_order;
if (dst_byte_order == eByteOrderInvalid)
dst_byte_order = m_byte_order;
- size_t bytes_written = 0;
const uint8_t *src = (const uint8_t *)s;
bool binary_was_set = m_flags.Test(eBinary);
if (!binary_was_set)
m_flags.Set(eBinary);
if (src_byte_order == dst_byte_order) {
for (size_t i = 0; i < src_len; ++i)
- bytes_written += _PutHex8(src[i], false);
+ _PutHex8(src[i], false);
} else {
for (size_t i = src_len - 1; i < src_len; --i)
- bytes_written += _PutHex8(src[i], false);
+ _PutHex8(src[i], false);
}
if (!binary_was_set)
m_flags.Clear(eBinary);
- return bytes_written;
+ return *delta;
}
size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len,
ByteOrder src_byte_order,
ByteOrder dst_byte_order) {
+ ByteDelta delta(*this);
if (src_byte_order == eByteOrderInvalid)
src_byte_order = m_byte_order;
if (dst_byte_order == eByteOrderInvalid)
dst_byte_order = m_byte_order;
- size_t bytes_written = 0;
const uint8_t *src = (const uint8_t *)s;
bool binary_is_set = m_flags.Test(eBinary);
m_flags.Clear(eBinary);
if (src_byte_order == dst_byte_order) {
for (size_t i = 0; i < src_len; ++i)
- bytes_written += _PutHex8(src[i], false);
+ _PutHex8(src[i], false);
} else {
for (size_t i = src_len - 1; i < src_len; --i)
- bytes_written += _PutHex8(src[i], false);
+ _PutHex8(src[i], false);
}
if (binary_is_set)
m_flags.Set(eBinary);
- return bytes_written;
+ return *delta;
}
size_t Stream::PutCStringAsRawHex8(const char *s) {
- size_t bytes_written = 0;
+ ByteDelta delta(*this);
bool binary_is_set = m_flags.Test(eBinary);
m_flags.Clear(eBinary);
- do {
- bytes_written += _PutHex8(*s, false);
+ while(*s) {
+ _PutHex8(*s, false);
++s;
- } while (*s);
+ }
if (binary_is_set)
m_flags.Set(eBinary);
- return bytes_written;
+ return *delta;
}
diff --git a/source/Utility/StreamGDBRemote.cpp b/source/Utility/StreamGDBRemote.cpp
index 2620e3786d29..9304d84f58a0 100644
--- a/source/Utility/StreamGDBRemote.cpp
+++ b/source/Utility/StreamGDBRemote.cpp
@@ -9,8 +9,8 @@
#include "lldb/Utility/StreamGDBRemote.h"
-#include "lldb/Utility/Flags.h" // for Flags
-#include "lldb/Utility/Stream.h" // for Stream::::eBinary
+#include "lldb/Utility/Flags.h"
+#include "lldb/Utility/Stream.h"
#include <stdio.h>
diff --git a/source/Utility/StreamString.cpp b/source/Utility/StreamString.cpp
index 75f58de28b97..152096198858 100644
--- a/source/Utility/StreamString.cpp
+++ b/source/Utility/StreamString.cpp
@@ -24,12 +24,15 @@ void StreamString::Flush() {
// Nothing to do when flushing a buffer based stream...
}
-size_t StreamString::Write(const void *s, size_t length) {
+size_t StreamString::WriteImpl(const void *s, size_t length) {
m_packet.append(reinterpret_cast<const char *>(s), length);
return length;
}
-void StreamString::Clear() { m_packet.clear(); }
+void StreamString::Clear() {
+ m_packet.clear();
+ m_bytes_written = 0;
+}
bool StreamString::Empty() const { return GetSize() == 0; }
diff --git a/source/Utility/StringExtractor.cpp b/source/Utility/StringExtractor.cpp
index 7528350cf759..ddf414702d8c 100644
--- a/source/Utility/StringExtractor.cpp
+++ b/source/Utility/StringExtractor.cpp
@@ -11,9 +11,9 @@
#include <tuple>
-#include <ctype.h> // for isxdigit, isspace
+#include <ctype.h>
#include <stdlib.h>
-#include <string.h> // for memset
+#include <string.h>
static inline int xdigit_to_sint(char ch) {
if (ch >= 'a' && ch <= 'f')
diff --git a/source/Utility/StringExtractorGDBRemote.cpp b/source/Utility/StringExtractorGDBRemote.cpp
index 3cae06df3b1e..2a8bd785576b 100644
--- a/source/Utility/StringExtractorGDBRemote.cpp
+++ b/source/Utility/StringExtractorGDBRemote.cpp
@@ -9,7 +9,7 @@
#include "lldb/Utility/StringExtractorGDBRemote.h"
-#include <ctype.h> // for isxdigit
+#include <ctype.h>
#include <string.h>
StringExtractorGDBRemote::ResponseType
diff --git a/source/Utility/StringList.cpp b/source/Utility/StringList.cpp
index 190cb9d682c9..20bde1a39ac1 100644
--- a/source/Utility/StringList.cpp
+++ b/source/Utility/StringList.cpp
@@ -10,13 +10,13 @@
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/Log.h"
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "llvm/ADT/ArrayRef.h" // for ArrayRef, makeArrayRef
+#include "llvm/ADT/ArrayRef.h"
-#include <algorithm> // for min
-#include <stdint.h> // for SIZE_MAX, uint32_t
-#include <string.h> // for size_t, strcspn, NULL
+#include <algorithm>
+#include <stdint.h>
+#include <string.h>
using namespace lldb_private;
@@ -83,7 +83,7 @@ size_t StringList::GetMaxStringLength() const {
const char *StringList::GetStringAtIndex(size_t idx) const {
if (idx < m_strings.size())
return m_strings[idx].c_str();
- return NULL;
+ return nullptr;
}
void StringList::Join(const char *separator, Stream &strm) {
diff --git a/source/Utility/StructuredData.cpp b/source/Utility/StructuredData.cpp
index 55f003f245bf..76a141af40b6 100644
--- a/source/Utility/StructuredData.cpp
+++ b/source/Utility/StructuredData.cpp
@@ -12,14 +12,14 @@
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/Status.h"
-#include "lldb/Utility/Stream.h" // for Stream
+#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StreamString.h"
-#include "llvm/ADT/STLExtras.h" // for make_unique
+#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cerrno>
#include <cstdlib>
#include <inttypes.h>
-#include <limits> // for numeric_limits
+#include <limits>
using namespace lldb_private;
@@ -33,11 +33,6 @@ static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser);
StructuredData::ObjectSP
StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) {
StructuredData::ObjectSP return_sp;
- if (!input_spec.Exists()) {
- error.SetErrorStringWithFormatv("input file {0} does not exist.",
- input_spec);
- return return_sp;
- }
auto buffer_or_error = llvm::MemoryBuffer::getFile(input_spec.GetPath());
if (!buffer_or_error) {
@@ -149,7 +144,7 @@ static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) {
}
StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) {
- JSONParser json_parser(json_text.c_str());
+ JSONParser json_parser(json_text);
StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
return object_sp;
}
@@ -174,11 +169,11 @@ StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
if (this->GetType() == lldb::eStructuredDataTypeArray) {
std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
- if (match.second.size() == 0) {
+ if (match.second.empty()) {
return this->shared_from_this();
}
errno = 0;
- uint64_t val = strtoul(match.second.str().c_str(), NULL, 10);
+ uint64_t val = strtoul(match.second.str().c_str(), nullptr, 10);
if (errno == 0) {
return this->GetAsArray()->GetItemAtIndex(val);
}
@@ -231,7 +226,7 @@ void StructuredData::Float::Dump(Stream &s, bool pretty_print) const {
}
void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const {
- if (m_value == true)
+ if (m_value)
s.PutCString("true");
else
s.PutCString("false");
diff --git a/source/Utility/TildeExpressionResolver.cpp b/source/Utility/TildeExpressionResolver.cpp
index ae947059d8b9..4e2be77c49cb 100644
--- a/source/Utility/TildeExpressionResolver.cpp
+++ b/source/Utility/TildeExpressionResolver.cpp
@@ -9,14 +9,14 @@
#include "lldb/Utility/TildeExpressionResolver.h"
-#include <assert.h> // for assert
-#include <system_error> // for error_code
+#include <assert.h>
+#include <system_error>
-#include "llvm/ADT/STLExtras.h" // for any_of
-#include "llvm/ADT/SmallVector.h" // for SmallVectorImpl
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h" // for fs
+#include "llvm/Support/raw_ostream.h"
#if !defined(_WIN32)
#include <pwd.h>
@@ -59,7 +59,7 @@ bool StandardTildeExpressionResolver::ResolvePartial(StringRef Expr,
struct passwd *user_entry;
Expr = Expr.drop_front();
- while ((user_entry = getpwent()) != NULL) {
+ while ((user_entry = getpwent()) != nullptr) {
StringRef ThisName(user_entry->pw_name);
if (!ThisName.startswith(Expr))
continue;
diff --git a/source/Utility/Timer.cpp b/source/Utility/Timer.cpp
index fe7787458fa6..c56ac2192b33 100644
--- a/source/Utility/Timer.cpp
+++ b/source/Utility/Timer.cpp
@@ -12,11 +12,11 @@
#include <algorithm>
#include <map>
#include <mutex>
-#include <utility> // for pair
+#include <utility>
#include <vector>
-#include <assert.h> // for assert
-#include <stdarg.h> // for va_end, va_list, va_start
+#include <assert.h>
+#include <stdarg.h>
#include <stdio.h>
using namespace lldb_private;
@@ -125,7 +125,7 @@ void Timer::DumpCategoryTimes(Stream *s) {
return; // Later code will break without any elements.
// Sort by time
- std::sort(sorted.begin(), sorted.end(), CategoryMapIteratorSortCriterion);
+ llvm::sort(sorted.begin(), sorted.end(), CategoryMapIteratorSortCriterion);
for (const auto &timer : sorted)
s->Printf("%.9f sec for %s\n", timer.second / 1000000000., timer.first);
diff --git a/source/Utility/UUID.cpp b/source/Utility/UUID.cpp
index 623ad69ddc76..b00878792c7e 100644
--- a/source/Utility/UUID.cpp
+++ b/source/Utility/UUID.cpp
@@ -9,13 +9,10 @@
#include "lldb/Utility/UUID.h"
-// Other libraries and framework includes
-// Project includes
#include "lldb/Utility/Stream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Format.h"
-// C Includes
#include <ctype.h>
#include <stdio.h>
#include <string.h>
@@ -54,9 +51,7 @@ std::string UUID::GetAsString(llvm::StringRef separator) const {
return result;
}
-void UUID::Dump(Stream *s) const {
- s->PutCString(GetAsString().c_str());
-}
+void UUID::Dump(Stream *s) const { s->PutCString(GetAsString()); }
static inline int xdigit_to_int(char ch) {
ch = tolower(ch);
diff --git a/source/Utility/VASprintf.cpp b/source/Utility/VASprintf.cpp
index 900d9754a9b4..4368a3738307 100644
--- a/source/Utility/VASprintf.cpp
+++ b/source/Utility/VASprintf.cpp
@@ -10,12 +10,12 @@
#include "lldb/Utility/VASPrintf.h"
#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallVector.h" // for SmallVectorImpl
-#include "llvm/ADT/StringRef.h" // for StringRef
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
-#include <assert.h> // for assert
-#include <stdarg.h> // for va_end, va_list, va_copy
-#include <stdio.h> // for vsnprintf, size_t
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
bool lldb_private::VASprintf(llvm::SmallVectorImpl<char> &buf, const char *fmt,
va_list args) {
diff --git a/source/Utility/VMRange.cpp b/source/Utility/VMRange.cpp
index 105b1a58c48c..20dc7dbbe757 100644
--- a/source/Utility/VMRange.cpp
+++ b/source/Utility/VMRange.cpp
@@ -10,28 +10,30 @@
#include "lldb/Utility/VMRange.h"
#include "lldb/Utility/Stream.h"
-#include "lldb/lldb-types.h" // for addr_t
+#include "lldb/lldb-types.h"
#include <algorithm>
-#include <iterator> // for distance
-#include <vector> // for const_iterator
+#include <iterator>
+#include <vector>
-#include <stddef.h> // for size_t
-#include <stdint.h> // for UINT32_MAX, uint32_t
+#include <stddef.h>
+#include <stdint.h>
using namespace lldb;
using namespace lldb_private;
bool VMRange::ContainsValue(const VMRange::collection &coll,
lldb::addr_t value) {
- ValueInRangeUnaryPredicate in_range_predicate(value);
- return llvm::find_if(coll, in_range_predicate) != coll.end();
+ return llvm::find_if(coll, [&](const VMRange &r) {
+ return r.Contains(value);
+ }) != coll.end();
}
bool VMRange::ContainsRange(const VMRange::collection &coll,
const VMRange &range) {
- RangeInRangeUnaryPredicate in_range_predicate(range);
- return llvm::find_if(coll, in_range_predicate) != coll.end();
+ return llvm::find_if(coll, [&](const VMRange &r) {
+ return r.Contains(range);
+ }) != coll.end();
}
void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const {
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index de548f03069e..71a76c2d93d3 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -30,7 +30,7 @@ set(LLDB_TEST_USER_ARGS
""
CACHE STRING "Specify additional arguments to pass to test runner. For example: '-C gcc -C clang -A i386 -A x86_64'")
-# The .nodindex suffix is a marker for Spotlight to never index the
+# The .noindex suffix is a marker for Spotlight to never index the
# build directory. LLDB queries Spotlight to locate .dSYM bundles
# based on the UUID embedded in a binary, and because the UUID is a
# hash of filename and .text section, there *will* be conflicts inside
@@ -49,6 +49,7 @@ set(LLDB_TEST_COMMON_ARGS
list(APPEND LLDB_TEST_COMMON_ARGS
--executable ${LLDB_TEST_EXECUTABLE}
--dsymutil ${LLDB_TEST_DSYMUTIL}
+ --filecheck ${LLDB_TEST_FILECHECK}
-C ${LLDB_TEST_C_COMPILER}
)
@@ -73,12 +74,13 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
endif()
endif()
-if(LLDB_CODESIGN_IDENTITY)
- list(APPEND LLDB_TEST_COMMON_ARGS --codesign-identity "${LLDB_CODESIGN_IDENTITY}")
+if(LLDB_CODESIGN_IDENTITY_USED)
+ list(APPEND LLDB_TEST_COMMON_ARGS --codesign-identity "${LLDB_CODESIGN_IDENTITY_USED}")
endif()
if(LLDB_BUILD_FRAMEWORK)
- list(APPEND LLDB_TEST_COMMON_ARGS --framework ${LLDB_FRAMEWORK_DIR}/LLDB.framework)
+ get_target_property(framework_target_dir liblldb LIBRARY_OUTPUT_DIRECTORY)
+ list(APPEND LLDB_TEST_COMMON_ARGS --framework ${framework_target_dir}/LLDB.framework)
endif()
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows|Darwin")
@@ -86,11 +88,17 @@ if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows|Darwin")
--env ARCHIVER=${CMAKE_AR} --env OBJCOPY=${CMAKE_OBJCOPY})
endif()
-if(CMAKE_HOST_APPLE)
+if (NOT "${LLDB_LIT_TOOLS_DIR}" STREQUAL "")
+ if (NOT EXISTS "${LLDB_LIT_TOOLS_DIR}")
+ message(WARNING "LLDB_LIT_TOOLS_DIR ${LLDB_LIT_TOOLS_DIR} does not exist.")
+ endif()
+endif()
+
+if(CMAKE_HOST_APPLE AND DEBUGSERVER_PATH)
list(APPEND LLDB_TEST_COMMON_ARGS --server ${DEBUGSERVER_PATH})
endif()
-if(SKIP_DEBUGSERVER)
+if(SKIP_TEST_DEBUGSERVER)
list(APPEND LLDB_TEST_COMMON_ARGS --out-of-tree-debugserver)
endif()
@@ -126,6 +134,6 @@ endif ()
add_dependencies(check-lldb check-lldb-lit)
add_custom_target(lldb-test-depends DEPENDS ${LLDB_TEST_DEPENDS})
-# This will add LLDB's test dependencies to the depenednecies for check-all and
+# This will add LLDB's test dependencies to the dependencies for check-all and
# include them in the test-depends target.
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS})
diff --git a/test/use_lldb_suite.py b/test/use_lldb_suite.py
index 6e24b9da8d34..6a8c12d81898 100644
--- a/test/use_lldb_suite.py
+++ b/test/use_lldb_suite.py
@@ -4,7 +4,9 @@ import sys
def find_lldb_root():
- lldb_root = os.path.dirname(inspect.getfile(inspect.currentframe()))
+ lldb_root = os.path.dirname(
+ os.path.abspath(inspect.getfile(inspect.currentframe()))
+ )
while True:
lldb_root = os.path.dirname(lldb_root)
if lldb_root is None:
diff --git a/third_party/Python/module/unittest2/unittest2/result.py b/third_party/Python/module/unittest2/unittest2/result.py
index 9d76429fb4ad..8f89816b772f 100644
--- a/third_party/Python/module/unittest2/unittest2/result.py
+++ b/third_party/Python/module/unittest2/unittest2/result.py
@@ -148,7 +148,9 @@ class TestResult(unittest.TestResult):
def wasSuccessful(self):
"Tells whether or not this result was a success"
- return (len(self.failures) + len(self.errors) == 0)
+ return (len(self.failures) +
+ len(self.errors) +
+ len(self.unexpectedSuccesses) == 0)
def stop(self):
"Indicates that the tests should be aborted"
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 75c9c15c487d..8be67393bef0 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,12 +1,15 @@
+add_subdirectory(argdumper)
+add_subdirectory(driver)
+add_subdirectory(intel-features)
+add_subdirectory(lldb-mi)
+add_subdirectory(lldb-test)
+add_subdirectory(lldb-vscode)
+
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(darwin-debug)
add_subdirectory(debugserver)
endif()
-add_subdirectory(argdumper)
-add_subdirectory(driver)
-add_subdirectory(lldb-mi)
-if (LLDB_CAN_USE_LLDB_SERVER)
+
+if (LLDB_CAN_USE_LLDB_SERVER AND NOT SKIP_LLDB_SERVER_BUILD)
add_subdirectory(lldb-server)
endif()
-add_subdirectory(intel-features)
-add_subdirectory(lldb-test)
diff --git a/tools/argdumper/CMakeLists.txt b/tools/argdumper/CMakeLists.txt
index a59a4e7a8514..71c73cc195c2 100644
--- a/tools/argdumper/CMakeLists.txt
+++ b/tools/argdumper/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_lldb_tool(lldb-argdumper INCLUDE_IN_SUITE
+add_lldb_tool(lldb-argdumper
argdumper.cpp
LINK_LIBS
diff --git a/tools/darwin-debug/CMakeLists.txt b/tools/darwin-debug/CMakeLists.txt
index c2b5cb486483..5be6e4ee4598 100644
--- a/tools/darwin-debug/CMakeLists.txt
+++ b/tools/darwin-debug/CMakeLists.txt
@@ -1,3 +1,3 @@
-add_lldb_tool(darwin-debug INCLUDE_IN_SUITE
+add_lldb_tool(darwin-debug
darwin-debug.cpp
)
diff --git a/tools/darwin-debug/darwin-debug.cpp b/tools/darwin-debug/darwin-debug.cpp
index e754ded474c4..31b04bcde9be 100644
--- a/tools/darwin-debug/darwin-debug.cpp
+++ b/tools/darwin-debug/darwin-debug.cpp
@@ -24,7 +24,7 @@
//----------------------------------------------------------------------
#if defined(__APPLE__)
-#include <crt_externs.h> // for _NSGetEnviron()
+#include <crt_externs.h>
#include <getopt.h>
#include <limits.h>
#include <mach/machine.h>
diff --git a/tools/debugserver/CMakeLists.txt b/tools/debugserver/CMakeLists.txt
index ae436b8f07c3..1dc32434ba40 100644
--- a/tools/debugserver/CMakeLists.txt
+++ b/tools/debugserver/CMakeLists.txt
@@ -8,8 +8,9 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
"${CMAKE_SOURCE_DIR}/../../cmake"
"${CMAKE_SOURCE_DIR}/../../cmake/modules"
)
-
+
include(LLDBStandalone)
+ include(debugserverConfig)
include(AddLLDB)
set(LLDB_SOURCE_DIR "${CMAKE_SOURCE_DIR}/../../")
diff --git a/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/tools/debugserver/debugserver.xcodeproj/project.pbxproj
index 92b41b1873ab..f4267b7633a2 100644
--- a/tools/debugserver/debugserver.xcodeproj/project.pbxproj
+++ b/tools/debugserver/debugserver.xcodeproj/project.pbxproj
@@ -710,12 +710,9 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 0;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "";
STRIP_INSTALLED_PRODUCT = NO;
@@ -749,13 +746,10 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 0;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "";
STRIPFLAGS = "-x";
@@ -790,12 +784,9 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 1;
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = "";
STRIPFLAGS = "-x";
STRIP_STYLE = debugging;
@@ -828,20 +819,15 @@
HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_PATH = /usr/bin;
"INSTALL_PATH[sdk=iphoneos*]" = /Developer/usr/bin/;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"$(LLDB_ENERGY_CFLAGS)",
"-DDT_VARIANT_$(DT_VARIANT)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*]" = (
@@ -851,8 +837,6 @@
"-DWITH_BKS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -871,7 +855,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -880,7 +863,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = debugserver;
@@ -916,20 +898,15 @@
GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/bin;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"-DDT_VARIANT_$(DT_VARIANT)",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -939,8 +916,6 @@
"-DWITH_FBS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -959,7 +934,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -967,7 +941,6 @@
__info_plist,
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
@@ -1003,20 +976,15 @@
GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_RELEASE;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/bin;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"-DDT_VARIANT_$(DT_VARIANT)",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -1026,8 +994,6 @@
"-DWITH_BKS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -1046,7 +1012,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -1055,7 +1020,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = debugserver;
@@ -1107,21 +1071,16 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
INSTALL_PATH = /usr/local/bin;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"-Wparentheses",
"-DDT_VARIANT_$(DT_VARIANT)",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -1130,7 +1089,6 @@
"-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui",
"$(LLDB_ENERGY_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
);
"OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)";
OTHER_LDFLAGS = "";
@@ -1191,8 +1149,6 @@
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
OTHER_CFLAGS = (
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
"-Wparentheses",
@@ -1215,7 +1171,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = "debugserver-nonui";
@@ -1251,7 +1206,6 @@
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_PATH = /usr/local/bin;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
@@ -1259,8 +1213,6 @@
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
OTHER_CFLAGS = (
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui",
"$(LLDB_OS_LOG_CFLAGS)",
);
@@ -1269,7 +1221,6 @@
"-DOS_OBJECT_USE_OBJC=0",
"-DDEBUGSERVER_PROGRAM_SYMBOL=debugserver_nonui",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CPLUSPLUSFLAGS[sdk=iphoneos*][arch=*]" = "$(OTHER_CFLAGS)";
@@ -1279,7 +1230,6 @@
Foundation,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -1288,7 +1238,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = "debugserver-nonui";
@@ -1391,7 +1340,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 0;
@@ -1426,20 +1374,15 @@
GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/bin;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"-DDT_VARIANT_$(DT_VARIANT)",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -1449,8 +1392,6 @@
"-DWITH_BKS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -1468,7 +1409,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -1477,7 +1417,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = debugserver;
@@ -1516,7 +1455,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 0;
@@ -1551,19 +1489,14 @@
GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/bin;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -1573,8 +1506,6 @@
"-DWITH_BKS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -1592,7 +1523,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -1601,7 +1531,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = debugserver;
@@ -1716,7 +1645,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 0;
@@ -1751,20 +1679,15 @@
GCC_PREPROCESSOR_DEFINITIONS = LLDB_DEBUGSERVER_DEBUG;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
INSTALL_PATH = /usr/bin;
- LLDB_COMPRESSION_CFLAGS = "";
- LLDB_COMPRESSION_LDFLAGS = "";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"-DDT_VARIANT_$(DT_VARIANT)",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -1774,8 +1697,6 @@
"-DWITH_FBS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -1794,7 +1715,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -1803,7 +1723,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = debugserver;
@@ -1841,7 +1760,6 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- LLDB_COMPRESSION_CFLAGS = "-DHAVE_LIBCOMPRESSION=1";
LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_OS_LOG_CFLAGS = "-DLLDB_USE_OS_LOG=$(LLDB_USE_OS_LOG)";
LLDB_USE_OS_LOG = 0;
@@ -1877,20 +1795,15 @@
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
HEADER_SEARCH_PATHS = /System/Library/Frameworks/System.framework/PrivateHeaders;
INSTALL_PATH = /usr/bin;
- LLDB_COMPRESSION_CFLAGS = "";
- LLDB_COMPRESSION_LDFLAGS = "";
+ LLDB_COMPRESSION_LDFLAGS = "-lcompression";
LLDB_DEBUGSERVER = 1;
LLDB_ENERGY_CFLAGS = "";
"LLDB_ENERGY_CFLAGS[sdk=*.internal]" = "-DLLDB_ENERGY";
LLDB_ENERGY_LDFLAGS = "-lpmenergy -lpmsample";
- LLDB_ZLIB_CFLAGS = "-DHAVE_LIBZ=1";
- LLDB_ZLIB_LDFLAGS = "-lz";
OTHER_CFLAGS = (
"-Wparentheses",
"-DDT_VARIANT_$(DT_VARIANT)",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
);
"OTHER_CFLAGS[sdk=iphoneos*][arch=*]" = (
@@ -1900,8 +1813,6 @@
"-DWITH_BKS",
"-DOS_OBJECT_USE_OBJC=0",
"$(LLDB_ENERGY_CFLAGS)",
- "$(LLDB_COMPRESSION_CFLAGS)",
- "$(LLDB_ZLIB_CFLAGS)",
"$(LLDB_OS_LOG_CFLAGS)",
"-isystem",
"$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
@@ -1919,7 +1830,6 @@
MobileCoreServices,
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
"OTHER_LDFLAGS[sdk=macosx*]" = (
"-sectcreate",
@@ -1928,7 +1838,6 @@
"$(PROJECT_DIR)/resources/lldb-debugserver-Info.plist",
"$(LLDB_ENERGY_LDFLAGS)",
"$(LLDB_COMPRESSION_LDFLAGS)",
- "$(LLDB_ZLIB_LDFLAGS)",
);
OTHER_MIGFLAGS = "-I$(DERIVED_FILE_DIR)";
PRODUCT_NAME = debugserver;
diff --git a/tools/debugserver/source/CMakeLists.txt b/tools/debugserver/source/CMakeLists.txt
index ec136039d349..860a0289d22c 100644
--- a/tools/debugserver/source/CMakeLists.txt
+++ b/tools/debugserver/source/CMakeLists.txt
@@ -5,7 +5,6 @@ include_directories(${LLDB_SOURCE_DIR}/source)
include_directories(MacOSX/DarwinLog)
include_directories(MacOSX)
-#include_directories(${CMAKE_CURRENT_BINARY_DIR}/MacOSX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/../resources/lldb-debugserver-Info.plist")
@@ -94,32 +93,121 @@ set(lldbDebugserverCommonSources
add_library(lldbDebugserverCommon ${lldbDebugserverCommonSources})
+# LLDB-specific identity, currently used for code signing debugserver.
+set(LLDB_CODESIGN_IDENTITY "" CACHE STRING
+ "Override code sign identity for debugserver and for use in tests; falls back to LLVM_CODESIGNING_IDENTITY if set or lldb_codesign otherwise (Darwin only)")
-set(LLDB_CODESIGN_IDENTITY "lldb_codesign"
- CACHE STRING "Identity used for code signing. Set to empty string to skip the signing step.")
-
-if(NOT LLDB_CODESIGN_IDENTITY STREQUAL "")
- set(DEBUGSERVER_PATH ${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver${CMAKE_EXECUTABLE_SUFFIX} CACHE PATH "Path to debugserver.")
- set(SKIP_DEBUGSERVER OFF CACHE BOOL "Skip building the in-tree debug server")
+# Determine which identity to use and store it in the separate cache entry.
+# We will query it later for LLDB_TEST_COMMON_ARGS.
+if(LLDB_CODESIGN_IDENTITY)
+ set(LLDB_CODESIGN_IDENTITY_USED ${LLDB_CODESIGN_IDENTITY} CACHE INTERNAL "" FORCE)
+elseif(LLVM_CODESIGNING_IDENTITY)
+ set(LLDB_CODESIGN_IDENTITY_USED ${LLVM_CODESIGNING_IDENTITY} CACHE INTERNAL "" FORCE)
else()
+ set(LLDB_CODESIGN_IDENTITY_USED lldb_codesign CACHE INTERNAL "" FORCE)
+endif()
+
+# Override locally, so the identity is used for targets created in this scope.
+set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY_USED})
+
+option(LLDB_NO_DEBUGSERVER "Disable the debugserver target" OFF)
+option(LLDB_USE_SYSTEM_DEBUGSERVER "Use the system's debugserver instead of building it from source (Darwin only)." OFF)
+
+# Incompatible options
+if(LLDB_NO_DEBUGSERVER AND LLDB_USE_SYSTEM_DEBUGSERVER)
+ message(FATAL_ERROR "Inconsistent options: LLDB_NO_DEBUGSERVER and LLDB_USE_SYSTEM_DEBUGSERVER")
+endif()
+
+# Try to locate the system debugserver.
+# Subsequent feasibility checks depend on it.
+if(APPLE AND CMAKE_HOST_APPLE)
execute_process(
COMMAND xcode-select -p
- OUTPUT_VARIABLE XCODE_DEV_DIR)
- string(STRIP ${XCODE_DEV_DIR} XCODE_DEV_DIR)
- if(EXISTS "${XCODE_DEV_DIR}/../SharedFrameworks/LLDB.framework/")
- set(DEBUGSERVER_PATH
- "${XCODE_DEV_DIR}/../SharedFrameworks/LLDB.framework/Resources/debugserver" CACHE PATH "Path to debugserver.")
- elseif(EXISTS "${XCODE_DEV_DIR}/Library/PrivateFrameworks/LLDB.framework/")
- set(DEBUGSERVER_PATH
- "${XCODE_DEV_DIR}/Library/PrivateFrameworks/LLDB.framework/Resources/debugserver" CACHE PATH "Path to debugserver.")
+ OUTPUT_VARIABLE xcode_dev_dir)
+ string(STRIP ${xcode_dev_dir} xcode_dev_dir)
+
+ set(debugserver_rel_path "LLDB.framework/Resources/debugserver")
+ set(debugserver_shared "${xcode_dev_dir}/../SharedFrameworks/${debugserver_rel_path}")
+ set(debugserver_private "${xcode_dev_dir}/Library/PrivateFrameworks/${debugserver_rel_path}")
+
+ if(EXISTS ${debugserver_shared})
+ set(system_debugserver ${debugserver_shared})
+ elseif(EXISTS ${debugserver_private})
+ set(system_debugserver ${debugserver_private})
+ endif()
+endif()
+
+# Handle unavailability
+if(LLDB_USE_SYSTEM_DEBUGSERVER)
+ if(system_debugserver)
+ set(use_system_debugserver ON)
+ elseif(APPLE AND CMAKE_HOST_APPLE)
+ # Binary not found on system. Keep cached variable, to try again on reconfigure.
+ message(SEND_ERROR
+ "LLDB_USE_SYSTEM_DEBUGSERVER option set, but no debugserver found in:\
+ ${debugserver_shared}\
+ ${debugserver_private}")
else()
- message(SEND_ERROR "Cannot find debugserver on system.")
+ # Non-Apple target platform or non-Darwin host. Reset invalid cached variable.
+ message(WARNING "Reverting invalid option LLDB_USE_SYSTEM_DEBUGSERVER (Darwin only)")
+ set(LLDB_USE_SYSTEM_DEBUGSERVER OFF CACHE BOOL "" FORCE)
endif()
- set(SKIP_DEBUGSERVER ON CACHE BOOL "Skip building the in-tree debug server")
+elseif(NOT LLDB_NO_DEBUGSERVER)
+ # Default case: on Darwin we need the right code signing ID.
+ # See lldb/docs/code-signing.txt for details.
+ if(CMAKE_HOST_APPLE AND NOT LLVM_CODESIGNING_IDENTITY STREQUAL "lldb_codesign")
+ set(problem "Cannot code sign debugserver with LLVM_CODESIGNING_IDENTITY '${LLVM_CODESIGNING_IDENTITY}'.")
+ set(advice "Pass -DLLDB_CODESIGN_IDENTITY=lldb_codesign to override the LLVM value for debugserver.")
+ if(system_debugserver)
+ set(effect "Will fall back to system's debugserver.")
+ set(use_system_debugserver ON)
+ else()
+ set(effect "debugserver will not be available.")
+ endif()
+ message(WARNING "${problem} ${effect} ${advice}")
+ else()
+ set(build_and_sign_debugserver ON)
+ endif()
+endif()
+
+# TODO: We don't use the $<TARGET_FILE:debugserver> generator expression here,
+# because the value of DEBUGSERVER_PATH is used to build LLDB_DOTEST_ARGS,
+# which is used for configuring lldb-dotest.in, which does not have a generator
+# step at the moment.
+set(default_debugserver_path "${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver${CMAKE_EXECUTABLE_SUFFIX}")
+
+# Remember where debugserver binary goes and whether or not we have to test it.
+set(DEBUGSERVER_PATH "" CACHE FILEPATH "Path to debugserver")
+set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "Building the in-tree debugserver was skipped")
+
+# Reset values in all cases in order to correctly support reconfigurations.
+if(use_system_debugserver)
+ add_custom_target(debugserver
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different
+ ${system_debugserver} ${LLVM_RUNTIME_OUTPUT_INTDIR}
+ COMMENT "Copying the system debugserver to LLDB's binaries directory.")
+
+ # Don't test debugserver itself.
+ # Tests that require debugserver will use the copy.
+ set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE)
+ set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE)
+
+ message(STATUS "Copy system debugserver from: ${system_debugserver}")
+elseif(build_and_sign_debugserver)
+ # Build, sign and test debugserver (below)
+ set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE)
+ set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "" FORCE)
+
+ message(STATUS "lldb debugserver: ${DEBUGSERVER_PATH}")
+else()
+ # No tests for debugserver, no tests that require it.
+ set(DEBUGSERVER_PATH "" CACHE FILEPATH "" FORCE)
+ set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE)
+
+ message(STATUS "lldb debugserver will not be available.")
endif()
-message(STATUS "Path to the lldb debugserver: ${DEBUGSERVER_PATH}")
-if (APPLE)
+if(APPLE)
if(IOS)
find_library(BACKBOARD_LIBRARY BackBoardServices
PATHS ${CMAKE_OSX_SYSROOT}/System/Library/PrivateFrameworks)
@@ -132,7 +220,7 @@ if (APPLE)
find_library(LOCKDOWN_LIBRARY lockdown)
if(NOT BACKBOARD_LIBRARY)
- set(SKIP_DEBUGSERVER ON CACHE BOOL "Skip building the in-tree debug server" FORCE)
+ set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE)
endif()
else()
find_library(COCOA_LIBRARY Cocoa)
@@ -143,7 +231,16 @@ if(HAVE_LIBCOMPRESSION)
set(LIBCOMPRESSION compression)
endif()
-if(NOT SKIP_DEBUGSERVER)
+if(LLDB_USE_ENTITLEMENTS)
+ if(IOS)
+ set(entitlements ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-entitlements.plist)
+ else()
+ # Same entitlements file as used for lldb-server
+ set(entitlements ${LLDB_SOURCE_DIR}/resources/debugserver-macosx-entitlements.plist)
+ endif()
+endif()
+
+if(build_and_sign_debugserver)
target_link_libraries(lldbDebugserverCommon
INTERFACE ${COCOA_LIBRARY}
${CORE_FOUNDATION_LIBRARY}
@@ -161,11 +258,14 @@ if(NOT SKIP_DEBUGSERVER)
COMPILE_DEFINITIONS HAVE_LIBCOMPRESSION)
endif()
set(LLVM_OPTIONAL_SOURCES ${lldbDebugserverCommonSources})
- add_lldb_tool(debugserver INCLUDE_IN_SUITE
+ add_lldb_tool(debugserver
debugserver.cpp
LINK_LIBS
lldbDebugserverCommon
+
+ ENTITLEMENTS
+ ${entitlements}
)
if(IOS)
set_property(TARGET lldbDebugserverCommon APPEND PROPERTY COMPILE_DEFINITIONS
@@ -203,56 +303,8 @@ if(IOS)
LINK_LIBS
lldbDebugserverCommon_NonUI
- )
-endif()
-
-set(entitlements_xml ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-macosx-entitlements.plist)
-if(IOS)
- set(entitlements_xml ${CMAKE_CURRENT_SOURCE_DIR}/debugserver-entitlements.plist)
-else()
- set(entitlements_xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../resources/debugserver-macosx-entitlements.plist)
-endif()
-
-set(LLDB_USE_ENTITLEMENTS_Default On)
-option(LLDB_USE_ENTITLEMENTS "Use entitlements when codesigning (Defaults Off when using lldb_codesign identity, otherwise On)" ${LLDB_USE_ENTITLEMENTS_Default})
-if (SKIP_DEBUGSERVER)
- if (CMAKE_HOST_APPLE)
- # If we haven't built a signed debugserver, copy the one from the system.
- add_custom_target(debugserver
- COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEBUGSERVER_PATH} ${CMAKE_BINARY_DIR}/bin
- VERBATIM
- COMMENT "Copying the system debugserver to LLDB's binaries directory.")
- endif()
-else()
- if(LLDB_USE_ENTITLEMENTS)
- set(entitlements_flags --entitlements ${entitlements_xml})
- endif()
- execute_process(
- COMMAND xcrun -f codesign_allocate
- OUTPUT_STRIP_TRAILING_WHITESPACE
- OUTPUT_VARIABLE CODESIGN_ALLOCATE
- )
- add_custom_command(TARGET debugserver
- POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE}
- codesign --force --sign ${LLDB_CODESIGN_IDENTITY}
- ${entitlements_flags}
- $<TARGET_FILE:debugserver>
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
- )
- if(IOS)
- add_custom_command(TARGET debugserver-nonui
- POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E env CODESIGN_ALLOCATE=${CODESIGN_ALLOCATE}
- codesign --force --sign ${LLDB_CODESIGN_IDENTITY}
- ${entitlements_flags}
- $<TARGET_FILE:debugserver>
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
+ ENTITLEMENTS
+ ${entitlements}
)
- endif()
endif()
-
-
-
-
diff --git a/tools/debugserver/source/DNBRegisterInfo.cpp b/tools/debugserver/source/DNBRegisterInfo.cpp
index b85b39378183..d0f6063fbce0 100644
--- a/tools/debugserver/source/DNBRegisterInfo.cpp
+++ b/tools/debugserver/source/DNBRegisterInfo.cpp
@@ -156,6 +156,7 @@ void DNBRegisterValueClass::Dump(const char *pre, const char *post) const {
DNBLogError(
"unsupported vector format %d, defaulting to hex bytes.",
info.format);
+ [[clang::fallthrough]];
case VectorOfUInt8:
snprintf(str, sizeof(str), "%s", "uint8 { ");
pos = str + strlen(str);
diff --git a/tools/debugserver/source/JSONGenerator.h b/tools/debugserver/source/JSONGenerator.h
index 7af6ae60c5f7..0ac5e0bb768c 100644
--- a/tools/debugserver/source/JSONGenerator.h
+++ b/tools/debugserver/source/JSONGenerator.h
@@ -10,8 +10,6 @@
#ifndef __JSONGenerator_h_
#define __JSONGenerator_h_
-// C Includes
-// C++ Includes
#include <iomanip>
#include <sstream>
@@ -184,7 +182,7 @@ public:
void SetValue(bool value) { m_value = value; }
void Dump(std::ostream &s) const override {
- if (m_value == true)
+ if (m_value)
s << "true";
else
s << "false";
@@ -264,7 +262,7 @@ public:
s << "{";
for (collection::const_iterator iter = m_dict.begin();
iter != m_dict.end(); ++iter) {
- if (have_printed_one_elem == false) {
+ if (!have_printed_one_elem) {
have_printed_one_elem = true;
} else {
s << ",";
diff --git a/tools/debugserver/source/MacOSX/Genealogy.cpp b/tools/debugserver/source/MacOSX/Genealogy.cpp
index 22ff52abaa47..1473a53fcbea 100644
--- a/tools/debugserver/source/MacOSX/Genealogy.cpp
+++ b/tools/debugserver/source/MacOSX/Genealogy.cpp
@@ -74,8 +74,7 @@ Genealogy::GetGenealogyInfoForThread(pid_t pid, nub_thread_t tid,
// (else we'll need to hit the timeout for every thread we're asked about.)
// We'll try again at the next public stop.
- if (m_thread_activities.size() == 0 &&
- m_diagnosticd_call_timed_out == false) {
+ if (m_thread_activities.size() == 0 && !m_diagnosticd_call_timed_out) {
GetActivities(pid, thread_list, task);
}
std::map<nub_thread_t, ThreadActivitySP>::const_iterator search;
diff --git a/tools/debugserver/source/MacOSX/MachException.cpp b/tools/debugserver/source/MacOSX/MachException.cpp
index da2b2fe92980..01e5892d487d 100644
--- a/tools/debugserver/source/MacOSX/MachException.cpp
+++ b/tools/debugserver/source/MacOSX/MachException.cpp
@@ -386,24 +386,29 @@ void MachException::Data::Dump() const {
}
}
-#define PREV_EXC_MASK_ALL \
- (EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | \
- EXC_MASK_EMULATION | EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT | \
- EXC_MASK_SYSCALL | EXC_MASK_MACH_SYSCALL | EXC_MASK_RPC_ALERT | \
- EXC_MASK_MACHINE)
-
-// Don't listen for EXC_RESOURCE, it should really get handled by the system
-// handler.
-
-#ifndef EXC_RESOURCE
-#define EXC_RESOURCE 11
-#endif
-
-#ifndef EXC_MASK_RESOURCE
-#define EXC_MASK_RESOURCE (1 << EXC_RESOURCE)
-#endif
-
-#define LLDB_EXC_MASK (EXC_MASK_ALL & ~EXC_MASK_RESOURCE)
+// The EXC_MASK_ALL value hard-coded here so that lldb can be built
+// on a new OS with an older deployment target . The new OS may have
+// an addition to its EXC_MASK_ALL that the old OS will not recognize -
+// <mach/exception_types.h> doesn't vary the value based on the deployment
+// target. So we need a known set of masks that can be assumed to be
+// valid when running on an older OS. We'll fall back to trying
+// PREV_EXC_MASK_ALL if the EXC_MASK_ALL value lldb was compiled with is
+// not recognized.
+
+#define PREV_EXC_MASK_ALL (EXC_MASK_BAD_ACCESS | \
+ EXC_MASK_BAD_INSTRUCTION | \
+ EXC_MASK_ARITHMETIC | \
+ EXC_MASK_EMULATION | \
+ EXC_MASK_SOFTWARE | \
+ EXC_MASK_BREAKPOINT | \
+ EXC_MASK_SYSCALL | \
+ EXC_MASK_MACH_SYSCALL | \
+ EXC_MASK_RPC_ALERT | \
+ EXC_MASK_RESOURCE | \
+ EXC_MASK_GUARD | \
+ EXC_MASK_MACHINE)
+
+#define LLDB_EXC_MASK EXC_MASK_ALL
kern_return_t MachException::PortInfo::Save(task_t task) {
DNBLogThreadedIf(LOG_EXCEPTIONS | LOG_VERBOSE,
@@ -485,9 +490,21 @@ const char *MachException::Name(exception_type_t exc_type) {
return "EXC_MACH_SYSCALL";
case EXC_RPC_ALERT:
return "EXC_RPC_ALERT";
-#ifdef EXC_CRASH
case EXC_CRASH:
return "EXC_CRASH";
+ case EXC_RESOURCE:
+ return "EXC_RESOURCE";
+#ifdef EXC_GUARD
+ case EXC_GUARD:
+ return "EXC_GUARD";
+#endif
+#ifdef EXC_CORPSE_NOTIFY
+ case EXC_CORPSE_NOTIFY:
+ return "EXC_CORPSE_NOTIFY";
+#endif
+#ifdef EXC_CORPSE_VARIANT_BIT
+ case EXC_CORPSE_VARIANT_BIT:
+ return "EXC_CORPSE_VARIANT_BIT";
#endif
default:
break;
diff --git a/tools/debugserver/source/MacOSX/MachProcess.mm b/tools/debugserver/source/MacOSX/MachProcess.mm
index 4ddc5f8b10dc..a3b905d05150 100644
--- a/tools/debugserver/source/MacOSX/MachProcess.mm
+++ b/tools/debugserver/source/MacOSX/MachProcess.mm
@@ -783,8 +783,8 @@ JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON(
uuid_unparse_upper(image_infos[i].macho_info.uuid, uuidstr);
image_info_dict_sp->AddStringItem("uuid", uuidstr);
- if (image_infos[i].macho_info.min_version_os_name.empty() == false &&
- image_infos[i].macho_info.min_version_os_version.empty() == false) {
+ if (!image_infos[i].macho_info.min_version_os_name.empty() &&
+ !image_infos[i].macho_info.min_version_os_version.empty()) {
image_info_dict_sp->AddStringItem(
"min_version_os_name", image_infos[i].macho_info.min_version_os_name);
image_info_dict_sp->AddStringItem(
@@ -803,6 +803,8 @@ JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON(
(uint32_t)image_infos[i].macho_info.mach_header.cpusubtype);
mach_header_dict_sp->AddIntegerItem(
"filetype", image_infos[i].macho_info.mach_header.filetype);
+ mach_header_dict_sp->AddIntegerItem ("flags",
+ image_infos[i].macho_info.mach_header.flags);
// DynamicLoaderMacOSX doesn't currently need these fields, so
// don't send them.
@@ -810,8 +812,6 @@ JSONGenerator::ObjectSP MachProcess::FormatDynamicLibrariesIntoJSON(
// image_infos[i].macho_info.mach_header.ncmds);
// mach_header_dict_sp->AddIntegerItem ("sizeofcmds",
// image_infos[i].macho_info.mach_header.sizeofcmds);
- // mach_header_dict_sp->AddIntegerItem ("flags",
- // image_infos[i].macho_info.mach_header.flags);
image_info_dict_sp->AddItem("mach_header", mach_header_dict_sp);
JSONGenerator::ArraySP segments_sp(new JSONGenerator::Array());
@@ -1602,7 +1602,7 @@ nub_size_t MachProcess::WriteMemory(nub_addr_t addr, nub_size_t size,
void MachProcess::ReplyToAllExceptions() {
PTHREAD_MUTEX_LOCKER(locker, m_exception_messages_mutex);
- if (m_exception_messages.empty() == false) {
+ if (!m_exception_messages.empty()) {
MachException::Message::iterator pos;
MachException::Message::iterator begin = m_exception_messages.begin();
MachException::Message::iterator end = m_exception_messages.end();
@@ -1774,7 +1774,7 @@ bool MachProcess::DisableBreakpoint(nub_addr_t addr, bool remove) {
if (bp->IsHardware()) {
bool hw_disable_result = m_thread_list.DisableHardwareBreakpoint(bp);
- if (hw_disable_result == true) {
+ if (hw_disable_result) {
bp->SetEnabled(false);
// Let the thread list know that a breakpoint has been modified
if (remove) {
@@ -1909,7 +1909,7 @@ bool MachProcess::DisableWatchpoint(nub_addr_t addr, bool remove) {
if (wp->IsHardware()) {
bool hw_disable_result = m_thread_list.DisableHardwareWatchpoint(wp);
- if (hw_disable_result == true) {
+ if (hw_disable_result) {
wp->SetEnabled(false);
if (remove)
m_watchpoints.Remove(addr);
@@ -2179,7 +2179,7 @@ task_t MachProcess::ExceptionMessageBundleComplete() {
m_thread_list.Dump();
bool step_more = false;
- if (m_thread_list.ShouldStop(step_more) && auto_resume == false) {
+ if (m_thread_list.ShouldStop(step_more) && !auto_resume) {
// Wait for the eEventProcessRunningStateChanged event to be reset
// before changing state to stopped to avoid race condition with
// very fast start/stops
diff --git a/tools/debugserver/source/MacOSX/MachTask.h b/tools/debugserver/source/MacOSX/MachTask.h
index 1e0e2af9a92b..1fe74ddec56c 100644
--- a/tools/debugserver/source/MacOSX/MachTask.h
+++ b/tools/debugserver/source/MacOSX/MachTask.h
@@ -18,14 +18,10 @@
#ifndef __MachTask_h__
#define __MachTask_h__
-// C Includes
#include <mach/mach.h>
#include <sys/socket.h>
-// C++ Includes
#include <map>
#include <string>
-// Other libraries and framework includes
-// Project includes
#include "DNBDefs.h"
#include "MachException.h"
#include "MachVMMemory.h"
diff --git a/tools/debugserver/source/MacOSX/MachThread.cpp b/tools/debugserver/source/MacOSX/MachThread.cpp
index fc97825786a0..062e1c3d9edf 100644
--- a/tools/debugserver/source/MacOSX/MachThread.cpp
+++ b/tools/debugserver/source/MacOSX/MachThread.cpp
@@ -83,7 +83,7 @@ bool MachThread::SetSuspendCountBeforeResume(bool others_stopped) {
DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )",
__FUNCTION__);
DNBError err;
- if (MachPortNumberIsValid(m_mach_port_number) == false)
+ if (!MachPortNumberIsValid(m_mach_port_number))
return false;
integer_t times_to_resume;
@@ -121,7 +121,7 @@ bool MachThread::RestoreSuspendCountAfterStop() {
DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThread::%s ( )",
__FUNCTION__);
DNBError err;
- if (MachPortNumberIsValid(m_mach_port_number) == false)
+ if (!MachPortNumberIsValid(m_mach_port_number))
return false;
if (m_suspend_count > 0) {
diff --git a/tools/debugserver/source/MacOSX/MachVMRegion.cpp b/tools/debugserver/source/MacOSX/MachVMRegion.cpp
index c011c133ac38..172fc7867b57 100644
--- a/tools/debugserver/source/MacOSX/MachVMRegion.cpp
+++ b/tools/debugserver/source/MacOSX/MachVMRegion.cpp
@@ -166,10 +166,7 @@ bool MachVMRegion::GetRegionForAddress(nub_addr_t addr) {
// doesn't mean that "addr" is in the range. The data in this object will
// be valid though, so you could see where the next region begins. So we
// return false, yet leave "m_err" with a successfull return code.
- if ((addr < m_start) || (addr >= (m_start + m_size)))
- return false;
-
- return true;
+ return !((addr < m_start) || (addr >= (m_start + m_size)));
}
uint32_t MachVMRegion::GetDNBPermissions() const {
diff --git a/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
index adcd65002191..ba37a328ecf3 100644
--- a/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
+++ b/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
@@ -889,10 +889,7 @@ bool DNBArchImplI386::RollbackTransForHWP() {
LOG_WATCHPOINTS,
"DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
- if (kret == KERN_SUCCESS)
- return true;
- else
- return false;
+ return kret == KERN_SUCCESS;
}
bool DNBArchImplI386::FinishTransForHWP() {
m_2pc_trans_state = Trans_Done;
@@ -918,7 +915,7 @@ uint32_t DNBArchImplI386::EnableHardwareWatchpoint(nub_addr_t addr,
return INVALID_NUB_HW_INDEX;
// We must watch for either read or write
- if (read == false && write == false)
+ if (!read && !write)
return INVALID_NUB_HW_INDEX;
// Read the debug state
diff --git a/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
index f0a3d2b001b2..2f8ed32fa5d0 100644
--- a/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
+++ b/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp
@@ -844,10 +844,7 @@ bool DNBArchImplX86_64::RollbackTransForHWP() {
"DNBArchImplX86_64::RollbackTransForHWP() SetDBGState() => 0x%8.8x.",
kret);
- if (kret == KERN_SUCCESS)
- return true;
- else
- return false;
+ return kret == KERN_SUCCESS;
}
bool DNBArchImplX86_64::FinishTransForHWP() {
m_2pc_trans_state = Trans_Done;
@@ -873,7 +870,7 @@ uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr,
return INVALID_NUB_HW_INDEX;
// We must watch for either read or write
- if (read == false && write == false)
+ if (!read && !write)
return INVALID_NUB_HW_INDEX;
// Read the debug state
diff --git a/tools/debugserver/source/PThreadMutex.cpp b/tools/debugserver/source/PThreadMutex.cpp
index 32db862f6b42..0e9132e380bf 100644
--- a/tools/debugserver/source/PThreadMutex.cpp
+++ b/tools/debugserver/source/PThreadMutex.cpp
@@ -13,10 +13,6 @@
#include "PThreadMutex.h"
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "DNBTimer.h"
#if defined(DEBUG_PTHREAD_MUTEX_DEADLOCKS)
diff --git a/tools/debugserver/source/RNBRemote.cpp b/tools/debugserver/source/RNBRemote.cpp
index 8ba06be1d6ad..f611ec0d2199 100644
--- a/tools/debugserver/source/RNBRemote.cpp
+++ b/tools/debugserver/source/RNBRemote.cpp
@@ -42,15 +42,9 @@
#include "RNBSocket.h"
#include "StdStringExtractor.h"
-#if defined(HAVE_LIBCOMPRESSION)
#include <compression.h>
-#endif
-
-#if defined(HAVE_LIBZ)
-#include <zlib.h>
-#endif
-#include <TargetConditionals.h> // for endianness predefines
+#include <TargetConditionals.h>
#include <iomanip>
#include <sstream>
#include <unordered_set>
@@ -709,53 +703,73 @@ std::string RNBRemote::CompressString(const std::string &orig) {
std::vector<uint8_t> encoded_data(encoded_data_buf_size);
size_t compressed_size = 0;
-#if defined(HAVE_LIBCOMPRESSION)
+ // Allocate a scratch buffer for libcompression the first
+ // time we see a different compression type; reuse it in
+ // all compression_encode_buffer calls so it doesn't need
+ // to allocate / free its own scratch buffer each time.
+ // This buffer will only be freed when compression type
+ // changes; otherwise it will persist until debugserver
+ // exit.
+
+ static compression_types g_libcompress_scratchbuf_type = compression_types::none;
+ static void *g_libcompress_scratchbuf = nullptr;
+
+ if (g_libcompress_scratchbuf_type != compression_type) {
+ if (g_libcompress_scratchbuf) {
+ free (g_libcompress_scratchbuf);
+ g_libcompress_scratchbuf = nullptr;
+ }
+ size_t scratchbuf_size = 0;
+ switch (compression_type) {
+ case compression_types::lz4:
+ scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_LZ4_RAW);
+ break;
+ case compression_types::zlib_deflate:
+ scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_ZLIB);
+ break;
+ case compression_types::lzma:
+ scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_LZMA);
+ break;
+ case compression_types::lzfse:
+ scratchbuf_size = compression_encode_scratch_buffer_size (COMPRESSION_LZFSE);
+ break;
+ default:
+ break;
+ }
+ if (scratchbuf_size > 0) {
+ g_libcompress_scratchbuf = (void*) malloc (scratchbuf_size);
+ g_libcompress_scratchbuf_type = compression_type;
+ }
+ }
+
if (compression_type == compression_types::lz4) {
compressed_size = compression_encode_buffer(
encoded_data.data(), encoded_data_buf_size,
- (const uint8_t *)orig.c_str(), orig.size(), nullptr,
+ (const uint8_t *)orig.c_str(), orig.size(),
+ g_libcompress_scratchbuf,
COMPRESSION_LZ4_RAW);
}
if (compression_type == compression_types::zlib_deflate) {
compressed_size = compression_encode_buffer(
encoded_data.data(), encoded_data_buf_size,
- (const uint8_t *)orig.c_str(), orig.size(), nullptr,
+ (const uint8_t *)orig.c_str(), orig.size(),
+ g_libcompress_scratchbuf,
COMPRESSION_ZLIB);
}
if (compression_type == compression_types::lzma) {
compressed_size = compression_encode_buffer(
encoded_data.data(), encoded_data_buf_size,
- (const uint8_t *)orig.c_str(), orig.size(), nullptr,
+ (const uint8_t *)orig.c_str(), orig.size(),
+ g_libcompress_scratchbuf,
COMPRESSION_LZMA);
}
if (compression_type == compression_types::lzfse) {
compressed_size = compression_encode_buffer(
encoded_data.data(), encoded_data_buf_size,
- (const uint8_t *)orig.c_str(), orig.size(), nullptr,
+ (const uint8_t *)orig.c_str(), orig.size(),
+ g_libcompress_scratchbuf,
COMPRESSION_LZFSE);
}
-#endif
-
-#if defined(HAVE_LIBZ)
- if (compressed_size == 0 &&
- compression_type == compression_types::zlib_deflate) {
- z_stream stream;
- memset(&stream, 0, sizeof(z_stream));
- stream.next_in = (Bytef *)orig.c_str();
- stream.avail_in = (uInt)orig.size();
- stream.next_out = (Bytef *)encoded_data.data();
- stream.avail_out = (uInt)encoded_data_buf_size;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
- deflateInit2(&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
- int compress_status = deflate(&stream, Z_FINISH);
- deflateEnd(&stream);
- if (compress_status == Z_STREAM_END && stream.total_out > 0) {
- compressed_size = stream.total_out;
- }
- }
-#endif
if (compressed_size > 0) {
compressed.clear();
@@ -1811,18 +1825,18 @@ rnb_err_t RNBRemote::HandlePacket_qRcmd(const char *p) {
}
if (*c == '\0') {
std::string command = get_identifier(line);
- if (command.compare("set") == 0) {
+ if (command == "set") {
std::string variable = get_identifier(line);
std::string op = get_operator(line);
std::string value = get_value(line);
- if (variable.compare("logfile") == 0) {
+ if (variable == "logfile") {
FILE *log_file = fopen(value.c_str(), "w");
if (log_file) {
DNBLogSetLogCallback(FileLogCallback, log_file);
return SendPacket("OK");
}
return SendPacket("E71");
- } else if (variable.compare("logmask") == 0) {
+ } else if (variable == "logmask") {
char *end;
errno = 0;
uint32_t logmask =
@@ -3413,10 +3427,7 @@ static bool RNBRemoteShouldCancelCallback(void *not_used) {
RNBRemoteSP remoteSP(g_remoteSP);
if (remoteSP.get() != NULL) {
RNBRemote *remote = remoteSP.get();
- if (remote->Comm().IsConnected())
- return false;
- else
- return true;
+ return !remote->Comm().IsConnected();
}
return true;
}
@@ -3614,13 +3625,13 @@ rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) {
bool enable_compression = false;
(void)enable_compression;
-#if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1) || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) || (defined (TARGET_OS_TV) && TARGET_OS_TV == 1)
+#if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1) \
+ || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) \
+ || (defined (TARGET_OS_TV) && TARGET_OS_TV == 1) \
+ || (defined (TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1)
enable_compression = true;
#endif
-#if defined(HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so test if compression_decode_buffer() is
- // available
if (enable_compression) {
strcat(buf, ";SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;"
"DefaultCompressionMinSize=");
@@ -3628,17 +3639,7 @@ rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) {
snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
numbuf[sizeof(numbuf) - 1] = '\0';
strcat(buf, numbuf);
- }
-#elif defined(HAVE_LIBZ)
- if (enable_compression) {
- strcat(buf,
- ";SupportedCompressions=zlib-deflate;DefaultCompressionMinSize=");
- char numbuf[16];
- snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize);
- numbuf[sizeof(numbuf) - 1] = '\0';
- strcat(buf, numbuf);
- }
-#endif
+ }
return SendPacket(buf);
}
@@ -3690,7 +3691,7 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
return HandlePacket_ILLFORMED(
__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
// Fall through to next case...
-
+ [[clang::fallthrough]];
case 'c':
// Continue
thread_action.state = eStateRunning;
@@ -3703,7 +3704,7 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
return HandlePacket_ILLFORMED(
__FILE__, __LINE__, p, "Could not parse signal in vCont packet");
// Fall through to next case...
-
+ [[clang::fallthrough]];
case 's':
// Step
thread_action.state = eStateStepping;
@@ -3817,7 +3818,7 @@ rnb_err_t RNBRemote::HandlePacket_v(const char *p) {
attach_failed_due_to_sip = true;
}
- if (attach_failed_due_to_sip == false) {
+ if (!attach_failed_due_to_sip) {
int csops_flags = 0;
int retval = ::csops(pid_attaching_to, CS_OPS_STATUS, &csops_flags,
sizeof(csops_flags));
@@ -4230,7 +4231,7 @@ rnb_err_t RNBRemote::HandlePacket_GetProfileData(const char *p) {
std::string name;
std::string value;
while (packet.GetNameColonValue(name, value)) {
- if (name.compare("scan_type") == 0) {
+ if (name == "scan_type") {
std::istringstream iss(value);
uint32_t int_value = 0;
if (iss >> std::hex >> int_value) {
@@ -4260,11 +4261,11 @@ rnb_err_t RNBRemote::HandlePacket_SetEnableAsyncProfiling(const char *p) {
std::string name;
std::string value;
while (packet.GetNameColonValue(name, value)) {
- if (name.compare("enable") == 0) {
+ if (name == "enable") {
enable = strtoul(value.c_str(), NULL, 10) > 0;
- } else if (name.compare("interval_usec") == 0) {
+ } else if (name == "interval_usec") {
interval_usec = strtoul(value.c_str(), NULL, 10);
- } else if (name.compare("scan_type") == 0) {
+ } else if (name == "scan_type") {
std::istringstream iss(value);
uint32_t int_value = 0;
if (iss >> std::hex >> int_value) {
@@ -4306,7 +4307,6 @@ rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
}
}
-#if defined(HAVE_LIBCOMPRESSION)
if (strstr(p, "type:zlib-deflate;") != nullptr) {
EnableCompressionNextSendPacket(compression_types::zlib_deflate);
m_compression_minsize = new_compression_minsize;
@@ -4324,15 +4324,6 @@ rnb_err_t RNBRemote::HandlePacket_QEnableCompression(const char *p) {
m_compression_minsize = new_compression_minsize;
return SendPacket("OK");
}
-#endif
-
-#if defined(HAVE_LIBZ)
- if (strstr(p, "type:zlib-deflate;") != nullptr) {
- EnableCompressionNextSendPacket(compression_types::zlib_deflate);
- m_compression_minsize = new_compression_minsize;
- return SendPacket("OK");
- }
-#endif
return SendPacket("E88");
}
@@ -5300,7 +5291,7 @@ RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
thread_dict_sp->AddStringItem("reason", reason_value);
- if (threads_with_valid_stop_info_only == false) {
+ if (!threads_with_valid_stop_info_only) {
const char *thread_name = DNBThreadGetName(pid, tid);
if (thread_name && thread_name[0])
thread_dict_sp->AddStringItem("name", thread_name);
@@ -5488,7 +5479,7 @@ rnb_err_t RNBRemote::HandlePacket_jThreadExtendedInfo(const char *p) {
bool need_to_print_comma = false;
- if (thread_activity_sp && timed_out == false) {
+ if (thread_activity_sp && !timed_out) {
const Genealogy::Activity *activity =
&thread_activity_sp->current_activity;
bool need_vouchers_comma_sep = false;
diff --git a/tools/debugserver/source/RNBServices.cpp b/tools/debugserver/source/RNBServices.cpp
index b2f4910f8855..89c4c27da1dd 100644
--- a/tools/debugserver/source/RNBServices.cpp
+++ b/tools/debugserver/source/RNBServices.cpp
@@ -57,9 +57,9 @@ int GetProcesses(CFMutableArrayRef plistMutableArray, bool all_users) {
const pid_t pid = proc_info.kp_proc.p_pid;
// Skip zombie processes and processes with unset status
- if (kinfo_user_matches == false || // User is acceptable
- pid == our_pid || // Skip this process
- pid == 0 || // Skip kernel (kernel pid is zero)
+ if (!kinfo_user_matches || // User is acceptable
+ pid == our_pid || // Skip this process
+ pid == 0 || // Skip kernel (kernel pid is zero)
proc_info.kp_proc.p_stat ==
SZOMB || // Zombies are bad, they like brains...
proc_info.kp_proc.p_flag & P_TRACED || // Being debugged?
diff --git a/tools/debugserver/source/StdStringExtractor.cpp b/tools/debugserver/source/StdStringExtractor.cpp
index d23f9319fa7b..3b400b2a89d2 100644
--- a/tools/debugserver/source/StdStringExtractor.cpp
+++ b/tools/debugserver/source/StdStringExtractor.cpp
@@ -9,12 +9,8 @@
#include "StdStringExtractor.h"
-// C Includes
#include <stdlib.h>
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
static inline int xdigit_to_sint(char ch) {
if (ch >= 'a' && ch <= 'f')
diff --git a/tools/debugserver/source/StdStringExtractor.h b/tools/debugserver/source/StdStringExtractor.h
index c46978b61f4f..40b57cb08fb5 100644
--- a/tools/debugserver/source/StdStringExtractor.h
+++ b/tools/debugserver/source/StdStringExtractor.h
@@ -10,13 +10,9 @@
#ifndef utility_StdStringExtractor_h_
#define utility_StdStringExtractor_h_
-// C Includes
-// C++ Includes
#include <stdint.h>
#include <string>
-// Other libraries and framework includes
-// Project includes
// Based on StringExtractor, with the added limitation that this file should not
// take a dependency on LLVM, as it is used from debugserver.
diff --git a/tools/debugserver/source/TTYState.h b/tools/debugserver/source/TTYState.h
index ab34015e1a42..88b6d3c2462e 100644
--- a/tools/debugserver/source/TTYState.h
+++ b/tools/debugserver/source/TTYState.h
@@ -56,4 +56,4 @@ protected:
TTYState m_ttystates[2];
};
-#endif \ No newline at end of file
+#endif
diff --git a/tools/debugserver/source/debugserver-entitlements.plist b/tools/debugserver/source/debugserver-entitlements.plist
index 7f1ae4615019..6d9f44536f94 100644
--- a/tools/debugserver/source/debugserver-entitlements.plist
+++ b/tools/debugserver/source/debugserver-entitlements.plist
@@ -12,8 +12,6 @@
<true/>
<key>com.apple.frontboard.debugapplications</key>
<true/>
- <key>run-unsigned-code</key>
- <true/>
<key>seatbelt-profiles</key>
<array>
<string>debugserver</string>
diff --git a/tools/debugserver/source/debugserver.cpp b/tools/debugserver/source/debugserver.cpp
index 7ae321ba431b..8afe17bce37d 100644
--- a/tools/debugserver/source/debugserver.cpp
+++ b/tools/debugserver/source/debugserver.cpp
@@ -9,19 +9,17 @@
#include <arpa/inet.h>
#include <asl.h>
-#include <crt_externs.h> // for _NSGetEnviron()
+#include <crt_externs.h>
#include <errno.h>
#include <getopt.h>
#include <netdb.h>
#include <netinet/in.h>
-#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/types.h>
-#include <sys/types.h>
#include <sys/un.h>
#include <vector>
diff --git a/tools/debugserver/source/libdebugserver.cpp b/tools/debugserver/source/libdebugserver.cpp
index 0d27cfd89a3d..34df67521a7c 100644
--- a/tools/debugserver/source/libdebugserver.cpp
+++ b/tools/debugserver/source/libdebugserver.cpp
@@ -176,7 +176,7 @@ RNBRunLoopMode HandleProcessStateChange(RNBRemoteSP &remote, bool initialize) {
case eStateSuspended:
case eStateCrashed:
case eStateStopped:
- if (initialize == false) {
+ if (!initialize) {
// Compare the last stop count to our current notion of a stop count
// to make sure we don't notify more than once for a given stop.
nub_size_t prev_pid_stop_count = ctx.GetProcessStopCount();
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index 9e01a6b67ea2..9636e1e2c790 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -1,12 +1,6 @@
-if ((CMAKE_SYSTEM_NAME MATCHES "Windows") OR
- (CMAKE_SYSTEM_NAME MATCHES "NetBSD" ))
- # These targets do not have getopt support, so they rely on the one provided by
- # liblldb. However, getopt is not a part of the liblldb interface, so we have
- # to link against the constituent libraries manually. Note that this is
- # extremely scary as it introduces ODR violations, and it should go away as
- # soon as possible.
- set(host_lib lldbHost)
-endif()
+set(LLVM_TARGET_DEFINITIONS Options.td)
+tablegen(LLVM Options.inc -gen-opt-parser-defs)
+add_public_tablegen_target(LLDBOptionsTableGen)
add_lldb_tool(lldb
Driver.cpp
@@ -14,9 +8,9 @@ add_lldb_tool(lldb
LINK_LIBS
liblldb
- ${host_lib}
LINK_COMPONENTS
+ Option
Support
)
@@ -24,4 +18,11 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" )
add_definitions( -DIMPORT_LIBLLDB )
endif()
-add_dependencies(lldb ${LLDB_SUITE_TARGET})
+add_dependencies(lldb
+ LLDBOptionsTableGen
+ ${tablegen_deps}
+)
+
+if(LLDB_BUILD_FRAMEWORK)
+ lldb_setup_framework_rpaths_in_tool(lldb)
+endif()
diff --git a/tools/driver/Driver.cpp b/tools/driver/Driver.cpp
index f3391a55e0d1..71a613afd9bf 100644
--- a/tools/driver/Driver.cpp
+++ b/tools/driver/Driver.cpp
@@ -9,8 +9,31 @@
#include "Driver.h"
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBCommandReturnObject.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBHostOS.h"
+#include "lldb/API/SBLanguageRuntime.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <algorithm>
#include <atomic>
+#include <bitset>
#include <csignal>
+#include <string>
+#include <thread>
+#include <utility>
+
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
@@ -25,39 +48,50 @@
#include <unistd.h>
#endif
-#include <string>
-
-#include "lldb/API/SBBreakpoint.h"
-#include "lldb/API/SBCommandInterpreter.h"
-#include "lldb/API/SBCommandReturnObject.h"
-#include "lldb/API/SBCommunication.h"
-#include "lldb/API/SBDebugger.h"
-#include "lldb/API/SBEvent.h"
-#include "lldb/API/SBHostOS.h"
-#include "lldb/API/SBLanguageRuntime.h"
-#include "lldb/API/SBListener.h"
-#include "lldb/API/SBProcess.h"
-#include "lldb/API/SBStream.h"
-#include "lldb/API/SBStringList.h"
-#include "lldb/API/SBTarget.h"
-#include "lldb/API/SBThread.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ConvertUTF.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-#include <thread>
-
#if !defined(__APPLE__)
#include "llvm/Support/DataTypes.h"
#endif
using namespace lldb;
+using namespace llvm;
+
+namespace {
+enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ OPT_##ID,
+#include "Options.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Options.inc"
+#undef PREFIX
+
+const opt::OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR, VALUES) \
+ { \
+ PREFIX, NAME, HELPTEXT, \
+ METAVAR, OPT_##ID, opt::Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, \
+ OPT_##ALIAS, ALIASARGS, VALUES},
+#include "Options.inc"
+#undef OPTION
+};
+
+class LLDBOptTable : public opt::OptTable {
+public:
+ LLDBOptTable() : OptTable(InfoTable) {}
+};
+} // namespace
static void reset_stdin_termios();
static bool g_old_stdin_termios_is_valid = false;
static struct termios g_old_stdin_termios;
-static Driver *g_driver = NULL;
+static Driver *g_driver = nullptr;
// In the Driver::MainLoop, we change the terminal settings. This function is
// added as an atexit handler to make sure we clean them up.
@@ -68,402 +102,35 @@ static void reset_stdin_termios() {
}
}
-typedef struct {
- uint32_t usage_mask; // Used to mark options that can be used together. If (1
- // << n & usage_mask) != 0
- // then this option belongs to option set n.
- bool required; // This option is required (in the current usage level)
- const char *long_option; // Full name for this option.
- int short_option; // Single character for this option.
- int option_has_arg; // no_argument, required_argument or optional_argument
- uint32_t completion_type; // Cookie the option class can use to do define the
- // argument completion.
- lldb::CommandArgumentType argument_type; // Type of argument this option takes
- const char *usage_text; // Full text explaining what this options does and
- // what (if any) argument to
- // pass it.
-} OptionDefinition;
-
-#define LLDB_3_TO_5 LLDB_OPT_SET_3 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5
-#define LLDB_4_TO_5 LLDB_OPT_SET_4 | LLDB_OPT_SET_5
-
-static OptionDefinition g_options[] = {
- {LLDB_OPT_SET_1, true, "help", 'h', no_argument, 0, eArgTypeNone,
- "Prints out the usage information for the LLDB debugger."},
- {LLDB_OPT_SET_2, true, "version", 'v', no_argument, 0, eArgTypeNone,
- "Prints out the current version number of the LLDB debugger."},
- {LLDB_OPT_SET_3, true, "arch", 'a', required_argument, 0,
- eArgTypeArchitecture,
- "Tells the debugger to use the specified architecture when starting and "
- "running the program. <architecture> must "
- "be one of the architectures for which the program was compiled."},
- {LLDB_OPT_SET_3, true, "file", 'f', required_argument, 0, eArgTypeFilename,
- "Tells the debugger to use the file <filename> as the program to be "
- "debugged."},
- {LLDB_OPT_SET_3, false, "core", 'c', required_argument, 0, eArgTypeFilename,
- "Tells the debugger to use the fullpath to <path> as the core file."},
- {LLDB_OPT_SET_5, true, "attach-pid", 'p', required_argument, 0, eArgTypePid,
- "Tells the debugger to attach to a process with the given pid."},
- {LLDB_OPT_SET_4, true, "attach-name", 'n', required_argument, 0,
- eArgTypeProcessName,
- "Tells the debugger to attach to a process with the given name."},
- {LLDB_OPT_SET_4, true, "wait-for", 'w', no_argument, 0, eArgTypeNone,
- "Tells the debugger to wait for a process with the given pid or name to "
- "launch before attaching."},
- {LLDB_3_TO_5, false, "source", 's', required_argument, 0, eArgTypeFilename,
- "Tells the debugger to read in and execute the lldb commands in the given "
- "file, after any file provided on the command line has been loaded."},
- {LLDB_3_TO_5, false, "one-line", 'o', required_argument, 0, eArgTypeNone,
- "Tells the debugger to execute this one-line lldb command after any file "
- "provided on the command line has been loaded."},
- {LLDB_3_TO_5, false, "source-before-file", 'S', required_argument, 0,
- eArgTypeFilename, "Tells the debugger to read in and execute the lldb "
- "commands in the given file, before any file provided "
- "on the command line has been loaded."},
- {LLDB_3_TO_5, false, "one-line-before-file", 'O', required_argument, 0,
- eArgTypeNone, "Tells the debugger to execute this one-line lldb command "
- "before any file provided on the command line has been "
- "loaded."},
- {LLDB_3_TO_5, false, "one-line-on-crash", 'k', required_argument, 0,
- eArgTypeNone, "When in batch mode, tells the debugger to execute this "
- "one-line lldb command if the target crashes."},
- {LLDB_3_TO_5, false, "source-on-crash", 'K', required_argument, 0,
- eArgTypeFilename, "When in batch mode, tells the debugger to source this "
- "file of lldb commands if the target crashes."},
- {LLDB_3_TO_5, false, "source-quietly", 'Q', no_argument, 0, eArgTypeNone,
- "Tells the debugger to execute this one-line lldb command before any file "
- "provided on the command line has been loaded."},
- {LLDB_3_TO_5, false, "batch", 'b', no_argument, 0, eArgTypeNone,
- "Tells the debugger to run the commands from -s, -S, -o & -O, and "
- "then quit. However if any run command stopped due to a signal or crash, "
- "the debugger will return to the interactive prompt at the place of the "
- "crash."},
- {LLDB_3_TO_5, false, "editor", 'e', no_argument, 0, eArgTypeNone,
- "Tells the debugger to open source files using the host's \"external "
- "editor\" mechanism."},
- {LLDB_3_TO_5, false, "no-lldbinit", 'x', no_argument, 0, eArgTypeNone,
- "Do not automatically parse any '.lldbinit' files."},
- {LLDB_3_TO_5, false, "no-use-colors", 'X', no_argument, 0, eArgTypeNone,
- "Do not use colors."},
- {LLDB_OPT_SET_6, true, "python-path", 'P', no_argument, 0, eArgTypeNone,
- "Prints out the path to the lldb.py file for this version of lldb."},
- {LLDB_3_TO_5, false, "script-language", 'l', required_argument, 0,
- eArgTypeScriptLang,
- "Tells the debugger to use the specified scripting language for "
- "user-defined scripts, rather than the default. "
- "Valid scripting languages that can be specified include Python, Perl, "
- "Ruby and Tcl. Currently only the Python "
- "extensions have been implemented."},
- {LLDB_3_TO_5, false, "debug", 'd', no_argument, 0, eArgTypeNone,
- "Tells the debugger to print out extra information for debugging itself."},
- {LLDB_OPT_SET_7, true, "repl", 'r', optional_argument, 0, eArgTypeNone,
- "Runs lldb in REPL mode with a stub process."},
- {LLDB_OPT_SET_7, true, "repl-language", 'R', required_argument, 0,
- eArgTypeNone, "Chooses the language for the REPL."},
- {0, false, NULL, 0, 0, 0, eArgTypeNone, NULL}};
-
-static const uint32_t last_option_set_with_args = 2;
-
Driver::Driver()
- : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)),
- m_option_data() {
+ : SBBroadcaster("Driver"), m_debugger(SBDebugger::Create(false)) {
// We want to be able to handle CTRL+D in the terminal to have it terminate
// certain input
m_debugger.SetCloseInputOnEOF(false);
g_driver = this;
}
-Driver::~Driver() { g_driver = NULL; }
-
-// This function takes INDENT, which tells how many spaces to output at the
-// front
-// of each line; TEXT, which is the text that is to be output. It outputs the
-// text, on multiple lines if necessary, to RESULT, with INDENT spaces at the
-// front of each line. It breaks lines on spaces, tabs or newlines, shortening
-// the line if necessary to not break in the middle of a word. It assumes that
-// each output line should contain a maximum of OUTPUT_MAX_COLUMNS characters.
-
-void OutputFormattedUsageText(FILE *out, int indent, const char *text,
- int output_max_columns) {
- int len = strlen(text);
- std::string text_string(text);
-
- // Force indentation to be reasonable.
- if (indent >= output_max_columns)
- indent = 0;
-
- // Will it all fit on one line?
-
- if (len + indent < output_max_columns)
- // Output as a single line
- fprintf(out, "%*s%s\n", indent, "", text);
- else {
- // We need to break it up into multiple lines.
- int text_width = output_max_columns - indent - 1;
- int start = 0;
- int end = start;
- int final_end = len;
- int sub_len;
-
- while (end < final_end) {
- // Dont start the 'text' on a space, since we're already outputting the
- // indentation.
- while ((start < final_end) && (text[start] == ' '))
- start++;
-
- end = start + text_width;
- if (end > final_end)
- end = final_end;
- else {
- // If we're not at the end of the text, make sure we break the line on
- // white space.
- while (end > start && text[end] != ' ' && text[end] != '\t' &&
- text[end] != '\n')
- end--;
- }
- sub_len = end - start;
- std::string substring = text_string.substr(start, sub_len);
- fprintf(out, "%*s%s\n", indent, "", substring.c_str());
- start = end + 1;
- }
- }
-}
-
-void ShowUsage(FILE *out, OptionDefinition *option_table,
- Driver::OptionData data) {
- uint32_t screen_width = 80;
- uint32_t indent_level = 0;
- const char *name = "lldb";
-
- fprintf(out, "\nUsage:\n\n");
-
- indent_level += 2;
-
- // First, show each usage level set of options, e.g. <cmd>
- // [options-for-level-0]
- // <cmd>
- // [options-for-level-1]
- // etc.
-
- uint32_t num_options;
- uint32_t num_option_sets = 0;
+Driver::~Driver() { g_driver = nullptr; }
- for (num_options = 0; option_table[num_options].long_option != NULL;
- ++num_options) {
- uint32_t this_usage_mask = option_table[num_options].usage_mask;
- if (this_usage_mask == LLDB_OPT_SET_ALL) {
- if (num_option_sets == 0)
- num_option_sets = 1;
- } else {
- for (uint32_t j = 0; j < LLDB_MAX_NUM_OPTION_SETS; j++) {
- if (this_usage_mask & 1 << j) {
- if (num_option_sets <= j)
- num_option_sets = j + 1;
- }
- }
- }
- }
-
- for (uint32_t opt_set = 0; opt_set < num_option_sets; opt_set++) {
- uint32_t opt_set_mask;
-
- opt_set_mask = 1 << opt_set;
-
- if (opt_set > 0)
- fprintf(out, "\n");
- fprintf(out, "%*s%s", indent_level, "", name);
- bool is_help_line = false;
-
- for (uint32_t i = 0; i < num_options; ++i) {
- if (option_table[i].usage_mask & opt_set_mask) {
- CommandArgumentType arg_type = option_table[i].argument_type;
- const char *arg_name =
- SBCommandInterpreter::GetArgumentTypeAsCString(arg_type);
- // This is a bit of a hack, but there's no way to say certain options
- // don't have arguments yet...
- // so we do it by hand here.
- if (option_table[i].short_option == 'h')
- is_help_line = true;
-
- if (option_table[i].required) {
- if (option_table[i].option_has_arg == required_argument)
- fprintf(out, " -%c <%s>", option_table[i].short_option, arg_name);
- else if (option_table[i].option_has_arg == optional_argument)
- fprintf(out, " -%c [<%s>]", option_table[i].short_option, arg_name);
- else
- fprintf(out, " -%c", option_table[i].short_option);
- } else {
- if (option_table[i].option_has_arg == required_argument)
- fprintf(out, " [-%c <%s>]", option_table[i].short_option, arg_name);
- else if (option_table[i].option_has_arg == optional_argument)
- fprintf(out, " [-%c [<%s>]]", option_table[i].short_option,
- arg_name);
- else
- fprintf(out, " [-%c]", option_table[i].short_option);
- }
- }
- }
- if (!is_help_line && (opt_set <= last_option_set_with_args))
- fprintf(out, " [[--] <PROGRAM-ARG-1> [<PROGRAM_ARG-2> ...]]");
- }
-
- fprintf(out, "\n\n");
-
- // Now print out all the detailed information about the various options: long
- // form, short form and help text:
- // -- long_name <argument>
- // - short <argument>
- // help text
-
- // This variable is used to keep track of which options' info we've printed
- // out, because some options can be in
- // more than one usage level, but we only want to print the long form of its
- // information once.
-
- Driver::OptionData::OptionSet options_seen;
- Driver::OptionData::OptionSet::iterator pos;
-
- indent_level += 5;
-
- for (uint32_t i = 0; i < num_options; ++i) {
- // Only print this option if we haven't already seen it.
- pos = options_seen.find(option_table[i].short_option);
- if (pos == options_seen.end()) {
- CommandArgumentType arg_type = option_table[i].argument_type;
- const char *arg_name =
- SBCommandInterpreter::GetArgumentTypeAsCString(arg_type);
-
- options_seen.insert(option_table[i].short_option);
- fprintf(out, "%*s-%c ", indent_level, "", option_table[i].short_option);
- if (arg_type != eArgTypeNone)
- fprintf(out, "<%s>", arg_name);
- fprintf(out, "\n");
- fprintf(out, "%*s--%s ", indent_level, "", option_table[i].long_option);
- if (arg_type != eArgTypeNone)
- fprintf(out, "<%s>", arg_name);
- fprintf(out, "\n");
- indent_level += 5;
- OutputFormattedUsageText(out, indent_level, option_table[i].usage_text,
- screen_width);
- indent_level -= 5;
- fprintf(out, "\n");
- }
- }
-
- indent_level -= 5;
-
- fprintf(out, "\n%*sNotes:\n", indent_level, "");
- indent_level += 5;
-
- fprintf(out,
- "\n%*sMultiple \"-s\" and \"-o\" options can be provided. They will "
- "be processed"
- "\n%*sfrom left to right in order, with the source files and commands"
- "\n%*sinterleaved. The same is true of the \"-S\" and \"-O\" "
- "options. The before"
- "\n%*sfile and after file sets can intermixed freely, the command "
- "parser will"
- "\n%*ssort them out. The order of the file specifiers (\"-c\", "
- "\"-f\", etc.) is"
- "\n%*snot significant in this regard.\n\n",
- indent_level, "", indent_level, "", indent_level, "", indent_level,
- "", indent_level, "", indent_level, "");
-
- fprintf(
- out,
- "\n%*sIf you don't provide -f then the first argument will be the file "
- "to be"
- "\n%*sdebugged which means that '%s -- <filename> [<ARG1> [<ARG2>]]' also"
- "\n%*sworks. But remember to end the options with \"--\" if any of your"
- "\n%*sarguments have a \"-\" in them.\n\n",
- indent_level, "", indent_level, "", name, indent_level, "", indent_level,
- "");
-}
-
-void BuildGetOptTable(OptionDefinition *expanded_option_table,
- std::vector<struct option> &getopt_table,
- uint32_t num_options) {
- if (num_options == 0)
- return;
-
- uint32_t i;
- uint32_t j;
- std::bitset<256> option_seen;
-
- getopt_table.resize(num_options + 1);
-
- for (i = 0, j = 0; i < num_options; ++i) {
- char short_opt = expanded_option_table[i].short_option;
-
- if (option_seen.test(short_opt) == false) {
- getopt_table[j].name = expanded_option_table[i].long_option;
- getopt_table[j].has_arg = expanded_option_table[i].option_has_arg;
- getopt_table[j].flag = NULL;
- getopt_table[j].val = expanded_option_table[i].short_option;
- option_seen.set(short_opt);
- ++j;
- }
- }
-
- getopt_table[j].name = NULL;
- getopt_table[j].has_arg = 0;
- getopt_table[j].flag = NULL;
- getopt_table[j].val = 0;
-}
-
-Driver::OptionData::OptionData()
- : m_args(), m_script_lang(lldb::eScriptLanguageDefault), m_core_file(),
- m_crash_log(), m_initial_commands(), m_after_file_commands(),
- m_after_crash_commands(), m_debug_mode(false), m_source_quietly(false),
- m_print_version(false), m_print_python_path(false), m_print_help(false),
- m_wait_for(false), m_repl(false), m_repl_lang(eLanguageTypeUnknown),
- m_repl_options(), m_process_name(),
- m_process_pid(LLDB_INVALID_PROCESS_ID), m_use_external_editor(false),
- m_batch(false), m_seen_options() {}
-
-Driver::OptionData::~OptionData() {}
-
-void Driver::OptionData::Clear() {
- m_args.clear();
- m_script_lang = lldb::eScriptLanguageDefault;
- m_initial_commands.clear();
- m_after_file_commands.clear();
-
- // If there is a local .lldbinit, add that to the
- // list of things to be sourced, if the settings
- // permit it.
+void Driver::OptionData::AddLocalLLDBInit() {
+ // If there is a local .lldbinit, add that to the list of things to be
+ // sourced, if the settings permit it.
SBFileSpec local_lldbinit(".lldbinit", true);
-
SBFileSpec homedir_dot_lldb = SBHostOS::GetUserHomeDirectory();
homedir_dot_lldb.AppendPathComponent(".lldbinit");
- // Only read .lldbinit in the current working directory
- // if it's not the same as the .lldbinit in the home
- // directory (which is already being read in).
- if (local_lldbinit.Exists() &&
- strcmp(local_lldbinit.GetDirectory(), homedir_dot_lldb.GetDirectory()) !=
- 0) {
- char path[2048];
- local_lldbinit.GetPath(path, 2047);
+ // Only read .lldbinit in the current working directory if it's not the same
+ // as the .lldbinit in the home directory (which is already being read in).
+ if (local_lldbinit.Exists() && strcmp(local_lldbinit.GetDirectory(),
+ homedir_dot_lldb.GetDirectory()) != 0) {
+ char path[PATH_MAX];
+ local_lldbinit.GetPath(path, sizeof(path));
InitialCmdEntry entry(path, true, true, true);
m_after_file_commands.push_back(entry);
}
-
- m_debug_mode = false;
- m_source_quietly = false;
- m_print_help = false;
- m_print_version = false;
- m_print_python_path = false;
- m_use_external_editor = false;
- m_wait_for = false;
- m_process_name.erase();
- m_batch = false;
- m_after_crash_commands.clear();
-
- m_process_pid = LLDB_INVALID_PROCESS_ID;
}
-void Driver::OptionData::AddInitialCommand(const char *command,
+void Driver::OptionData::AddInitialCommand(std::string command,
CommandPlacement placement,
bool is_file, SBError &error) {
std::vector<InitialCmdEntry> *command_set;
@@ -480,7 +147,7 @@ void Driver::OptionData::AddInitialCommand(const char *command,
}
if (is_file) {
- SBFileSpec file(command);
+ SBFileSpec file(command.c_str());
if (file.Exists())
command_set->push_back(InitialCmdEntry(command, is_file, false));
else if (file.ResolveExecutableLocation()) {
@@ -489,22 +156,21 @@ void Driver::OptionData::AddInitialCommand(const char *command,
command_set->push_back(InitialCmdEntry(final_path, is_file, false));
} else
error.SetErrorStringWithFormat(
- "file specified in --source (-s) option doesn't exist: '%s'", optarg);
+ "file specified in --source (-s) option doesn't exist: '%s'",
+ command.c_str());
} else
command_set->push_back(InitialCmdEntry(command, is_file, false));
}
-void Driver::ResetOptionValues() { m_option_data.Clear(); }
-
const char *Driver::GetFilename() const {
if (m_option_data.m_args.empty())
- return NULL;
+ return nullptr;
return m_option_data.m_args.front().c_str();
}
const char *Driver::GetCrashLogFilename() const {
if (m_option_data.m_crash_log.empty())
- return NULL;
+ return nullptr;
return m_option_data.m_crash_log.c_str();
}
@@ -535,7 +201,7 @@ void Driver::WriteCommandsForSourcing(CommandPlacement placement,
// file in the current working directory), only read it if
// target.load-cwd-lldbinit is 'true'.
if (command_entry.is_cwd_lldbinit_file_read) {
- SBStringList strlist = m_debugger.GetInternalVariableValue(
+ SBStringList strlist = lldb::SBDebugger::GetInternalVariableValue(
"target.load-cwd-lldbinit", m_debugger.GetInstanceName());
if (strlist.GetSize() == 1 &&
strcmp(strlist.GetStringAtIndex(0), "warn") == 0) {
@@ -562,7 +228,8 @@ void Driver::WriteCommandsForSourcing(CommandPlacement placement,
}
bool source_quietly =
m_option_data.m_source_quietly || command_entry.source_quietly;
- strm.Printf("command source -s %i '%s'\n", source_quietly, command);
+ strm.Printf("command source -s %i '%s'\n",
+ static_cast<int>(source_quietly), command);
} else
strm.Printf("%s\n", command);
}
@@ -571,308 +238,232 @@ void Driver::WriteCommandsForSourcing(CommandPlacement placement,
bool Driver::GetDebugMode() const { return m_option_data.m_debug_mode; }
// Check the arguments that were passed to this program to make sure they are
-// valid and to get their
-// argument values (if any). Return a boolean value indicating whether or not
-// to start up the full
-// debugger (i.e. the Command Interpreter) or not. Return FALSE if the
-// arguments were invalid OR
-// if the user only wanted help or version information.
+// valid and to get their argument values (if any). Return a boolean value
+// indicating whether or not to start up the full debugger (i.e. the Command
+// Interpreter) or not. Return FALSE if the arguments were invalid OR if the
+// user only wanted help or version information.
+SBError Driver::ProcessArgs(const opt::InputArgList &args, bool &exiting) {
+ SBError error;
+ m_option_data.AddLocalLLDBInit();
-SBError Driver::ParseArgs(int argc, const char *argv[], FILE *out_fh,
- bool &exiting) {
- ResetOptionValues();
+ // This is kind of a pain, but since we make the debugger in the Driver's
+ // constructor, we can't know at that point whether we should read in init
+ // files yet. So we don't read them in in the Driver constructor, then set
+ // the flags back to "read them in" here, and then if we see the "-n" flag,
+ // we'll turn it off again. Finally we have to read them in by hand later in
+ // the main loop.
+ m_debugger.SkipLLDBInitFiles(false);
+ m_debugger.SkipAppInitFiles(false);
- SBCommandReturnObject result;
+ if (args.hasArg(OPT_version)) {
+ m_option_data.m_print_version = true;
+ }
- SBError error;
- std::string option_string;
- struct option *long_options = NULL;
- std::vector<struct option> long_options_vector;
- uint32_t num_options;
-
- for (num_options = 0; g_options[num_options].long_option != NULL;
- ++num_options)
- /* Do Nothing. */;
-
- if (num_options == 0) {
- if (argc > 1)
- error.SetErrorStringWithFormat("invalid number of options");
- return error;
+ if (args.hasArg(OPT_python_path)) {
+ m_option_data.m_print_python_path = true;
+ }
+
+ if (args.hasArg(OPT_batch)) {
+ m_option_data.m_batch = true;
+ }
+
+ if (auto *arg = args.getLastArg(OPT_core)) {
+ auto arg_value = arg->getValue();
+ SBFileSpec file(arg_value);
+ if (!file.Exists()) {
+ error.SetErrorStringWithFormat(
+ "file specified in --core (-c) option doesn't exist: '%s'",
+ arg_value);
+ return error;
+ }
+ m_option_data.m_core_file = arg_value;
}
- BuildGetOptTable(g_options, long_options_vector, num_options);
+ if (args.hasArg(OPT_editor)) {
+ m_option_data.m_use_external_editor = true;
+ }
- if (long_options_vector.empty())
- long_options = NULL;
- else
- long_options = &long_options_vector.front();
+ if (args.hasArg(OPT_no_lldbinit)) {
+ m_debugger.SkipLLDBInitFiles(true);
+ m_debugger.SkipAppInitFiles(true);
+ }
- if (long_options == NULL) {
- error.SetErrorStringWithFormat("invalid long options");
- return error;
+ if (args.hasArg(OPT_no_use_colors)) {
+ m_debugger.SetUseColor(false);
}
- // Build the option_string argument for call to getopt_long_only.
-
- for (int i = 0; long_options[i].name != NULL; ++i) {
- if (long_options[i].flag == NULL) {
- option_string.push_back((char)long_options[i].val);
- switch (long_options[i].has_arg) {
- default:
- case no_argument:
- break;
- case required_argument:
- option_string.push_back(':');
- break;
- case optional_argument:
- option_string.append("::");
- break;
- }
+ if (auto *arg = args.getLastArg(OPT_file)) {
+ auto arg_value = arg->getValue();
+ SBFileSpec file(arg_value);
+ if (file.Exists()) {
+ m_option_data.m_args.emplace_back(arg_value);
+ } else if (file.ResolveExecutableLocation()) {
+ char path[PATH_MAX];
+ file.GetPath(path, sizeof(path));
+ m_option_data.m_args.emplace_back(path);
+ } else {
+ error.SetErrorStringWithFormat(
+ "file specified in --file (-f) option doesn't exist: '%s'",
+ arg_value);
+ return error;
}
}
- // This is kind of a pain, but since we make the debugger in the Driver's
- // constructor, we can't
- // know at that point whether we should read in init files yet. So we don't
- // read them in in the
- // Driver constructor, then set the flags back to "read them in" here, and
- // then if we see the
- // "-n" flag, we'll turn it off again. Finally we have to read them in by
- // hand later in the
- // main loop.
+ if (auto *arg = args.getLastArg(OPT_arch)) {
+ auto arg_value = arg->getValue();
+ if (!lldb::SBDebugger::SetDefaultArchitecture(arg_value)) {
+ error.SetErrorStringWithFormat(
+ "invalid architecture in the -a or --arch option: '%s'", arg_value);
+ return error;
+ }
+ }
- m_debugger.SkipLLDBInitFiles(false);
- m_debugger.SkipAppInitFiles(false);
+ if (auto *arg = args.getLastArg(OPT_script_language)) {
+ auto arg_value = arg->getValue();
+ m_option_data.m_script_lang = m_debugger.GetScriptingLanguage(arg_value);
+ }
-// Prepare for & make calls to getopt_long_only.
-#if __GLIBC__
- optind = 0;
-#else
- optreset = 1;
- optind = 1;
-#endif
- int val;
- while (1) {
- int long_options_index = -1;
- val = ::getopt_long_only(argc, const_cast<char **>(argv),
- option_string.c_str(), long_options,
- &long_options_index);
-
- if (val == -1)
- break;
- else if (val == '?') {
- m_option_data.m_print_help = true;
- error.SetErrorStringWithFormat("unknown or ambiguous option");
- break;
- } else if (val == 0)
- continue;
- else {
- m_option_data.m_seen_options.insert((char)val);
- if (long_options_index == -1) {
- for (int i = 0; long_options[i].name || long_options[i].has_arg ||
- long_options[i].flag || long_options[i].val;
- ++i) {
- if (long_options[i].val == val) {
- long_options_index = i;
- break;
- }
- }
- }
+ if (args.hasArg(OPT_no_use_colors)) {
+ m_option_data.m_debug_mode = true;
+ }
- if (long_options_index >= 0) {
- const int short_option = g_options[long_options_index].short_option;
-
- switch (short_option) {
- case 'h':
- m_option_data.m_print_help = true;
- break;
-
- case 'v':
- m_option_data.m_print_version = true;
- break;
-
- case 'P':
- m_option_data.m_print_python_path = true;
- break;
-
- case 'b':
- m_option_data.m_batch = true;
- break;
-
- case 'c': {
- SBFileSpec file(optarg);
- if (file.Exists()) {
- m_option_data.m_core_file = optarg;
- } else
- error.SetErrorStringWithFormat(
- "file specified in --core (-c) option doesn't exist: '%s'",
- optarg);
- } break;
-
- case 'e':
- m_option_data.m_use_external_editor = true;
- break;
-
- case 'x':
- m_debugger.SkipLLDBInitFiles(true);
- m_debugger.SkipAppInitFiles(true);
- break;
-
- case 'X':
- m_debugger.SetUseColor(false);
- break;
-
- case 'f': {
- SBFileSpec file(optarg);
- if (file.Exists()) {
- m_option_data.m_args.push_back(optarg);
- } else if (file.ResolveExecutableLocation()) {
- char path[PATH_MAX];
- file.GetPath(path, sizeof(path));
- m_option_data.m_args.push_back(path);
- } else
- error.SetErrorStringWithFormat(
- "file specified in --file (-f) option doesn't exist: '%s'",
- optarg);
- } break;
-
- case 'a':
- if (!m_debugger.SetDefaultArchitecture(optarg))
- error.SetErrorStringWithFormat(
- "invalid architecture in the -a or --arch option: '%s'",
- optarg);
- break;
-
- case 'l':
- m_option_data.m_script_lang = m_debugger.GetScriptingLanguage(optarg);
- break;
-
- case 'd':
- m_option_data.m_debug_mode = true;
- break;
-
- case 'Q':
- m_option_data.m_source_quietly = true;
- break;
-
- case 'K':
- m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash,
- true, error);
- break;
- case 'k':
- m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterCrash,
- false, error);
- break;
-
- case 'n':
- m_option_data.m_process_name = optarg;
- break;
-
- case 'w':
- m_option_data.m_wait_for = true;
- break;
-
- case 'p': {
- char *remainder;
- m_option_data.m_process_pid = strtol(optarg, &remainder, 0);
- if (remainder == optarg || *remainder != '\0')
- error.SetErrorStringWithFormat(
- "Could not convert process PID: \"%s\" into a pid.", optarg);
- } break;
-
- case 'r':
- m_option_data.m_repl = true;
- if (optarg && optarg[0])
- m_option_data.m_repl_options = optarg;
- else
- m_option_data.m_repl_options.clear();
- break;
-
- case 'R':
- m_option_data.m_repl_lang =
- SBLanguageRuntime::GetLanguageTypeFromString(optarg);
- if (m_option_data.m_repl_lang == eLanguageTypeUnknown) {
- error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"",
- optarg);
- }
- break;
-
- case 's':
- m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile,
- true, error);
- break;
- case 'o':
- m_option_data.AddInitialCommand(optarg, eCommandPlacementAfterFile,
- false, error);
- break;
- case 'S':
- m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile,
- true, error);
- break;
- case 'O':
- m_option_data.AddInitialCommand(optarg, eCommandPlacementBeforeFile,
- false, error);
- break;
- default:
- m_option_data.m_print_help = true;
- error.SetErrorStringWithFormat("unrecognized option %c",
- short_option);
- break;
- }
- } else {
- error.SetErrorStringWithFormat("invalid option with value %i", val);
- }
- if (error.Fail()) {
+ if (args.hasArg(OPT_no_use_colors)) {
+ m_debugger.SetUseColor(false);
+ }
+
+ if (args.hasArg(OPT_source_quietly)) {
+ m_option_data.m_source_quietly = true;
+ }
+
+ if (auto *arg = args.getLastArg(OPT_attach_name)) {
+ auto arg_value = arg->getValue();
+ m_option_data.m_process_name = arg_value;
+ }
+
+ if (args.hasArg(OPT_wait_for)) {
+ m_option_data.m_wait_for = true;
+ }
+
+ if (auto *arg = args.getLastArg(OPT_attach_pid)) {
+ auto arg_value = arg->getValue();
+ char *remainder;
+ m_option_data.m_process_pid = strtol(arg_value, &remainder, 0);
+ if (remainder == arg_value || *remainder != '\0') {
+ error.SetErrorStringWithFormat(
+ "Could not convert process PID: \"%s\" into a pid.", arg_value);
+ return error;
+ }
+ }
+
+ if (auto *arg = args.getLastArg(OPT_repl_language)) {
+ auto arg_value = arg->getValue();
+ m_option_data.m_repl_lang =
+ SBLanguageRuntime::GetLanguageTypeFromString(arg_value);
+ if (m_option_data.m_repl_lang == eLanguageTypeUnknown) {
+ error.SetErrorStringWithFormat("Unrecognized language name: \"%s\"",
+ arg_value);
+ return error;
+ }
+ }
+
+ if (args.hasArg(OPT_repl)) {
+ m_option_data.m_repl = true;
+ }
+
+ if (auto *arg = args.getLastArg(OPT_repl_)) {
+ m_option_data.m_repl = true;
+ if (auto arg_value = arg->getValue())
+ m_option_data.m_repl_options = arg_value;
+ }
+
+ // We need to process the options below together as their relative order
+ // matters.
+ for (auto *arg : args.filtered(OPT_source_on_crash, OPT_one_line_on_crash,
+ OPT_source, OPT_source_before_file,
+ OPT_one_line, OPT_one_line_before_file)) {
+ auto arg_value = arg->getValue();
+ if (arg->getOption().matches(OPT_source_on_crash)) {
+ m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
+ true, error);
+ if (error.Fail())
+ return error;
+ }
+
+ if (arg->getOption().matches(OPT_one_line_on_crash)) {
+ m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterCrash,
+ false, error);
+ if (error.Fail())
+ return error;
+ }
+
+ if (arg->getOption().matches(OPT_source)) {
+ m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
+ true, error);
+ if (error.Fail())
+ return error;
+ }
+
+ if (arg->getOption().matches(OPT_source_before_file)) {
+ m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
+ true, error);
+ if (error.Fail())
+ return error;
+ }
+
+ if (arg->getOption().matches(OPT_one_line)) {
+ m_option_data.AddInitialCommand(arg_value, eCommandPlacementAfterFile,
+ false, error);
+ if (error.Fail())
+ return error;
+ }
+
+ if (arg->getOption().matches(OPT_one_line_before_file)) {
+ m_option_data.AddInitialCommand(arg_value, eCommandPlacementBeforeFile,
+ false, error);
+ if (error.Fail())
return error;
+ }
+ }
+
+ if (m_option_data.m_process_name.empty() &&
+ m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) {
+
+ // If the option data args array is empty that means the file was not
+ // specified with -f and we need to get it from the input args.
+ if (m_option_data.m_args.empty()) {
+ if (auto *arg = args.getLastArgNoClaim(OPT_INPUT)) {
+ m_option_data.m_args.push_back(arg->getAsString((args)));
}
}
+
+ // Any argument following -- is an argument for the inferior.
+ if (auto *arg = args.getLastArgNoClaim(OPT_REM)) {
+ for (auto value : arg->getValues())
+ m_option_data.m_args.emplace_back(value);
+ }
+ } else if (args.getLastArgNoClaim() != nullptr) {
+ WithColor::warning() << "program arguments are ignored when attaching.\n";
}
- if (error.Fail() || m_option_data.m_print_help) {
- ShowUsage(out_fh, g_options, m_option_data);
- exiting = true;
- } else if (m_option_data.m_print_version) {
- ::fprintf(out_fh, "%s\n", m_debugger.GetVersionString());
+ if (m_option_data.m_print_version) {
+ llvm::outs() << lldb::SBDebugger::GetVersionString() << '\n';
exiting = true;
- } else if (m_option_data.m_print_python_path) {
+ return error;
+ }
+
+ if (m_option_data.m_print_python_path) {
SBFileSpec python_file_spec = SBHostOS::GetLLDBPythonPath();
if (python_file_spec.IsValid()) {
char python_path[PATH_MAX];
size_t num_chars = python_file_spec.GetPath(python_path, PATH_MAX);
if (num_chars < PATH_MAX) {
- ::fprintf(out_fh, "%s\n", python_path);
+ llvm::outs() << python_path << '\n';
} else
- ::fprintf(out_fh, "<PATH TOO LONG>\n");
+ llvm::outs() << "<PATH TOO LONG>\n";
} else
- ::fprintf(out_fh, "<COULD NOT FIND PATH>\n");
+ llvm::outs() << "<COULD NOT FIND PATH>\n";
exiting = true;
- } else if (m_option_data.m_process_name.empty() &&
- m_option_data.m_process_pid == LLDB_INVALID_PROCESS_ID) {
- // Any arguments that are left over after option parsing are for
- // the program. If a file was specified with -f then the filename
- // is already in the m_option_data.m_args array, and any remaining args
- // are arguments for the inferior program. If no file was specified with
- // -f, then what is left is the program name followed by any arguments.
-
- // Skip any options we consumed with getopt_long_only
- argc -= optind;
- argv += optind;
-
- if (argc > 0) {
- for (int arg_idx = 0; arg_idx < argc; ++arg_idx) {
- const char *arg = argv[arg_idx];
- if (arg)
- m_option_data.m_args.push_back(arg);
- }
- }
-
- } else {
- // Skip any options we consumed with getopt_long_only
- argc -= optind;
-
- if (argc > 0)
- ::fprintf(out_fh,
- "Warning: program arguments are ignored when attaching.\n");
+ return error;
}
return error;
@@ -882,7 +473,7 @@ static ::FILE *PrepareCommandsForSourcing(const char *commands_data,
size_t commands_size, int fds[2]) {
enum PIPES { READ, WRITE }; // Constants 0 and 1 for READ and WRITE
- ::FILE *commands_file = NULL;
+ ::FILE *commands_file = nullptr;
fds[0] = -1;
fds[1] = -1;
int err = 0;
@@ -894,10 +485,13 @@ static ::FILE *PrepareCommandsForSourcing(const char *commands_data,
if (err == 0) {
ssize_t nrwr = write(fds[WRITE], commands_data, commands_size);
if (nrwr < 0) {
- fprintf(stderr, "error: write(%i, %p, %" PRIu64 ") failed (errno = %i) "
- "when trying to open LLDB commands pipe\n",
- fds[WRITE], static_cast<const void *>(commands_data),
- static_cast<uint64_t>(commands_size), errno);
+ WithColor::error()
+ << format(
+ "write(%i, %p, %" PRIu64
+ ") failed (errno = %i) when trying to open LLDB commands pipe",
+ fds[WRITE], static_cast<const void *>(commands_data),
+ static_cast<uint64_t>(commands_size), errno)
+ << '\n';
} else if (static_cast<size_t>(nrwr) == commands_size) {
// Close the write end of the pipe so when we give the read end to
// the debugger/command interpreter it will exit when it consumes all
@@ -912,20 +506,20 @@ static ::FILE *PrepareCommandsForSourcing(const char *commands_data,
// Now open the read file descriptor in a FILE * that we can give to
// the debugger as an input handle
commands_file = fdopen(fds[READ], "r");
- if (commands_file) {
- fds[READ] =
- -1; // The FILE * 'commands_file' now owns the read descriptor
- // Hand ownership if the FILE * over to the debugger for
- // "commands_file".
+ if (commands_file != nullptr) {
+ fds[READ] = -1; // The FILE * 'commands_file' now owns the read
+ // descriptor Hand ownership if the FILE * over to the
+ // debugger for "commands_file".
} else {
- fprintf(stderr, "error: fdopen(%i, \"r\") failed (errno = %i) when "
- "trying to open LLDB commands pipe\n",
- fds[READ], errno);
+ WithColor::error() << format("fdopen(%i, \"r\") failed (errno = %i) "
+ "when trying to open LLDB commands pipe",
+ fds[READ], errno)
+ << '\n';
}
}
} else {
- fprintf(stderr,
- "error: can't create pipe file descriptors for LLDB commands\n");
+ WithColor::error()
+ << "can't create pipe file descriptors for LLDB commands\n";
}
return commands_file;
@@ -975,9 +569,9 @@ int Driver::MainLoop() {
// Disabling stdin buffering with MSVC's 2015 CRT exposes a bug in fgets
// which causes it to miss newlines depending on whether there have been an
// odd or even number of characters. Bug has been reported to MS via Connect.
- ::setbuf(stdin, NULL);
+ ::setbuf(stdin, nullptr);
#endif
- ::setbuf(stdout, NULL);
+ ::setbuf(stdout, nullptr);
m_debugger.SetErrorFileHandle(stderr, false);
m_debugger.SetOutputFileHandle(stdout, false);
@@ -987,7 +581,7 @@ int Driver::MainLoop() {
m_debugger.SetUseExternalEditor(m_option_data.m_use_external_editor);
struct winsize window_size;
- if (isatty(STDIN_FILENO) &&
+ if ((isatty(STDIN_FILENO) != 0) &&
::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
if (window_size.ws_col > 0)
m_debugger.SetTerminalWidth(window_size.ws_col);
@@ -1018,7 +612,7 @@ int Driver::MainLoop() {
const size_t num_args = m_option_data.m_args.size();
if (num_args > 0) {
char arch_name[64];
- if (m_debugger.GetDefaultArchitecture(arch_name, sizeof(arch_name)))
+ if (lldb::SBDebugger::GetDefaultArchitecture(arch_name, sizeof(arch_name)))
commands_stream.Printf("target create --arch=%s %s", arch_name,
EscapeString(m_option_data.m_args[0]).c_str());
else
@@ -1066,16 +660,16 @@ int Driver::MainLoop() {
bool spawn_thread = false;
if (m_option_data.m_repl) {
- const char *repl_options = NULL;
+ const char *repl_options = nullptr;
if (!m_option_data.m_repl_options.empty())
repl_options = m_option_data.m_repl_options.c_str();
SBError error(m_debugger.RunREPL(m_option_data.m_repl_lang, repl_options));
if (error.Fail()) {
const char *error_cstr = error.GetCString();
- if (error_cstr && error_cstr[0])
- fprintf(stderr, "error: %s\n", error_cstr);
+ if ((error_cstr != nullptr) && (error_cstr[0] != 0))
+ WithColor::error() << error_cstr << '\n';
else
- fprintf(stderr, "error: %u\n", error.GetError());
+ WithColor::error() << error.GetError() << '\n';
}
} else {
// Check if we have any data in the commands stream, and if so, save it to a
@@ -1088,12 +682,12 @@ int Driver::MainLoop() {
// track that.
bool quit_requested = false;
bool stopped_for_crash = false;
- if (commands_data && commands_size) {
+ if ((commands_data != nullptr) && (commands_size != 0u)) {
int initial_commands_fds[2];
bool success = true;
FILE *commands_file = PrepareCommandsForSourcing(
commands_data, commands_size, initial_commands_fds);
- if (commands_file) {
+ if (commands_file != nullptr) {
m_debugger.SetInputFileHandle(commands_file, true);
// Set the debugger into Sync mode when running the command file.
@@ -1122,7 +716,7 @@ int Driver::MainLoop() {
const size_t crash_commands_size = crash_commands_stream.GetSize();
commands_file = PrepareCommandsForSourcing(
crash_commands_data, crash_commands_size, crash_command_fds);
- if (commands_file) {
+ if (commands_file != nullptr) {
bool local_quit_requested;
bool local_stopped_for_crash;
m_debugger.SetInputFileHandle(commands_file, true);
@@ -1177,9 +771,9 @@ void Driver::ResizeWindow(unsigned short col) {
void sigwinch_handler(int signo) {
struct winsize window_size;
- if (isatty(STDIN_FILENO) &&
+ if ((isatty(STDIN_FILENO) != 0) &&
::ioctl(STDIN_FILENO, TIOCGWINSZ, &window_size) == 0) {
- if ((window_size.ws_col > 0) && g_driver != NULL) {
+ if ((window_size.ws_col > 0) && g_driver != nullptr) {
g_driver->ResizeWindow(window_size.ws_col);
}
}
@@ -1187,7 +781,7 @@ void sigwinch_handler(int signo) {
void sigint_handler(int signo) {
static std::atomic_flag g_interrupt_sent = ATOMIC_FLAG_INIT;
- if (g_driver) {
+ if (g_driver != nullptr) {
if (!g_interrupt_sent.test_and_set()) {
g_driver->GetDebugger().DispatchInputInterrupt();
g_interrupt_sent.clear();
@@ -1199,7 +793,7 @@ void sigint_handler(int signo) {
}
void sigtstp_handler(int signo) {
- if (g_driver)
+ if (g_driver != nullptr)
g_driver->GetDebugger().SaveInputTerminalState();
signal(signo, SIG_DFL);
@@ -1208,7 +802,7 @@ void sigtstp_handler(int signo) {
}
void sigcont_handler(int signo) {
- if (g_driver)
+ if (g_driver != nullptr)
g_driver->GetDebugger().RestoreInputTerminalState();
signal(signo, SIG_DFL);
@@ -1216,6 +810,45 @@ void sigcont_handler(int signo) {
signal(signo, sigcont_handler);
}
+static void printHelp(LLDBOptTable &table, llvm::StringRef tool_name) {
+ std::string usage_str = tool_name.str() + "options";
+ table.PrintHelp(llvm::outs(), usage_str.c_str(), "LLDB", false);
+
+ std::string examples = R"___(
+EXAMPLES:
+ The debugger can be started in several modes.
+
+ Passing an executable as a positional argument prepares lldb to debug the
+ given executable. Arguments passed after -- are considered arguments to the
+ debugged executable.
+
+ lldb --arch x86_64 /path/to/program -- --arch arvm7
+
+ Passing one of the attach options causes lldb to immediately attach to the
+ given process.
+
+ lldb -p <pid>
+ lldb -n <process-name>
+
+ Passing --repl starts lldb in REPL mode.
+
+ lldb -r
+
+ Passing --core causes lldb to debug the core file.
+
+ lldb -c /path/to/core
+
+ Command options can be combined with either mode and cause lldb to run the
+ specified commands before or after events, like loading the file or crashing,
+ in the order provided on the command line.
+
+ lldb -O 'settings set stop-disassembly-count 20' -o 'run' -o 'bt'
+ lldb -S /source/before/file -s /source/after/file
+ lldb -K /source/before/crash -k /source/after/crash
+ )___";
+ llvm::outs() << examples;
+}
+
int
#ifdef _MSC_VER
wmain(int argc, wchar_t const *wargv[])
@@ -1234,11 +867,48 @@ main(int argc, char const *argv[])
const char **argv = argvPointers.data();
#endif
- llvm::StringRef ToolName = argv[0];
+ // Print stack trace on crash.
+ llvm::StringRef ToolName = llvm::sys::path::filename(argv[0]);
llvm::sys::PrintStackTraceOnErrorSignal(ToolName);
llvm::PrettyStackTraceProgram X(argc, argv);
- SBDebugger::Initialize();
+ // Parse arguments.
+ LLDBOptTable T;
+ unsigned MAI;
+ unsigned MAC;
+ ArrayRef<const char *> arg_arr = makeArrayRef(argv + 1, argc - 1);
+ opt::InputArgList input_args = T.ParseArgs(arg_arr, MAI, MAC);
+
+ if (input_args.hasArg(OPT_help)) {
+ printHelp(T, ToolName);
+ return 0;
+ }
+
+ for (auto *arg : input_args.filtered(OPT_UNKNOWN)) {
+ WithColor::warning() << "ignoring unknown option: " << arg->getSpelling()
+ << '\n';
+ }
+
+ SBInitializerOptions options;
+
+ if (auto *arg = input_args.getLastArg(OPT_capture)) {
+ auto arg_value = arg->getValue();
+ options.SetReproducerPath(arg_value);
+ options.SetCaptureReproducer(true);
+ }
+
+ if (auto *arg = input_args.getLastArg(OPT_replay)) {
+ auto arg_value = arg->getValue();
+ options.SetReplayReproducer(true);
+ options.SetReproducerPath(arg_value);
+ }
+
+ SBError error = SBDebugger::Initialize(options);
+ if (error.Fail()) {
+ WithColor::error() << "initialization failed: " << error.GetCString()
+ << '\n';
+ return 1;
+ }
SBHostOS::ThreadCreated("<lldb.driver.main-thread>");
@@ -1257,12 +927,11 @@ main(int argc, char const *argv[])
Driver driver;
bool exiting = false;
- SBError error(driver.ParseArgs(argc, argv, stdout, exiting));
+ SBError error(driver.ProcessArgs(input_args, exiting));
if (error.Fail()) {
exit_code = 1;
- const char *error_cstr = error.GetCString();
- if (error_cstr)
- ::fprintf(stderr, "error: %s\n", error_cstr);
+ if (const char *error_cstr = error.GetCString())
+ WithColor::error() << error_cstr << '\n';
} else if (!exiting) {
exit_code = driver.MainLoop();
}
diff --git a/tools/driver/Driver.h b/tools/driver/Driver.h
index 34746a239999..3f2b0759255a 100644
--- a/tools/driver/Driver.h
+++ b/tools/driver/Driver.h
@@ -11,19 +11,19 @@
#define lldb_Driver_h_
#include "Platform.h"
-#include "lldb/Host/PseudoTerminal.h"
-
-#include <bitset>
-#include <set>
-#include <string>
-#include <vector>
#include "lldb/API/SBBroadcaster.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBError.h"
-class IOChannel;
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+
+#include <set>
+#include <string>
+#include <vector>
class Driver : public lldb::SBBroadcaster {
public:
@@ -42,8 +42,7 @@ public:
/// @return The exit code that the process should return.
int MainLoop();
- lldb::SBError ParseArgs(int argc, const char *argv[], FILE *out_fh,
- bool &do_exit);
+ lldb::SBError ProcessArgs(const llvm::opt::InputArgList &args, bool &exiting);
const char *GetFilename() const;
@@ -58,60 +57,57 @@ public:
bool GetDebugMode() const;
- class OptionData {
- public:
- OptionData();
- ~OptionData();
-
- void Clear();
-
- void AddInitialCommand(const char *command, CommandPlacement placement,
+ struct OptionData {
+ void AddLocalLLDBInit();
+ void AddInitialCommand(std::string command, CommandPlacement placement,
bool is_file, lldb::SBError &error);
- // static OptionDefinition m_cmd_option_table[];
-
struct InitialCmdEntry {
- InitialCmdEntry(const char *in_contents, bool in_is_file,
+ InitialCmdEntry(std::string contents, bool in_is_file,
bool is_cwd_lldbinit_file_read, bool in_quiet = false)
- : contents(in_contents), is_file(in_is_file),
- is_cwd_lldbinit_file_read(is_cwd_lldbinit_file_read),
- source_quietly(in_quiet) {}
+ : contents(std::move(contents)), is_file(in_is_file),
+ source_quietly(in_quiet),
+ is_cwd_lldbinit_file_read(is_cwd_lldbinit_file_read) {}
std::string contents;
bool is_file;
- bool is_cwd_lldbinit_file_read; // if this is reading ./.lldbinit - so we
- // may skip if not permitted
bool source_quietly;
+
+ /// Remember if this is reading the local lldbinit file so we can skip it
+ /// if not permitted.
+ bool is_cwd_lldbinit_file_read;
};
std::vector<std::string> m_args;
- lldb::ScriptLanguage m_script_lang;
+
+ lldb::ScriptLanguage m_script_lang = lldb::eScriptLanguageDefault;
+ lldb::LanguageType m_repl_lang = lldb::eLanguageTypeUnknown;
+ lldb::pid_t m_process_pid = LLDB_INVALID_PROCESS_ID;
+
std::string m_core_file;
std::string m_crash_log;
+ std::string m_repl_options;
+ std::string m_process_name;
+
std::vector<InitialCmdEntry> m_initial_commands;
std::vector<InitialCmdEntry> m_after_file_commands;
std::vector<InitialCmdEntry> m_after_crash_commands;
- bool m_debug_mode;
- bool m_source_quietly;
- bool m_print_version;
- bool m_print_python_path;
- bool m_print_help;
- bool m_wait_for;
- bool m_repl;
- lldb::LanguageType m_repl_lang;
- std::string m_repl_options;
- std::string m_process_name;
- lldb::pid_t m_process_pid;
- bool m_use_external_editor; // FIXME: When we have set/show variables we can
- // remove this from here.
- bool m_batch;
- typedef std::set<char> OptionSet;
+
+ bool m_debug_mode = false;
+ bool m_source_quietly = false;
+ bool m_print_version = false;
+ bool m_print_python_path = false;
+ bool m_wait_for = false;
+ bool m_repl = false;
+ bool m_batch = false;
+
+ // FIXME: When we have set/show variables we can remove this from here.
+ bool m_use_external_editor = false;
+
+ using OptionSet = std::set<char>;
OptionSet m_seen_options;
};
- static lldb::SBError SetOptionValue(int option_idx, const char *option_arg,
- Driver::OptionData &data);
-
lldb::SBDebugger &GetDebugger() { return m_debugger; }
void ResizeWindow(unsigned short col);
@@ -119,10 +115,6 @@ public:
private:
lldb::SBDebugger m_debugger;
OptionData m_option_data;
-
- void ResetOptionValues();
-
- void ReadyForCommand();
};
#endif // lldb_Driver_h_
diff --git a/tools/driver/Options.td b/tools/driver/Options.td
new file mode 100644
index 000000000000..563c0b54fb98
--- /dev/null
+++ b/tools/driver/Options.td
@@ -0,0 +1,229 @@
+include "llvm/Option/OptParser.td"
+
+class F<string name>: Flag<["--", "-"], name>;
+class S<string name>: Separate<["--", "-"], name>;
+class R<list<string> prefixes, string name>
+ : Option<prefixes, name, KIND_REMAINING_ARGS>;
+
+// Attaching options.
+def grp_attach : OptionGroup<"attaching">, HelpText<"ATTACHING">;
+
+def attach_name: Separate<["--", "-"], "attach-name">,
+ MetaVarName<"<name>">,
+ HelpText<"Tells the debugger to attach to a process with the given name.">,
+ Group<grp_attach>;
+def: Separate<["-"], "n">,
+ Alias<attach_name>,
+ HelpText<"Alias for --attach-name">,
+ Group<grp_attach>;
+
+def wait_for: F<"wait-for">,
+ HelpText<"Tells the debugger to wait for a process with the given pid or name to launch before attaching.">,
+ Group<grp_attach>;
+def: Flag<["-"], "w">,
+ Alias<wait_for>,
+ HelpText<"Alias for --wait-for">,
+ Group<grp_attach>;
+
+def attach_pid: Separate<["--", "-"], "attach-pid">,
+ MetaVarName<"<pid>">,
+ HelpText<"Tells the debugger to attach to a process with the given pid.">,
+ Group<grp_attach>;
+def: Separate<["-"], "p">,
+ Alias<attach_pid>,
+ HelpText<"Alias for --attach-pid">,
+ Group<grp_attach>;
+
+
+// Scripting options.
+def grp_scripting : OptionGroup<"scripting">, HelpText<"SCRIPTING">;
+
+def python_path: F<"python-path">,
+ HelpText<"Prints out the path to the lldb.py file for this version of lldb.">,
+ Group<grp_scripting>;
+def: Flag<["-"], "P">,
+ Alias<python_path>,
+ HelpText<"Alias for --python-path">,
+ Group<grp_scripting>;
+
+def script_language: Separate<["--", "-"], "script-language">,
+ MetaVarName<"<language>">,
+ HelpText<"Tells the debugger to use the specified scripting language for user-defined scripts.">,
+ Group<grp_scripting>;
+def: Separate<["-"], "l">,
+ Alias<script_language>,
+ HelpText<"Alias for --script-language">,
+ Group<grp_scripting>;
+
+// Repl options.
+def grp_repl : OptionGroup<"repl">, HelpText<"REPL">;
+
+def repl: Flag<["--", "-"], "repl">,
+ HelpText<"Runs lldb in REPL mode with a stub process.">,
+ Group<grp_repl>;
+def: Flag<["-"], "r">,
+ Alias<repl>,
+ HelpText<"Alias for --repl">,
+ Group<grp_repl>;
+def repl_: Joined<["--", "-"], "repl=">,
+ MetaVarName<"<flags>">,
+ HelpText<"Runs lldb in REPL mode with a stub process with the given flags.">,
+ Group<grp_repl>;
+def: Joined<["-"], "r=">,
+ MetaVarName<"<flags>">,
+ Alias<repl_>,
+ HelpText<"Alias for --repl=<flags>">,
+ Group<grp_repl>;
+
+def repl_language: Separate<["--", "-"], "repl-language">,
+ MetaVarName<"<language>">,
+ HelpText<"Chooses the language for the REPL.">,
+ Group<grp_repl>;
+def: Separate<["-"], "R">,
+ Alias<repl_language>,
+ HelpText<"Alias for --repl-language">,
+ Group<grp_repl>;
+
+
+// Command options.
+def grp_command : OptionGroup<"command">, HelpText<"COMMANDS">;
+
+def no_lldbinit: F<"no-lldbinit">,
+ HelpText<"Do not automatically parse any '.lldbinit' files.">,
+ Group<grp_command>;
+def: Flag<["-"], "x">,
+ Alias<no_lldbinit>,
+ HelpText<"Alias for --no-lldbinit">,
+ Group<grp_command>;
+
+def batch: F<"batch">,
+ HelpText<"Tells the debugger to run the commands from -s, -S, -o & -O, and then quit.">,
+ Group<grp_command>;
+def: Flag<["-"], "b">,
+ Alias<batch>,
+ HelpText<"Alias for --batch">,
+ Group<grp_command>;
+
+def source_quietly: F<"source-quietly">,
+ HelpText<"Tells the debugger to execute this one-line lldb command before any file has been loaded.">,
+ Group<grp_command>;
+def: Flag<["-"], "Q">,
+ Alias<source_quietly>,
+ HelpText<"Alias for --source-quietly">,
+ Group<grp_command>;
+
+def one_line_on_crash: Separate<["--", "-"], "one-line-on-crash">,
+ MetaVarName<"<command>">,
+ HelpText<"When in batch mode, tells the debugger to source this file of lldb commands if the target crashes.">,
+ Group<grp_command>;
+def: Separate<["-"], "k">,
+ Alias<one_line_on_crash>,
+ HelpText<"Alias for --one-line-on-crash">,
+ Group<grp_command>;
+
+def source_on_crash: Separate<["--", "-"], "source-on-crash">,
+ MetaVarName<"<file>">,
+ HelpText<"When in batch mode, tells the debugger to source this file of lldb commands if the target crashes.">,
+ Group<grp_command>;
+def: Separate<["-"], "K">,
+ Alias<source_on_crash>,
+ HelpText<"Alias for --source-on-crash">,
+ Group<grp_command>;
+
+def source: Separate<["--", "-"], "source">,
+ MetaVarName<"<file>">,
+ HelpText<"Tells the debugger to read in and execute the lldb commands in the given file, after any file has been loaded.">,
+ Group<grp_command>;
+def: Separate<["-"], "s">,
+ Alias<source>,
+ HelpText<"Alias for --source">,
+ Group<grp_command>;
+
+def source_before_file: Separate<["--", "-"], "source-before-file">,
+ MetaVarName<"<file>">,
+ HelpText<"Tells the debugger to read in and execute the lldb commands in the given file, before any file has been loaded.">,
+ Group<grp_command>;
+def: Separate<["-"], "S">,
+ Alias<source_before_file>,
+ HelpText<"Alias for --source-before-file">,
+ Group<grp_command>;
+
+def one_line: Separate<["--", "-"], "one-line">,
+ MetaVarName<"<command>">,
+ HelpText<"Tells the debugger to execute this one-line lldb command after any file provided on the command line has been loaded.">,
+ Group<grp_command>;
+def: Separate<["-"], "o">,
+ Alias<one_line>,
+ HelpText<"Alias for --one-line">,
+ Group<grp_command>;
+
+def one_line_before_file: Separate<["--", "-"], "one-line-before-file">,
+ MetaVarName<"<command>">,
+ HelpText<"Tells the debugger to execute this one-line lldb command before any file provided on the command line has been loaded.">,
+ Group<grp_command>;
+def: Separate<["-"], "O">,
+ Alias<one_line_before_file>,
+ HelpText<"Alias for --one-line-before-file">,
+ Group<grp_command>;
+
+
+// General options.
+def version: F<"version">,
+ HelpText<"Prints out the current version number of the LLDB debugger.">;
+def: Flag<["-"], "v">,
+ Alias<version>,
+ HelpText<"Alias for --version">;
+
+def help: F<"help">,
+ HelpText<"Prints out the usage information for the LLDB debugger.">;
+def: Flag<["-"], "h">,
+ Alias<help>,
+ HelpText<"Alias for --help">;
+
+def core: Separate<["--", "-"], "core">,
+ MetaVarName<"<filename>">,
+ HelpText<"Tells the debugger to use the full path to <filename> as the core file.">;
+def: Separate<["-"], "c">,
+ Alias<core>,
+ HelpText<"Alias for --core">;
+
+def editor: F<"editor">,
+ HelpText<"Tells the debugger to open source files using the host's \"external editor\" mechanism.">;
+def: Flag<["-"], "e">,
+ Alias<editor>,
+ HelpText<"Alias for --editor">;
+
+def no_use_colors: F<"no-use-colors">,
+ HelpText<"Do not use colors.">;
+def: Flag<["-"], "X">,
+ Alias<no_use_colors>,
+ HelpText<"Alias for --no-use-color">;
+
+def file: Separate<["--", "-"], "file">,
+ MetaVarName<"<filename>">,
+ HelpText<"Tells the debugger to use the file <filename> as the program to be debugged.">;
+def: Separate<["-"], "f">,
+ Alias<file>,
+ HelpText<"Alias for --file">;
+
+def arch: Separate<["--", "-"], "arch">,
+ MetaVarName<"<architecture>">,
+ HelpText<"Tells the debugger to use the specified architecture when starting and running the program.">;
+def: Separate<["-"], "a">,
+ Alias<arch>,
+ HelpText<"Alias for --arch">;
+
+def debug: F<"debug">,
+ HelpText<"Tells the debugger to print out extra information for debugging itself.">;
+def: Flag<["-"], "d">,
+ Alias<debug>,
+ HelpText<"Alias for --debug">;
+
+def capture: Separate<["--", "-"], "capture">,
+ MetaVarName<"<filename>">,
+ HelpText<"Tells the debugger to capture a reproducer to <filename>.">;
+def replay: Separate<["--", "-"], "replay">,
+ MetaVarName<"<filename>">,
+ HelpText<"Tells the debugger to replay a reproducer from <filename>.">;
+
+def REM : R<["--"], "">;
diff --git a/tools/driver/Platform.h b/tools/driver/Platform.h
index 521c5a1ccbb5..1bb42f9cfc16 100644
--- a/tools/driver/Platform.h
+++ b/tools/driver/Platform.h
@@ -12,7 +12,6 @@
#if defined(_WIN32)
-#include "lldb/Host/HostGetOpt.h"
#include <io.h>
#if defined(_MSC_VER)
#include <signal.h>
@@ -61,7 +60,6 @@ struct timeval {
long tv_usec;
};
typedef long pid_t;
-#define snprintf _snprintf
#define PATH_MAX MAX_PATH
#endif
@@ -74,7 +72,6 @@ extern int tcsetattr(int fd, int optional_actions,
extern int tcgetattr(int fildes, struct termios *termios_p);
#else
-#include "lldb/Host/HostGetOpt.h"
#include <inttypes.h>
#include <libgen.h>
diff --git a/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp b/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
index e654f076fb3a..df1221f3ccff 100644
--- a/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
+++ b/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
@@ -12,7 +12,6 @@
#include <cerrno>
#include <string>
-// Project includes
#include "cli-wrapper-mpxtable.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
diff --git a/tools/intel-features/intel-pt/Decoder.cpp b/tools/intel-features/intel-pt/Decoder.cpp
index 0c385adc811c..f838ff4c1e6e 100644
--- a/tools/intel-features/intel-pt/Decoder.cpp
+++ b/tools/intel-features/intel-pt/Decoder.cpp
@@ -7,14 +7,12 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "Decoder.h"
// C/C++ Includes
#include <cinttypes>
#include <cstring>
-// Other libraries and framework includes
#include "lldb/API/SBModule.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBThread.h"
diff --git a/tools/intel-features/intel-pt/Decoder.h b/tools/intel-features/intel-pt/Decoder.h
index 3762196058fd..58ebb7e734cb 100644
--- a/tools/intel-features/intel-pt/Decoder.h
+++ b/tools/intel-features/intel-pt/Decoder.h
@@ -16,7 +16,6 @@
#include <string>
#include <vector>
-// Project includes, Other libraries and framework includes
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBProcess.h"
diff --git a/tools/intel-features/intel-pt/PTDecoder.cpp b/tools/intel-features/intel-pt/PTDecoder.cpp
index 4f3554e84d3c..72effbe3da79 100644
--- a/tools/intel-features/intel-pt/PTDecoder.cpp
+++ b/tools/intel-features/intel-pt/PTDecoder.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "PTDecoder.h"
#include "Decoder.h"
diff --git a/tools/intel-features/intel-pt/PTDecoder.h b/tools/intel-features/intel-pt/PTDecoder.h
index 8af8c8672b18..c38057ac715a 100644
--- a/tools/intel-features/intel-pt/PTDecoder.h
+++ b/tools/intel-features/intel-pt/PTDecoder.h
@@ -13,7 +13,6 @@
// C/C++ Includes
#include <vector>
-// Project includes, Other libraries and framework includes
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBProcess.h"
diff --git a/tools/lldb-mi/CMakeLists.txt b/tools/lldb-mi/CMakeLists.txt
index f3f4c0097efd..20c031a12004 100644
--- a/tools/lldb-mi/CMakeLists.txt
+++ b/tools/lldb-mi/CMakeLists.txt
@@ -93,3 +93,7 @@ add_lldb_tool(lldb-mi
LINK_COMPONENTS
Support
)
+
+if(LLDB_BUILD_FRAMEWORK)
+ lldb_setup_framework_rpaths_in_tool(lldb-mi)
+endif()
diff --git a/tools/lldb-mi/MICmdArgSet.h b/tools/lldb-mi/MICmdArgSet.h
index cb321f0204d2..88716a91f0ad 100644
--- a/tools/lldb-mi/MICmdArgSet.h
+++ b/tools/lldb-mi/MICmdArgSet.h
@@ -9,12 +9,8 @@
#pragma once
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "MICmdArgContext.h"
#include "MICmnBase.h"
diff --git a/tools/lldb-mi/MICmdArgValBase.cpp b/tools/lldb-mi/MICmdArgValBase.cpp
index bedd983a06f6..8b1706db93ef 100644
--- a/tools/lldb-mi/MICmdArgValBase.cpp
+++ b/tools/lldb-mi/MICmdArgValBase.cpp
@@ -7,10 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "MICmdArgValBase.h"
#include "MICmdArgContext.h"
#include "MIUtilString.h"
diff --git a/tools/lldb-mi/MICmdArgValBase.h b/tools/lldb-mi/MICmdArgValBase.h
index 288476082806..1b4582963e57 100644
--- a/tools/lldb-mi/MICmdArgValBase.h
+++ b/tools/lldb-mi/MICmdArgValBase.h
@@ -9,10 +9,6 @@
#pragma once
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "MICmdArgSet.h"
#include "MIUtilString.h"
diff --git a/tools/lldb-mi/MICmdArgValConsume.cpp b/tools/lldb-mi/MICmdArgValConsume.cpp
index 5a76ab4b56f5..86c4f0912565 100644
--- a/tools/lldb-mi/MICmdArgValConsume.cpp
+++ b/tools/lldb-mi/MICmdArgValConsume.cpp
@@ -67,7 +67,7 @@ bool CMICmdArgValConsume::Validate(CMICmdArgContext &vwArgContext) {
while (it != vecOptions.end()) {
const CMIUtilString &rTxt(*it);
- if (rTxt.compare("--") == 0) {
+ if (rTxt == "--") {
m_bFound = true;
m_bValid = true;
if (!vwArgContext.RemoveArg(rTxt))
diff --git a/tools/lldb-mi/MICmdArgValFile.cpp b/tools/lldb-mi/MICmdArgValFile.cpp
index 77e9a6b2af8e..cb2ba0125903 100644
--- a/tools/lldb-mi/MICmdArgValFile.cpp
+++ b/tools/lldb-mi/MICmdArgValFile.cpp
@@ -158,10 +158,7 @@ bool CMICmdArgValFile::IsFilePath(const CMIUtilString &vrFileNamePath) const {
return false;
const bool bValidChars = IsValidChars(vrFileNamePath);
- if (bValidChars || bHavePosSlash || bHaveBckSlash)
- return true;
-
- return false;
+ return bValidChars || bHavePosSlash || bHaveBckSlash;
}
//++
diff --git a/tools/lldb-mi/MICmdArgValOptionLong.cpp b/tools/lldb-mi/MICmdArgValOptionLong.cpp
index 70faab900f63..3824fe19188a 100644
--- a/tools/lldb-mi/MICmdArgValOptionLong.cpp
+++ b/tools/lldb-mi/MICmdArgValOptionLong.cpp
@@ -252,10 +252,7 @@ bool CMICmdArgValOptionLong::IsArgLongOption(const CMIUtilString &vrTxt) const {
return false;
const CMIUtilString strArg = vrTxt.substr(2);
- if (strArg.IsNumber())
- return false;
-
- return true;
+ return !strArg.IsNumber();
}
//++
diff --git a/tools/lldb-mi/MICmdArgValString.cpp b/tools/lldb-mi/MICmdArgValString.cpp
index e872f3630587..28d4d18c361b 100644
--- a/tools/lldb-mi/MICmdArgValString.cpp
+++ b/tools/lldb-mi/MICmdArgValString.cpp
@@ -33,7 +33,7 @@ CMICmdArgValString::CMICmdArgValString()
// Throws: None.
//--
CMICmdArgValString::CMICmdArgValString(const bool vbAnything)
- : m_bHandleQuotedString(vbAnything ? true : false), m_bAcceptNumbers(false),
+ : m_bHandleQuotedString(vbAnything), m_bAcceptNumbers(false),
m_bHandleDirPaths(false), m_bHandleAnything(vbAnything) {}
//++
@@ -391,8 +391,5 @@ bool CMICmdArgValString::IsStringArgQuotedQuotedTextEmbedded(
return false;
const size_t nLen = vrTxt.length();
- if ((nLen > 5) && ((nPos + 2) == (nPos2 - 2)))
- return false;
-
- return true;
+ return !((nLen > 5) && ((nPos + 2) == (nPos2 - 2)));
}
diff --git a/tools/lldb-mi/MICmdArgValThreadGrp.cpp b/tools/lldb-mi/MICmdArgValThreadGrp.cpp
index 613ad0dcc348..4ed83e6191e1 100644
--- a/tools/lldb-mi/MICmdArgValThreadGrp.cpp
+++ b/tools/lldb-mi/MICmdArgValThreadGrp.cpp
@@ -115,10 +115,7 @@ bool CMICmdArgValThreadGrp::IsArgThreadGrp(const CMIUtilString &vrTxt) const {
return false;
const CMIUtilString strNum = vrTxt.substr(1);
- if (!strNum.IsNumber())
- return false;
-
- return true;
+ return strNum.IsNumber();
}
//++
diff --git a/tools/lldb-mi/MICmdBase.h b/tools/lldb-mi/MICmdBase.h
index cb44504a1613..fe6aadd66999 100644
--- a/tools/lldb-mi/MICmdBase.h
+++ b/tools/lldb-mi/MICmdBase.h
@@ -9,14 +9,10 @@
#pragma once
-// C Includes
-// C++ Includes
-#include <functional> // for function
+#include <functional>
-// Other libraries and framework includes
#include "lldb/API/SBError.h"
-// Project includes
#include "MICmdArgSet.h"
#include "MICmdData.h"
#include "MICmdFactory.h"
diff --git a/tools/lldb-mi/MICmdCmdBreak.cpp b/tools/lldb-mi/MICmdCmdBreak.cpp
index caad9192366f..0e42f8562ab4 100644
--- a/tools/lldb-mi/MICmdCmdBreak.cpp
+++ b/tools/lldb-mi/MICmdCmdBreak.cpp
@@ -165,8 +165,15 @@ bool CMICmdCmdBreakInsert::Execute() {
if (sbTarget == rSessionInfo.GetDebugger().GetDummyTarget())
m_bBrkPtIsPending = true;
- else
+ else {
m_bBrkPtIsPending = pArgPendingBrkPt->GetFound();
+ if (!m_bBrkPtIsPending) {
+ CMIUtilString pending;
+ if (m_rLLDBDebugSessionInfo.SharedDataRetrieve("breakpoint.pending", pending)) {
+ m_bBrkPtIsPending = pending == "on";
+ }
+ }
+ }
if (pArgLocation->GetFound())
m_brkName = pArgLocation->GetValue();
diff --git a/tools/lldb-mi/MICmdCmdData.cpp b/tools/lldb-mi/MICmdCmdData.cpp
index 53c2d7e621a7..7a4845bba430 100644
--- a/tools/lldb-mi/MICmdCmdData.cpp
+++ b/tools/lldb-mi/MICmdCmdData.cpp
@@ -23,9 +23,9 @@
#include "lldb/API/SBInstructionList.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBThread.h"
-#include "llvm/ADT/Twine.h"
#include "llvm/ADT/StringRef.h"
-#include <inttypes.h> // For PRIx64
+#include "llvm/ADT/Twine.h"
+#include <inttypes.h>
#include <string>
// In-house headers:
diff --git a/tools/lldb-mi/MICmdCmdGdbInfo.cpp b/tools/lldb-mi/MICmdCmdGdbInfo.cpp
index ba96319469a1..5988066883d1 100644
--- a/tools/lldb-mi/MICmdCmdGdbInfo.cpp
+++ b/tools/lldb-mi/MICmdCmdGdbInfo.cpp
@@ -11,7 +11,7 @@
// Third party headers:
#include "lldb/API/SBCommandReturnObject.h"
-#include <inttypes.h> // For PRIx64
+#include <inttypes.h>
// In-house headers:
#include "MICmdArgValString.h"
diff --git a/tools/lldb-mi/MICmdCmdGdbSet.cpp b/tools/lldb-mi/MICmdCmdGdbSet.cpp
index 9f7325c931fc..b433f7678449 100644
--- a/tools/lldb-mi/MICmdCmdGdbSet.cpp
+++ b/tools/lldb-mi/MICmdCmdGdbSet.cpp
@@ -28,7 +28,8 @@ const CMICmdCmdGdbSet::MapGdbOptionNameToFnGdbOptionPtr_t
{"output-radix", &CMICmdCmdGdbSet::OptionFnOutputRadix},
{"solib-search-path", &CMICmdCmdGdbSet::OptionFnSolibSearchPath},
{"disassembly-flavor", &CMICmdCmdGdbSet::OptionFnDisassemblyFlavor},
- {"fallback", &CMICmdCmdGdbSet::OptionFnFallback}};
+ {"fallback", &CMICmdCmdGdbSet::OptionFnFallback},
+ {"breakpoint", &CMICmdCmdGdbSet::OptionFnBreakpoint}};
//++
//------------------------------------------------------------------------------------
@@ -433,6 +434,56 @@ bool CMICmdCmdGdbSet::OptionFnDisassemblyFlavor(
//++
//------------------------------------------------------------------------------------
+// Details: Carry out work to complete the GDB set option 'breakpoint' to
+// prepare
+// and send back information asked for.
+// Type: Method.
+// Args: vrWords - (R) List of additional parameters used by this option.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbSet::OptionFnBreakpoint(
+ const CMIUtilString::VecString_t &vrWords) {
+ bool bPending = false;
+ bool bOk = true;
+
+ if (vrWords.size() != 2)
+ // Wrong number of arguments.
+ bOk = false;
+ else if (CMIUtilString::Compare(vrWords[0], "pending") &&
+ (CMIUtilString::Compare(vrWords[1], "on") ||
+ CMIUtilString::Compare(vrWords[1], "1")))
+ bPending = true;
+ else if (CMIUtilString::Compare(vrWords[0], "pending") &&
+ (CMIUtilString::Compare(vrWords[1], "off") ||
+ CMIUtilString::Compare(vrWords[1], "0")))
+ bPending = false;
+ else
+ // Unrecognized argument(s).
+ bOk = false;
+
+ if (!bOk) {
+ // Report error.
+ m_bGbbOptionFnHasError = false;
+ SetError(MIRSRC(IDS_CMD_ERR_GDBSET_OPT_BREAKPOINT));
+ return MIstatus::failure;
+ }
+
+ CMIUtilString sPendingVal = bPending ? "on" : "off";
+ CMIUtilString sKey = "breakpoint.pending";
+ if (!m_rLLDBDebugSessionInfo.SharedDataAdd(sKey, sPendingVal)) {
+ m_bGbbOptionFnHasError = false;
+ SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD),
+ m_cmdData.strMiCmd.c_str(), sKey.c_str()));
+ return MIstatus::failure;
+ }
+
+ return MIstatus::success;
+}
+
+//++
+//------------------------------------------------------------------------------------
// Details: Carry out work to complete the GDB set option to prepare and send
// back the
// requested information.
diff --git a/tools/lldb-mi/MICmdCmdGdbSet.h b/tools/lldb-mi/MICmdCmdGdbSet.h
index 730754f7f82a..7cca20c3348d 100644
--- a/tools/lldb-mi/MICmdCmdGdbSet.h
+++ b/tools/lldb-mi/MICmdCmdGdbSet.h
@@ -80,6 +80,7 @@ private:
bool OptionFnSolibSearchPath(const CMIUtilString::VecString_t &vrWords);
bool OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords);
bool OptionFnDisassemblyFlavor(const CMIUtilString::VecString_t &vrWords);
+ bool OptionFnBreakpoint(const CMIUtilString::VecString_t &vrWords);
bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords);
// Attributes:
diff --git a/tools/lldb-mi/MICmdCmdGdbShow.cpp b/tools/lldb-mi/MICmdCmdGdbShow.cpp
index 4ae45f8579e2..196b8271064f 100644
--- a/tools/lldb-mi/MICmdCmdGdbShow.cpp
+++ b/tools/lldb-mi/MICmdCmdGdbShow.cpp
@@ -32,7 +32,8 @@ const CMICmdCmdGdbShow::MapGdbOptionNameToFnGdbOptionPtr_t
{"print", &CMICmdCmdGdbShow::OptionFnPrint},
{"language", &CMICmdCmdGdbShow::OptionFnLanguage},
{"disassembly-flavor", &CMICmdCmdGdbShow::OptionFnDisassemblyFlavor},
- {"fallback", &CMICmdCmdGdbShow::OptionFnFallback}};
+ {"fallback", &CMICmdCmdGdbShow::OptionFnFallback},
+ {"breakpoint", &CMICmdCmdGdbShow::OptionFnBreakpoint}};
//++
//------------------------------------------------------------------------------------
@@ -349,6 +350,43 @@ bool CMICmdCmdGdbShow::OptionFnDisassemblyFlavor(const CMIUtilString::VecString_
//++
//------------------------------------------------------------------------------------
+// Details: Carry out work to complete the GDB show option 'breakpoint' to
+// prepare
+// and send back the requested information.
+// Type: Method.
+// Args: vrWords - (R) List of additional parameters used by this option.
+// Return: MIstatus::success - Function succeeded.
+// MIstatus::failure - Function failed.
+// Throws: None.
+//--
+bool CMICmdCmdGdbShow::OptionFnBreakpoint(
+ const CMIUtilString::VecString_t &vrWords) {
+ if (vrWords.size() != 1) {
+ m_bGbbOptionFnHasError = true;
+ m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_BREAKPOINT_BAD_ARGS);
+ return MIstatus::failure;
+ }
+
+ const CMIUtilString strOption(vrWords[0]);
+ if (!CMIUtilString::Compare(strOption, "pending")) {
+ m_bGbbOptionFnHasError = true;
+ m_strGdbOptionFnError = CMIUtilString::Format(
+ MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_BREAKPOINT_UNKNOWN_OPTION),
+ strOption.c_str());
+ return MIstatus::failure;
+ }
+
+ if (!m_rLLDBDebugSessionInfo.SharedDataRetrieve("breakpoint.pending",
+ m_strValue)) {
+ if (m_strValue.empty())
+ m_strValue = "off";
+ }
+
+ return MIstatus::success;
+}
+
+//++
+//------------------------------------------------------------------------------------
// Details: Carry out work to complete the GDB show option to prepare and send
// back the
// requested information.
diff --git a/tools/lldb-mi/MICmdCmdGdbShow.h b/tools/lldb-mi/MICmdCmdGdbShow.h
index 452db827032c..51f07092843f 100644
--- a/tools/lldb-mi/MICmdCmdGdbShow.h
+++ b/tools/lldb-mi/MICmdCmdGdbShow.h
@@ -80,6 +80,7 @@ private:
bool OptionFnLanguage(const CMIUtilString::VecString_t &vrWords);
bool OptionFnDisassemblyFlavor(const CMIUtilString::VecString_t &vrWords);
bool OptionFnFallback(const CMIUtilString::VecString_t &vrWords);
+ bool OptionFnBreakpoint(const CMIUtilString::VecString_t &vrWords);
// Attributes:
private:
diff --git a/tools/lldb-mi/MICmdCmdTarget.cpp b/tools/lldb-mi/MICmdCmdTarget.cpp
index a82bd682de81..0666fc4c60ec 100644
--- a/tools/lldb-mi/MICmdCmdTarget.cpp
+++ b/tools/lldb-mi/MICmdCmdTarget.cpp
@@ -10,9 +10,8 @@
// Overview: CMICmdCmdTargetSelect implementation.
// Third Party Headers:
-#include "lldb/API/SBCommandInterpreter.h"
-#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBStream.h"
+#include "lldb/API/SBError.h"
// In-house headers:
#include "MICmdArgValNumber.h"
@@ -52,7 +51,7 @@ CMICmdCmdTargetSelect::CMICmdCmdTargetSelect()
// Return: None.
// Throws: None.
//--
-CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect() {}
+CMICmdCmdTargetSelect::~CMICmdCmdTargetSelect() = default;
//++
//------------------------------------------------------------------------------------
@@ -93,16 +92,17 @@ bool CMICmdCmdTargetSelect::Execute() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
+ lldb::SBTarget target = rSessionInfo.GetTarget();
- // Check we have a valid target
- // Note: target created via 'file-exec-and-symbols' command
- if (!rSessionInfo.GetTarget().IsValid()) {
+ // Check we have a valid target.
+ // Note: target created via 'file-exec-and-symbols' command.
+ if (!target.IsValid()) {
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT),
m_cmdData.strMiCmd.c_str()));
return MIstatus::failure;
}
- // Verify that we are executing remotely
+ // Verify that we are executing remotely.
const CMIUtilString &rRemoteType(pArgType->GetValue());
if (rRemoteType != "remote") {
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_TYPE),
@@ -111,33 +111,25 @@ bool CMICmdCmdTargetSelect::Execute() {
return MIstatus::failure;
}
- // Create a URL pointing to the remote gdb stub
+ // Create a URL pointing to the remote gdb stub.
const CMIUtilString strUrl =
CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str());
- // Ask LLDB to connect to the target port
- const char *pPlugin("gdb-remote");
lldb::SBError error;
- lldb::SBProcess process = rSessionInfo.GetTarget().ConnectRemote(
+ // Ask LLDB to connect to the target port.
+ const char *pPlugin("gdb-remote");
+ lldb::SBProcess process = target.ConnectRemote(
rSessionInfo.GetListener(), strUrl.c_str(), pPlugin, error);
- // Verify that we have managed to connect successfully
- lldb::SBStream errMsg;
- error.GetDescription(errMsg);
+ // Verify that we have managed to connect successfully.
if (!process.IsValid()) {
SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN),
m_cmdData.strMiCmd.c_str(),
- errMsg.GetData()));
- return MIstatus::failure;
- }
- if (error.Fail()) {
- SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CONNECT_TO_TARGET),
- m_cmdData.strMiCmd.c_str(),
- errMsg.GetData()));
+ error.GetCString()));
return MIstatus::failure;
}
- // Set the environment path if we were given one
+ // Set the environment path if we were given one.
CMIUtilString strWkDir;
if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(
rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) {
@@ -150,28 +142,13 @@ bool CMICmdCmdTargetSelect::Execute() {
}
}
- // Set the shared object path if we were given one
+ // Set the shared object path if we were given one.
CMIUtilString strSolibPath;
if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(
- rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath)) {
- lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger();
- lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter();
-
- CMIUtilString strCmdString = CMIUtilString::Format(
- "target modules search-paths add . %s", strSolibPath.c_str());
-
- lldb::SBCommandReturnObject retObj;
- cmdIterpreter.HandleCommand(strCmdString.c_str(), retObj, false);
+ rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath))
+ target.AppendImageSearchPath(".", strSolibPath.c_str(), error);
- if (!retObj.Succeeded()) {
- SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED),
- m_cmdData.strMiCmd.c_str(),
- "target-select"));
- return MIstatus::failure;
- }
- }
-
- return MIstatus::success;
+ return HandleSBError(error);
}
//++
diff --git a/tools/lldb-mi/MICmdFactory.cpp b/tools/lldb-mi/MICmdFactory.cpp
index 8f6215463627..ad4283e50215 100644
--- a/tools/lldb-mi/MICmdFactory.cpp
+++ b/tools/lldb-mi/MICmdFactory.cpp
@@ -128,10 +128,7 @@ bool CMICmdFactory::CmdRegister(const CMIUtilString &vMiCmd,
bool CMICmdFactory::HaveAlready(const CMIUtilString &vMiCmd) const {
const MapMiCmdToCmdCreatorFn_t::const_iterator it =
m_mapMiCmdToCmdCreatorFn.find(vMiCmd);
- if (it != m_mapMiCmdToCmdCreatorFn.end())
- return true;
-
- return false;
+ return it != m_mapMiCmdToCmdCreatorFn.end();
}
//++
diff --git a/tools/lldb-mi/MICmnBase.cpp b/tools/lldb-mi/MICmnBase.cpp
index 63544dc5b9c7..7f82c6120e1a 100644
--- a/tools/lldb-mi/MICmnBase.cpp
+++ b/tools/lldb-mi/MICmnBase.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
// Third party headers
-#include <stdarg.h> // va_list, va_start, var_end
+#include <stdarg.h>
// In-house headers:
#include "MICmnBase.h"
diff --git a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
index 9a173d1007e2..f7f43f001b7b 100644
--- a/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ b/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -9,11 +9,11 @@
// Third party headers:
#include "lldb/API/SBThread.h"
-#include <inttypes.h> // For PRIx64
+#include <inttypes.h>
#ifdef _WIN32
-#include <io.h> // For the ::_access()
+#include <io.h>
#else
-#include <unistd.h> // For the ::access()
+#include <unistd.h>
#endif // _WIN32
#include "lldb/API/SBBreakpointLocation.h"
@@ -532,7 +532,7 @@ bool CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue,
const bool vbInSimpleForm,
CMIUtilString &vwrStrValue) {
const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false);
- const bool bExpandAggregates = vbInSimpleForm ? false : true;
+ const bool bExpandAggregates = !vbInSimpleForm;
vwrStrValue = utilValue.GetValue(bExpandAggregates);
return MIstatus::success;
}
diff --git a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
index dceb29f5908f..cd54c2bb5bc4 100644
--- a/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
+++ b/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
@@ -20,9 +20,9 @@
#include "lldb/API/SBUnixSignals.h"
#include "llvm/Support/Compiler.h"
#ifdef _WIN32
-#include <io.h> // For the ::_access()
+#include <io.h>
#else
-#include <unistd.h> // For the ::access()
+#include <unistd.h>
#endif // _WIN32
// In-house headers:
@@ -39,7 +39,7 @@
#include "MICmnStreamStdout.h"
#include "MIDriver.h"
#include "MIUtilDebug.h"
-#include "Platform.h" // for PATH_MAX
+#include "Platform.h"
#include <algorithm>
@@ -437,10 +437,10 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(
sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
sBrkPtInfo.m_bPending = false;
const char *pStrCondition = brkPt.GetCondition();
- sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
+ sBrkPtInfo.m_bCondition = pStrCondition != nullptr;
sBrkPtInfo.m_strCondition =
(pStrCondition != nullptr) ? pStrCondition : "??";
- sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
+ sBrkPtInfo.m_bBrkPtThreadId = brkPt.GetThreadID() != 0;
sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
}
@@ -950,6 +950,7 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(
bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(
const lldb::SBEvent &vEvent) {
bool bOk = MIstatus::success;
+ lldb::SBStream streamOut;
lldb::SBDebugger &rDebugger =
CMICmnLLDBDebugSessionInfo::Instance().GetDebugger();
lldb::SBProcess sbProcess =
@@ -958,16 +959,17 @@ bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(
if (rDebugger.GetSelectedTarget() == target) {
if (!UpdateSelectedThread())
return MIstatus::failure;
-
- lldb::SBCommandReturnObject result;
- const lldb::ReturnStatus status =
- rDebugger.GetCommandInterpreter().HandleCommand("process status",
- result, false);
- MIunused(status);
- bOk = TextToStderr(result.GetError());
- bOk = bOk && TextToStdout(result.GetOutput());
+ sbProcess.GetDescription(streamOut);
+ // Add a delimiter between process' and threads' info.
+ streamOut.Printf("\n");
+ for (uint32_t i = 0, e = sbProcess.GetNumThreads(); i < e; ++i) {
+ const lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
+ if (!thread.IsValid())
+ continue;
+ thread.GetDescription(streamOut);
+ }
+ bOk = TextToStdout(streamOut.GetData());
} else {
- lldb::SBStream streamOut;
const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
if (nTargetIndex != UINT_MAX)
streamOut.Printf("Target %d: (", nTargetIndex);
diff --git a/tools/lldb-mi/MICmnLog.cpp b/tools/lldb-mi/MICmnLog.cpp
index 8643a8784e35..d30c03f5063d 100644
--- a/tools/lldb-mi/MICmnLog.cpp
+++ b/tools/lldb-mi/MICmnLog.cpp
@@ -209,10 +209,7 @@ bool CMICmnLog::RegisterMedium(const IMedium &vrMedium) {
bool CMICmnLog::HaveMediumAlready(const IMedium &vrMedium) const {
IMedium *pMedium = const_cast<IMedium *>(&vrMedium);
const MapMediumToName_t::const_iterator it = m_mapMediumToName.find(pMedium);
- if (it != m_mapMediumToName.end())
- return true;
-
- return false;
+ return it != m_mapMediumToName.end();
}
//++
diff --git a/tools/lldb-mi/MICmnResources.cpp b/tools/lldb-mi/MICmnResources.cpp
index e32a816fc9f1..d8fa0a829245 100644
--- a/tools/lldb-mi/MICmnResources.cpp
+++ b/tools/lldb-mi/MICmnResources.cpp
@@ -9,7 +9,7 @@
// Third party headers
#include "assert.h"
-#include <inttypes.h> // For PRIx64
+#include <inttypes.h>
// In-house headers:
#include "MICmnResources.h"
@@ -78,7 +78,7 @@ const CMICmnResources::SRsrcTextData
"and a custom plugin.\nThe custom plugin is not necessary to operate "
"the MI Driver."},
{IDE_MI_APP_ARG_USAGE, "\nMI driver usage:\n\n\tlldb-mi [--longOption] "
- "[-s hortOption] [executeable]\n\n[] = optional "
+ "[-s hortOption] [executable]\n\n[] = optional "
"argument."},
{IDE_MI_APP_ARG_HELP, "-h\n--help\n\tPrints out usage information for "
"the MI debugger. Exit the MI\n\tDriver "
@@ -439,6 +439,8 @@ const CMICmnResources::SRsrcTextData
{IDS_CMD_ERR_INFO_PRINTFN_FAILED, "The request '%s' failed."},
{IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC,
"'target-async' expects \"on\" or \"off\""},
+ {IDS_CMD_ERR_GDBSET_OPT_BREAKPOINT,
+ "'breakpoint' expects \"pending on\" or \"pending off\""},
{IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH,
"'solib-search-path' requires at least one argument"},
{IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS,
@@ -449,6 +451,10 @@ const CMICmnResources::SRsrcTextData
"'print' expects option-name and \"on\" or \"off\""},
{IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION,
"'print' error. The option '%s' not found"},
+ {IDS_CMD_ERR_GDBSHOW_OPT_BREAKPOINT_BAD_ARGS,
+ "'breakpoint' expects option-name"},
+ {IDS_CMD_ERR_GDBSHOW_OPT_BREAKPOINT_UNKNOWN_OPTION,
+ "'breakpoint' error. The option '%s' not found"},
{IDS_CMD_ERR_EXPR_INVALID, "Failed to evaluate expression: %s"},
{IDS_CMD_ERR_ATTACH_FAILED,
"Command '%s'. Attach to process failed: %s"},
diff --git a/tools/lldb-mi/MICmnResources.h b/tools/lldb-mi/MICmnResources.h
index 8912a2b8463e..4177a95a5488 100644
--- a/tools/lldb-mi/MICmnResources.h
+++ b/tools/lldb-mi/MICmnResources.h
@@ -264,11 +264,14 @@ enum {
IDS_CMD_ERR_INFO_PRINTFN_NOT_FOUND,
IDS_CMD_ERR_INFO_PRINTFN_FAILED,
IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC,
+ IDS_CMD_ERR_GDBSET_OPT_BREAKPOINT,
IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH,
IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS,
IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION,
IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS,
IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION,
+ IDS_CMD_ERR_GDBSHOW_OPT_BREAKPOINT_BAD_ARGS,
+ IDS_CMD_ERR_GDBSHOW_OPT_BREAKPOINT_UNKNOWN_OPTION,
IDS_CMD_ERR_EXPR_INVALID,
IDS_CMD_ERR_ATTACH_FAILED,
IDS_CMD_ERR_ATTACH_BAD_ARGS
diff --git a/tools/lldb-mi/MICmnStreamStdin.cpp b/tools/lldb-mi/MICmnStreamStdin.cpp
index 154519dbec4c..4d3fa2aabd96 100644
--- a/tools/lldb-mi/MICmnStreamStdin.cpp
+++ b/tools/lldb-mi/MICmnStreamStdin.cpp
@@ -11,7 +11,7 @@
#ifdef _MSC_VER
#include <windows.h>
#endif
-#include <string.h> // For std::strerror()
+#include <string.h>
// In-house headers:
#include "MICmnLog.h"
diff --git a/tools/lldb-mi/MIDataTypes.h b/tools/lldb-mi/MIDataTypes.h
index 34fe4575160e..59ff099389cb 100644
--- a/tools/lldb-mi/MIDataTypes.h
+++ b/tools/lldb-mi/MIDataTypes.h
@@ -21,7 +21,7 @@
// Debugging:
#ifdef _DEBUG
-#include <crtdbg.h> // C-runtime debugging library (defines _ASSERT).
+#include <crtdbg.h>
#endif // _DEBUG
#endif // _WIN32
diff --git a/tools/lldb-mi/MIDriver.cpp b/tools/lldb-mi/MIDriver.cpp
index 23039110b428..cb8fb1c2c25f 100644
--- a/tools/lldb-mi/MIDriver.cpp
+++ b/tools/lldb-mi/MIDriver.cpp
@@ -443,8 +443,7 @@ lldb::SBError CMIDriver::ParseArgs(const int argc, const char *argv[],
CMICmdArgValString(true, false, true).IsStringArg(strArg)) {
// Is this the command file for the '-s' or '--source' options?
const CMIUtilString strPrevArg(argv[i - 1]);
- if (strPrevArg.compare("-s") == 0 ||
- strPrevArg.compare("--source") == 0) {
+ if (strPrevArg == "-s" || strPrevArg == "--source") {
m_strCmdLineArgCommandFileNamePath = strArg;
m_bHaveCommandFileNamePathOnCmdLine = true;
i--; // skip '-s' on the next loop
@@ -457,7 +456,7 @@ lldb::SBError CMIDriver::ParseArgs(const int argc, const char *argv[],
}
// Report error if no command file was specified for the '-s' or
// '--source' options
- else if (strArg.compare("-s") == 0 || strArg.compare("--source") == 0) {
+ else if (strArg == "-s" || strArg == "--source") {
vwbExiting = true;
const CMIUtilString errMsg = CMIUtilString::Format(
MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF), strArg.c_str());
@@ -465,13 +464,13 @@ lldb::SBError CMIDriver::ParseArgs(const int argc, const char *argv[],
break;
}
// This argument is also checked for in CMIDriverMgr::ParseArgs()
- else if (strArg.compare("--executable") == 0) // Used to specify that
- // there is executable
- // argument also on the
- // command line
- { // See fn description.
+ else if (strArg == "--executable") // Used to specify that
+ // there is executable
+ // argument also on the
+ // command line
+ { // See fn description.
bHaveExecutableLongOption = true;
- } else if (strArg.compare("--synchronous") == 0) {
+ } else if (strArg == "--synchronous") {
CMICmnLLDBDebugSessionInfo::Instance().GetDebugger().SetAsync(false);
}
}
diff --git a/tools/lldb-mi/MIDriverMain.cpp b/tools/lldb-mi/MIDriverMain.cpp
index 1b3521e8f03f..d347ecbbebeb 100644
--- a/tools/lldb-mi/MIDriverMain.cpp
+++ b/tools/lldb-mi/MIDriverMain.cpp
@@ -42,7 +42,7 @@
#include "MIDriver.h"
#include "MIDriverMgr.h"
#include "MIUtilDebug.h"
-#include "Platform.h" // Define signals - CODETAG_IOR_SIGNALS
+#include "Platform.h"
#if defined(_MSC_VER)
#pragma warning( \
@@ -165,11 +165,7 @@ bool DriverSystemShutdown(const bool vbAppExitOk) {
//--
int main(int argc, char const *argv[]) {
#if MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
-#ifdef _WIN32
- CMIUtilDebug::ShowDlgWaitForDbgAttach();
-#else
CMIUtilDebug::WaitForDbgAttachInfinteLoop();
-#endif // _WIN32
#endif // MICONFIG_DEBUG_SHOW_ATTACH_DBG_DLG
llvm::StringRef ToolName = argv[0];
diff --git a/tools/lldb-mi/MIDriverMgr.cpp b/tools/lldb-mi/MIDriverMgr.cpp
index 6b39832d736e..93070a5912d6 100644
--- a/tools/lldb-mi/MIDriverMgr.cpp
+++ b/tools/lldb-mi/MIDriverMgr.cpp
@@ -516,29 +516,27 @@ bool CMIDriverMgr::ParseArgs(const int argc, const char *argv[],
const CMIUtilString strArg(argv[i]);
// Argument "--executable" is also check for in CMIDriver::ParseArgs()
- if ((0 ==
- strArg.compare(
- "--interpreter")) || // Given by the client such as Eclipse
- (0 == strArg.compare("--executable"))) // Used to specify that there
- // is executable argument also
- // on the command line
- { // See fn description.
+ if (("--interpreter" == strArg) || // Given by the client such as Eclipse
+ ("--executable" == strArg)) // Used to specify that there
+ // is executable argument also
+ // on the command line
+ { // See fn description.
bHaveArgInterpret = true;
}
- if (0 == strArg.compare("--version")) {
+ if ("--version" == strArg) {
bHaveArgVersion = true;
}
- if (0 == strArg.compare("--versionLong")) {
+ if ("--versionLong" == strArg) {
bHaveArgVersionLong = true;
}
- if (0 == strArg.compare("--log")) {
+ if ("--log" == strArg) {
bHaveArgLog = true;
}
if (0 == strArg.compare(0, 10, "--log-dir=")) {
strLogDir = strArg.substr(10, CMIUtilString::npos);
bHaveArgLogDir = true;
}
- if ((0 == strArg.compare("--help")) || (0 == strArg.compare("-h"))) {
+ if (("--help" == strArg) || ("-h" == strArg)) {
bHaveArgHelp = true;
}
}
diff --git a/tools/lldb-mi/MIUtilDebug.cpp b/tools/lldb-mi/MIUtilDebug.cpp
index 519fd950feb2..598a1a71046b 100644
--- a/tools/lldb-mi/MIUtilDebug.cpp
+++ b/tools/lldb-mi/MIUtilDebug.cpp
@@ -39,25 +39,6 @@ CMIUtilDebug::~CMIUtilDebug() {}
//++
//------------------------------------------------------------------------------------
-// Details: Show a dialog to the process/application halts. It gives the
-// opportunity to
-// attach a debugger.
-// Type: Static method.
-// Args: None.
-// Return: None.
-// Throws: None.
-//--
-void CMIUtilDebug::ShowDlgWaitForDbgAttach() {
- const CMIUtilString strCaption(CMIDriver::Instance().GetAppNameShort());
-#ifdef _WIN32
- ::MessageBoxA(NULL, "Attach your debugger now", strCaption.c_str(), MB_OK);
-#else
-// ToDo: Implement other platform version of an Ok to continue dialog box
-#endif // _WIN32
-}
-
-//++
-//------------------------------------------------------------------------------------
// Details: Temporarily stall the process/application to give the programmer the
// opportunity to attach a debugger. How to use: Put a break in the
// programmer
diff --git a/tools/lldb-mi/MIUtilDebug.h b/tools/lldb-mi/MIUtilDebug.h
index a49fd9a868ec..16b080ee7b62 100644
--- a/tools/lldb-mi/MIUtilDebug.h
+++ b/tools/lldb-mi/MIUtilDebug.h
@@ -24,7 +24,6 @@ class CMICmnLog;
class CMIUtilDebug {
// Statics:
public:
- static void ShowDlgWaitForDbgAttach();
static void WaitForDbgAttachInfinteLoop();
// Methods:
diff --git a/tools/lldb-mi/MIUtilFileStd.cpp b/tools/lldb-mi/MIUtilFileStd.cpp
index 1e76c1c58fe2..abf0ef407d3b 100644
--- a/tools/lldb-mi/MIUtilFileStd.cpp
+++ b/tools/lldb-mi/MIUtilFileStd.cpp
@@ -11,7 +11,7 @@
#include <assert.h>
#include <cerrno>
#include <stdio.h>
-#include <string.h> // For strerror()
+#include <string.h>
// In-house headers:
#include "MICmnResources.h"
diff --git a/tools/lldb-mi/MIUtilMapIdToVariant.cpp b/tools/lldb-mi/MIUtilMapIdToVariant.cpp
index 52bc413a471f..0a4e7299e926 100644
--- a/tools/lldb-mi/MIUtilMapIdToVariant.cpp
+++ b/tools/lldb-mi/MIUtilMapIdToVariant.cpp
@@ -52,10 +52,7 @@ void CMIUtilMapIdToVariant::Clear() { m_mapKeyToVariantValue.clear(); }
bool CMIUtilMapIdToVariant::HaveAlready(const CMIUtilString &vId) const {
const MapKeyToVariantValue_t::const_iterator it =
m_mapKeyToVariantValue.find(vId);
- if (it != m_mapKeyToVariantValue.end())
- return true;
-
- return false;
+ return it != m_mapKeyToVariantValue.end();
}
//++
diff --git a/tools/lldb-mi/MIUtilString.cpp b/tools/lldb-mi/MIUtilString.cpp
index 3797d1001798..627c2f3d4d3b 100644
--- a/tools/lldb-mi/MIUtilString.cpp
+++ b/tools/lldb-mi/MIUtilString.cpp
@@ -10,12 +10,12 @@
// Third party headers
#include "llvm/Support/Compiler.h"
#include <cstdlib>
-#include <inttypes.h> // for PRIx8
-#include <limits.h> // for ULONG_MAX
-#include <memory> // std::unique_ptr
-#include <sstream> // std::stringstream
-#include <stdarg.h> // va_list, va_start, var_end
-#include <string.h> // for strncmp
+#include <inttypes.h>
+#include <limits.h>
+#include <memory>
+#include <sstream>
+#include <stdarg.h>
+#include <string.h>
// In-house headers:
#include "MIUtilString.h"
@@ -378,10 +378,7 @@ bool CMIUtilString::IsNumber() const {
return false;
const size_t nPos = find_first_not_of("-.0123456789");
- if (nPos != std::string::npos)
- return false;
-
- return true;
+ return nPos == std::string::npos;
}
//++
@@ -399,10 +396,7 @@ bool CMIUtilString::IsHexadecimalNumber() const {
// Skip '0x..' prefix
const size_t nPos = find_first_not_of("01234567890ABCDEFabcedf", 2);
- if (nPos != std::string::npos)
- return false;
-
- return true;
+ return nPos == std::string::npos;
}
//++
@@ -419,10 +413,7 @@ bool CMIUtilString::ExtractNumber(MIint64 &vwrNumber) const {
vwrNumber = 0;
if (!IsNumber()) {
- if (ExtractNumberFromHexadecimal(vwrNumber))
- return true;
-
- return false;
+ return ExtractNumberFromHexadecimal(vwrNumber);
}
std::stringstream ss(const_cast<CMIUtilString &>(*this));
@@ -639,10 +630,7 @@ bool CMIUtilString::IsQuoted() const {
return false;
const size_t nLen = length();
- if ((nLen > 0) && (at(nLen - 1) != cQuote))
- return false;
-
- return true;
+ return !((nLen > 0) && (at(nLen - 1) != cQuote));
}
//++
diff --git a/tools/lldb-server/CMakeLists.txt b/tools/lldb-server/CMakeLists.txt
index c74f553e9659..5b138534404f 100644
--- a/tools/lldb-server/CMakeLists.txt
+++ b/tools/lldb-server/CMakeLists.txt
@@ -42,7 +42,7 @@ else()
list(APPEND LLDB_PLUGINS lldbPluginObjectFileELF)
endif()
-add_lldb_tool(lldb-server INCLUDE_IN_SUITE
+add_lldb_tool(lldb-server
Acceptor.cpp
lldb-gdbserver.cpp
lldb-platform.cpp
diff --git a/tools/lldb-server/SystemInitializerLLGS.cpp b/tools/lldb-server/SystemInitializerLLGS.cpp
index aeaf382a1dd8..93ef4d9d0761 100644
--- a/tools/lldb-server/SystemInitializerLLGS.cpp
+++ b/tools/lldb-server/SystemInitializerLLGS.cpp
@@ -22,9 +22,14 @@ using HostObjectFile = ObjectFileELF;
using namespace lldb_private;
-void SystemInitializerLLGS::Initialize() {
- SystemInitializerCommon::Initialize();
+llvm::Error
+SystemInitializerLLGS::Initialize(const InitializerOptions &options) {
+ if (auto e = SystemInitializerCommon::Initialize(options))
+ return e;
+
HostObjectFile::Initialize();
+
+ return llvm::Error::success();
}
void SystemInitializerLLGS::Terminate() {
diff --git a/tools/lldb-server/SystemInitializerLLGS.h b/tools/lldb-server/SystemInitializerLLGS.h
index e6460a2cdd39..7feba3fe07bd 100644
--- a/tools/lldb-server/SystemInitializerLLGS.h
+++ b/tools/lldb-server/SystemInitializerLLGS.h
@@ -10,11 +10,13 @@
#ifndef LLDB_SYSTEMINITIALIZERLLGS_H
#define LLDB_SYSTEMINITIALIZERLLGS_H
+#include "lldb/Initialization/SystemInitializer.h"
#include "lldb/Initialization/SystemInitializerCommon.h"
class SystemInitializerLLGS : public lldb_private::SystemInitializerCommon {
public:
- void Initialize() override;
+ llvm::Error
+ Initialize(const lldb_private::InitializerOptions &options) override;
void Terminate() override;
};
diff --git a/tools/lldb-server/lldb-gdbserver.cpp b/tools/lldb-server/lldb-gdbserver.cpp
index c91a8a89e46a..062bbd0c3b6e 100644
--- a/tools/lldb-server/lldb-gdbserver.cpp
+++ b/tools/lldb-server/lldb-gdbserver.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
@@ -19,8 +18,6 @@
#include <unistd.h>
#endif
-// C++ Includes
-
#include "Acceptor.h"
#include "LLDBServerUtilities.h"
@@ -28,6 +25,7 @@
#include "Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostGetOpt.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Host/Pipe.h"
@@ -187,7 +185,9 @@ void handle_launch(GDBRemoteCommunicationServerLLGS &gdb_server, int argc,
llvm::errs() << "Error getting current directory: " << ec.message() << "\n";
exit(1);
}
- info.SetWorkingDirectory(FileSpec(cwd, true));
+ FileSpec cwd_spec(cwd);
+ FileSystem::Instance().Resolve(cwd_spec);
+ info.SetWorkingDirectory(cwd_spec);
info.GetEnvironment() = Host::GetEnvironment();
gdb_server.SetLaunchInfo(info);
@@ -218,20 +218,17 @@ Status writeSocketIdToPipe(const char *const named_pipe_path,
return writeSocketIdToPipe(port_name_pipe, socket_id);
}
-Status writeSocketIdToPipe(int unnamed_pipe_fd, const std::string &socket_id) {
-#if defined(_WIN32)
- return Status("Unnamed pipes are not supported on Windows.");
-#else
- Pipe port_pipe{Pipe::kInvalidDescriptor, unnamed_pipe_fd};
+Status writeSocketIdToPipe(lldb::pipe_t unnamed_pipe,
+ const std::string &socket_id) {
+ Pipe port_pipe{LLDB_INVALID_PIPE, unnamed_pipe};
return writeSocketIdToPipe(port_pipe, socket_id);
-#endif
}
void ConnectToRemote(MainLoop &mainloop,
GDBRemoteCommunicationServerLLGS &gdb_server,
bool reverse_connect, const char *const host_and_port,
const char *const progname, const char *const subcommand,
- const char *const named_pipe_path, int unnamed_pipe_fd,
+ const char *const named_pipe_path, pipe_t unnamed_pipe,
int connection_fd) {
Status error;
@@ -331,8 +328,8 @@ void ConnectToRemote(MainLoop &mainloop,
}
// If we have an unnamed pipe to write the socket id back to, do that
// now.
- else if (unnamed_pipe_fd >= 0) {
- error = writeSocketIdToPipe(unnamed_pipe_fd, socket_id);
+ else if (unnamed_pipe != LLDB_INVALID_PIPE) {
+ error = writeSocketIdToPipe(unnamed_pipe, socket_id);
if (error.Fail())
fprintf(stderr, "failed to write to the unnamed pipe: %s\n",
error.AsCString());
@@ -384,7 +381,7 @@ int main_gdbserver(int argc, char *argv[]) {
std::string log_file;
StringRef
log_channels; // e.g. "lldb process threads:gdb-remote default:linux all"
- int unnamed_pipe_fd = -1;
+ lldb::pipe_t unnamed_pipe = LLDB_INVALID_PIPE;
bool reverse_connect = false;
int connection_fd = -1;
@@ -425,7 +422,7 @@ int main_gdbserver(int argc, char *argv[]) {
case 'U': // unnamed pipe
if (optarg && optarg[0])
- unnamed_pipe_fd = StringConvert::ToUInt32(optarg, -1);
+ unnamed_pipe = (pipe_t)StringConvert::ToUInt64(optarg, -1);
break;
case 'r':
@@ -528,8 +525,8 @@ int main_gdbserver(int argc, char *argv[]) {
printf("%s-%s", LLGS_PROGRAM_NAME, LLGS_VERSION_STR);
ConnectToRemote(mainloop, gdb_server, reverse_connect, host_and_port,
- progname, subcommand, named_pipe_path.c_str(),
- unnamed_pipe_fd, connection_fd);
+ progname, subcommand, named_pipe_path.c_str(),
+ unnamed_pipe, connection_fd);
if (!gdb_server.IsConnected()) {
fprintf(stderr, "no connection information provided, unable to run\n");
diff --git a/tools/lldb-server/lldb-platform.cpp b/tools/lldb-server/lldb-platform.cpp
index cfaf5550d096..b7f7950d4ccf 100644
--- a/tools/lldb-server/lldb-platform.cpp
+++ b/tools/lldb-server/lldb-platform.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
#include <errno.h>
#if defined(__APPLE__)
#include <netinet/in.h>
@@ -19,10 +18,8 @@
#include <string.h>
#include <sys/wait.h>
-// C++ Includes
#include <fstream>
-// Other libraries and framework includes
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
@@ -100,7 +97,7 @@ static void display_usage(const char *progname, const char *subcommand) {
static Status save_socket_id_to_file(const std::string &socket_id,
const FileSpec &file_spec) {
- FileSpec temp_file_spec(file_spec.GetDirectory().AsCString(), false);
+ FileSpec temp_file_spec(file_spec.GetDirectory().AsCString());
Status error(llvm::sys::fs::create_directory(temp_file_spec.GetPath()));
if (error.Fail())
return Status("Failed to create directory %s: %s",
@@ -193,7 +190,7 @@ int main_platform(int argc, char *argv[]) {
case 'f': // Socket file
if (optarg && optarg[0])
- socket_file.SetFile(optarg, false, FileSpec::Style::native);
+ socket_file.SetFile(optarg, FileSpec::Style::native);
break;
case 'p': {
diff --git a/tools/lldb-server/lldb-server.cpp b/tools/lldb-server/lldb-server.cpp
index f05c96cfaa95..c924fa22f310 100644
--- a/tools/lldb-server/lldb-server.cpp
+++ b/tools/lldb-server/lldb-server.cpp
@@ -38,8 +38,9 @@ int main_gdbserver(int argc, char *argv[]);
int main_platform(int argc, char *argv[]);
static void initialize() {
- g_debugger_lifetime->Initialize(llvm::make_unique<SystemInitializerLLGS>(),
- nullptr);
+ if (auto e = g_debugger_lifetime->Initialize(
+ llvm::make_unique<SystemInitializerLLGS>(), {}, nullptr))
+ llvm::consumeError(std::move(e));
}
static void terminate() { g_debugger_lifetime->Terminate(); }
diff --git a/tools/lldb-test/FormatUtil.cpp b/tools/lldb-test/FormatUtil.cpp
index 381cbd6e25b8..970f25a6b42f 100644
--- a/tools/lldb-test/FormatUtil.cpp
+++ b/tools/lldb-test/FormatUtil.cpp
@@ -14,6 +14,11 @@
using namespace lldb_private;
using namespace llvm;
+LinePrinter::Line::~Line() {
+ if (P)
+ P->NewLine();
+}
+
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {}
@@ -31,39 +36,31 @@ void LinePrinter::Unindent(uint32_t Amount) {
void LinePrinter::NewLine() {
OS << "\n";
- OS.indent(CurrentIndent);
-}
-
-void LinePrinter::print(const Twine &T) { OS << T; }
-
-void LinePrinter::printLine(const Twine &T) {
- NewLine();
- OS << T;
}
void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
uint32_t StartOffset) {
- NewLine();
- OS << Label << " (";
- if (!Data.empty()) {
- OS << "\n";
- OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
- CurrentIndent + IndentSpaces, true);
- NewLine();
+ if (Data.empty()) {
+ line() << Label << " ()";
+ return;
}
- OS << ")";
+ line() << Label << " (";
+ OS << format_bytes_with_ascii(Data, StartOffset, 32, 4,
+ CurrentIndent + IndentSpaces, true);
+ NewLine();
+ line() << ")";
}
void LinePrinter::formatBinary(StringRef Label, ArrayRef<uint8_t> Data,
uint64_t Base, uint32_t StartOffset) {
- NewLine();
- OS << Label << " (";
- if (!Data.empty()) {
- OS << "\n";
- Base += StartOffset;
- OS << format_bytes_with_ascii(Data, Base, 32, 4,
- CurrentIndent + IndentSpaces, true);
- NewLine();
+ if (Data.empty()) {
+ line() << Label << " ()";
+ return;
}
- OS << ")";
+ line() << Label << " (";
+ Base += StartOffset;
+ OS << format_bytes_with_ascii(Data, Base, 32, 4, CurrentIndent + IndentSpaces,
+ true);
+ NewLine();
+ line() << ")";
}
diff --git a/tools/lldb-test/FormatUtil.h b/tools/lldb-test/FormatUtil.h
index f22ee41662ee..598d4c5440f5 100644
--- a/tools/lldb-test/FormatUtil.h
+++ b/tools/lldb-test/FormatUtil.h
@@ -26,27 +26,36 @@ class LinePrinter {
int CurrentIndent;
public:
+ class Line {
+ LinePrinter *P;
+
+ public:
+ Line(LinePrinter &P) : P(&P) { P.OS.indent(P.CurrentIndent); }
+ ~Line();
+
+ Line(Line &&RHS) : P(RHS.P) { RHS.P = nullptr; }
+ void operator=(Line &&) = delete;
+
+ operator llvm::raw_ostream &() { return P->OS; }
+ };
+
LinePrinter(int Indent, llvm::raw_ostream &Stream);
void Indent(uint32_t Amount = 0);
void Unindent(uint32_t Amount = 0);
void NewLine();
- void printLine(const llvm::Twine &T);
- void print(const llvm::Twine &T);
+ void printLine(const llvm::Twine &T) { line() << T; }
template <typename... Ts> void formatLine(const char *Fmt, Ts &&... Items) {
printLine(llvm::formatv(Fmt, std::forward<Ts>(Items)...));
}
- template <typename... Ts> void format(const char *Fmt, Ts &&... Items) {
- print(llvm::formatv(Fmt, std::forward<Ts>(Items)...));
- }
void formatBinary(llvm::StringRef Label, llvm::ArrayRef<uint8_t> Data,
uint32_t StartOffset);
void formatBinary(llvm::StringRef Label, llvm::ArrayRef<uint8_t> Data,
uint64_t BaseAddr, uint32_t StartOffset);
- llvm::raw_ostream &getStream() { return OS; }
+ Line line() { return Line(*this); }
int getIndentLevel() const { return CurrentIndent; }
};
@@ -64,12 +73,6 @@ struct AutoIndent {
uint32_t Amount = 0;
};
-template <class T>
-inline llvm::raw_ostream &operator<<(LinePrinter &Printer, const T &Item) {
- Printer.getStream() << Item;
- return Printer.getStream();
-}
-
} // namespace lldb_private
#endif
diff --git a/tools/lldb-test/SystemInitializerTest.cpp b/tools/lldb-test/SystemInitializerTest.cpp
index 2c190ecfc745..1220312def84 100644
--- a/tools/lldb-test/SystemInitializerTest.cpp
+++ b/tools/lldb-test/SystemInitializerTest.cpp
@@ -14,9 +14,6 @@
#include "lldb/Initialization/SystemInitializerCommon.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Symbol/GoASTContext.h"
-#include "lldb/Symbol/JavaASTContext.h"
-#include "lldb/Symbol/OCamlASTContext.h"
#include "lldb/Utility/Timer.h"
#include "Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h"
@@ -48,22 +45,17 @@
#include "Plugins/InstrumentationRuntime/UBSan/UBSanRuntime.h"
#include "Plugins/JITLoader/GDB/JITLoaderGDB.h"
#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
-#include "Plugins/Language/Go/GoLanguage.h"
-#include "Plugins/Language/Java/JavaLanguage.h"
-#include "Plugins/Language/OCaml/OCamlLanguage.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h"
#include "Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h"
-#include "Plugins/LanguageRuntime/Go/GoLanguageRuntime.h"
-#include "Plugins/LanguageRuntime/Java/JavaLanguageRuntime.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h"
#include "Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h"
#include "Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h"
#include "Plugins/MemoryHistory/asan/MemoryHistoryASan.h"
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/ObjectFile/Mach-O/ObjectFileMachO.h"
#include "Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h"
-#include "Plugins/OperatingSystem/Go/OperatingSystemGo.h"
#include "Plugins/Platform/Android/PlatformAndroid.h"
#include "Plugins/Platform/FreeBSD/PlatformFreeBSD.h"
#include "Plugins/Platform/Kalimba/PlatformKalimba.h"
@@ -78,6 +70,7 @@
#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
#include "Plugins/Process/minidump/ProcessMinidump.h"
#include "Plugins/ScriptInterpreter/None/ScriptInterpreterNone.h"
+#include "Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
@@ -120,16 +113,18 @@ SystemInitializerTest::SystemInitializerTest() {}
SystemInitializerTest::~SystemInitializerTest() {}
-void SystemInitializerTest::Initialize() {
- SystemInitializerCommon::Initialize();
+llvm::Error
+SystemInitializerTest::Initialize(const InitializerOptions &options) {
+ if (auto e = SystemInitializerCommon::Initialize(options))
+ return e;
+ breakpad::ObjectFileBreakpad::Initialize();
ObjectFileELF::Initialize();
ObjectFileMachO::Initialize();
ObjectFilePECOFF::Initialize();
ScriptInterpreterNone::Initialize();
- OperatingSystemGo::Initialize();
platform_freebsd::PlatformFreeBSD::Initialize();
platform_linux::PlatformLinux::Initialize();
@@ -152,9 +147,6 @@ void SystemInitializerTest::Initialize() {
llvm::InitializeAllDisassemblers();
ClangASTContext::Initialize();
- GoASTContext::Initialize();
- JavaASTContext::Initialize();
- OCamlASTContext::Initialize();
ABIMacOSX_i386::Initialize();
ABIMacOSX_arm::Initialize();
@@ -185,6 +177,7 @@ void SystemInitializerTest::Initialize() {
MainThreadCheckerRuntime::Initialize();
SymbolVendorELF::Initialize();
+ breakpad::SymbolFileBreakpad::Initialize();
SymbolFileDWARF::Initialize();
SymbolFilePDB::Initialize();
SymbolFileSymtab::Initialize();
@@ -198,15 +191,10 @@ void SystemInitializerTest::Initialize() {
AppleObjCRuntimeV1::Initialize();
SystemRuntimeMacOSX::Initialize();
RenderScriptRuntime::Initialize();
- GoLanguageRuntime::Initialize();
- JavaLanguageRuntime::Initialize();
CPlusPlusLanguage::Initialize();
- GoLanguage::Initialize();
- JavaLanguage::Initialize();
ObjCLanguage::Initialize();
ObjCPlusPlusLanguage::Initialize();
- OCamlLanguage::Initialize();
#if defined(_WIN32)
ProcessWindows::Initialize();
@@ -249,6 +237,8 @@ void SystemInitializerTest::Initialize() {
// AFTER PluginManager::Initialize is called.
Debugger::SettingsInitialize();
+
+ return llvm::Error::success();
}
void SystemInitializerTest::Terminate() {
@@ -261,9 +251,6 @@ void SystemInitializerTest::Terminate() {
PluginManager::Terminate();
ClangASTContext::Terminate();
- GoASTContext::Terminate();
- JavaASTContext::Terminate();
- OCamlASTContext::Terminate();
ABIMacOSX_i386::Terminate();
ABIMacOSX_arm::Terminate();
@@ -289,6 +276,7 @@ void SystemInitializerTest::Terminate() {
UndefinedBehaviorSanitizerRuntime::Terminate();
MainThreadCheckerRuntime::Terminate();
SymbolVendorELF::Terminate();
+ breakpad::SymbolFileBreakpad::Terminate();
SymbolFileDWARF::Terminate();
SymbolFilePDB::Terminate();
SymbolFileSymtab::Terminate();
@@ -302,14 +290,10 @@ void SystemInitializerTest::Terminate() {
AppleObjCRuntimeV1::Terminate();
SystemRuntimeMacOSX::Terminate();
RenderScriptRuntime::Terminate();
- JavaLanguageRuntime::Terminate();
CPlusPlusLanguage::Terminate();
- GoLanguage::Terminate();
- JavaLanguage::Terminate();
ObjCLanguage::Terminate();
ObjCPlusPlusLanguage::Terminate();
- OCamlLanguage::Terminate();
#if defined(__APPLE__)
DynamicLoaderDarwinKernel::Terminate();
@@ -337,7 +321,6 @@ void SystemInitializerTest::Terminate() {
DynamicLoaderStatic::Terminate();
DynamicLoaderWindowsDYLD::Terminate();
- OperatingSystemGo::Terminate();
platform_freebsd::PlatformFreeBSD::Terminate();
platform_linux::PlatformLinux::Terminate();
@@ -353,6 +336,7 @@ void SystemInitializerTest::Terminate() {
PlatformDarwinKernel::Terminate();
#endif
+ breakpad::ObjectFileBreakpad::Terminate();
ObjectFileELF::Terminate();
ObjectFileMachO::Terminate();
ObjectFilePECOFF::Terminate();
diff --git a/tools/lldb-test/SystemInitializerTest.h b/tools/lldb-test/SystemInitializerTest.h
index 887d6243765d..5950ff725ff0 100644
--- a/tools/lldb-test/SystemInitializerTest.h
+++ b/tools/lldb-test/SystemInitializerTest.h
@@ -26,7 +26,7 @@ public:
SystemInitializerTest();
~SystemInitializerTest() override;
- void Initialize() override;
+ llvm::Error Initialize(const InitializerOptions &options) override;
void Terminate() override;
};
diff --git a/tools/lldb-test/lldb-test.cpp b/tools/lldb-test/lldb-test.cpp
index c9225f63d303..f7bfc487c0ce 100644
--- a/tools/lldb-test/lldb-test.cpp
+++ b/tools/lldb-test/lldb-test.cpp
@@ -30,6 +30,7 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/ADT/IntervalMap.h"
@@ -90,19 +91,27 @@ namespace object {
cl::opt<bool> SectionContents("contents",
cl::desc("Dump each section's contents"),
cl::sub(ObjectFileSubcommand));
+cl::opt<bool> SectionDependentModules("dep-modules",
+ cl::desc("Dump each dependent module"),
+ cl::sub(ObjectFileSubcommand));
cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"),
cl::OneOrMore,
cl::sub(ObjectFileSubcommand));
} // namespace object
namespace symbols {
-static cl::list<std::string> InputFilenames(cl::Positional,
- cl::desc("<input files>"),
- cl::OneOrMore,
- cl::sub(SymbolsSubcommand));
+static cl::opt<std::string> InputFile(cl::Positional, cl::desc("<input file>"),
+ cl::Required, cl::sub(SymbolsSubcommand));
+
+static cl::opt<std::string>
+ SymbolPath("symbol-file",
+ cl::desc("The file from which to fetch symbol information."),
+ cl::value_desc("file"), cl::sub(SymbolsSubcommand));
+
enum class FindType {
None,
Function,
+ Block,
Namespace,
Type,
Variable,
@@ -112,6 +121,7 @@ static cl::opt<FindType> Find(
cl::values(
clEnumValN(FindType::None, "none", "No search, just dump the module."),
clEnumValN(FindType::Function, "function", "Find functions."),
+ clEnumValN(FindType::Block, "block", "Find blocks."),
clEnumValN(FindType::Namespace, "namespace", "Find namespaces."),
clEnumValN(FindType::Type, "type", "Find types."),
clEnumValN(FindType::Variable, "variable", "Find global variables.")),
@@ -146,6 +156,10 @@ static FunctionNameType getFunctionNameFlags() {
return Result;
}
+static cl::opt<bool> DumpAST("dump-ast",
+ cl::desc("Dump AST restored from symbols."),
+ cl::sub(SymbolsSubcommand));
+
static cl::opt<bool> Verify("verify", cl::desc("Verify symbol information."),
cl::sub(SymbolsSubcommand));
@@ -158,10 +172,12 @@ static cl::opt<int> Line("line", cl::desc("Line to search."),
static Expected<CompilerDeclContext> getDeclContext(SymbolVendor &Vendor);
static Error findFunctions(lldb_private::Module &Module);
+static Error findBlocks(lldb_private::Module &Module);
static Error findNamespaces(lldb_private::Module &Module);
static Error findTypes(lldb_private::Module &Module);
static Error findVariables(lldb_private::Module &Module);
static Error dumpModule(lldb_private::Module &Module);
+static Error dumpAST(lldb_private::Module &Module);
static Error verify(lldb_private::Module &Module);
static Expected<Error (*)(lldb_private::Module &)> getAction();
@@ -197,7 +213,6 @@ struct IRMemoryMapTestState {
: Target(Target), Map(Target), Allocations(IntervalMapAllocator) {}
};
-bool areAllocationsOverlapping(const AllocationT &L, const AllocationT &R);
bool evalMalloc(StringRef Line, IRMemoryMapTestState &State);
bool evalFree(StringRef Line, IRMemoryMapTestState &State);
int evaluateMemoryMapCommands(Debugger &Dbg);
@@ -214,10 +229,9 @@ static Error make_string_error(const char *Format, Args &&... args) {
TargetSP opts::createTarget(Debugger &Dbg, const std::string &Filename) {
TargetSP Target;
- Status ST =
- Dbg.GetTargetList().CreateTarget(Dbg, Filename, /*triple*/ "",
- /*get_dependent_modules*/ false,
- /*platform_options*/ nullptr, Target);
+ Status ST = Dbg.GetTargetList().CreateTarget(
+ Dbg, Filename, /*triple*/ "", eLoadDependentsNo,
+ /*platform_options*/ nullptr, Target);
if (ST.Fail()) {
errs() << formatv("Failed to create target '{0}: {1}\n", Filename, ST);
exit(1);
@@ -278,7 +292,7 @@ std::string opts::breakpoint::substitute(StringRef Cmd) {
OS << sys::path::parent_path(breakpoint::CommandFile);
break;
}
- // fall through
+ LLVM_FALLTHROUGH;
default:
size_t pos = Cmd.find('%');
OS << Cmd.substr(0, pos);
@@ -340,7 +354,7 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) {
if (!File.empty()) {
assert(Line != 0);
- FileSpec src_file(File, false);
+ FileSpec src_file(File);
size_t cu_count = Module.GetNumCompileUnits();
for (size_t i = 0; i < cu_count; i++) {
lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
@@ -383,6 +397,42 @@ Error opts::symbols::findFunctions(lldb_private::Module &Module) {
return Error::success();
}
+Error opts::symbols::findBlocks(lldb_private::Module &Module) {
+ assert(!Regex);
+ assert(!File.empty());
+ assert(Line != 0);
+
+ SymbolContextList List;
+
+ FileSpec src_file(File);
+ size_t cu_count = Module.GetNumCompileUnits();
+ for (size_t i = 0; i < cu_count; i++) {
+ lldb::CompUnitSP cu_sp = Module.GetCompileUnitAtIndex(i);
+ if (!cu_sp)
+ continue;
+
+ LineEntry le;
+ cu_sp->FindLineEntry(0, Line, &src_file, false, &le);
+ if (!le.IsValid())
+ continue;
+
+ auto addr = le.GetSameLineContiguousAddressRange().GetBaseAddress();
+ if (!addr.IsValid())
+ continue;
+
+ SymbolContext sc;
+ uint32_t resolved = addr.CalculateSymbolContext(&sc, eSymbolContextBlock);
+ if (resolved & eSymbolContextBlock)
+ List.Append(sc);
+ }
+
+ outs() << formatv("Found {0} blocks:\n", List.GetSize());
+ StreamString Stream;
+ List.Dump(&Stream, nullptr);
+ outs() << Stream.GetData() << "\n";
+ return Error::success();
+}
+
Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
SymbolVendor &Vendor = *Module.GetSymbolVendor();
Expected<CompilerDeclContext> ContextOr = getDeclContext(Vendor);
@@ -391,9 +441,8 @@ Error opts::symbols::findNamespaces(lldb_private::Module &Module) {
CompilerDeclContext *ContextPtr =
ContextOr->IsValid() ? &*ContextOr : nullptr;
- SymbolContext SC;
CompilerDeclContext Result =
- Vendor.FindNamespace(SC, ConstString(Name), ContextPtr);
+ Vendor.FindNamespace(ConstString(Name), ContextPtr);
if (Result)
outs() << "Found namespace: "
<< Result.GetScopeQualifiedName().GetStringRef() << "\n";
@@ -410,10 +459,9 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) {
CompilerDeclContext *ContextPtr =
ContextOr->IsValid() ? &*ContextOr : nullptr;
- SymbolContext SC;
DenseSet<SymbolFile *> SearchedFiles;
TypeMap Map;
- Vendor.FindTypes(SC, ConstString(Name), ContextPtr, true, UINT32_MAX,
+ Vendor.FindTypes(ConstString(Name), ContextPtr, true, UINT32_MAX,
SearchedFiles, Map);
outs() << formatv("Found {0} types:\n", Map.GetSize());
@@ -470,6 +518,32 @@ Error opts::symbols::dumpModule(lldb_private::Module &Module) {
return Error::success();
}
+Error opts::symbols::dumpAST(lldb_private::Module &Module) {
+ SymbolVendor &plugin = *Module.GetSymbolVendor();
+ Module.ParseAllDebugSymbols();
+
+ auto symfile = plugin.GetSymbolFile();
+ if (!symfile)
+ return make_string_error("Module has no symbol file.");
+
+ auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ symfile->GetTypeSystemForLanguage(eLanguageTypeC_plus_plus));
+ if (!clang_ast_ctx)
+ return make_string_error("Can't retrieve Clang AST context.");
+
+ auto ast_ctx = clang_ast_ctx->getASTContext();
+ if (!ast_ctx)
+ return make_string_error("Can't retrieve AST context.");
+
+ auto tu = ast_ctx->getTranslationUnitDecl();
+ if (!tu)
+ return make_string_error("Can't retrieve translation unit declaration.");
+
+ tu->print(outs());
+
+ return Error::success();
+}
+
Error opts::symbols::verify(lldb_private::Module &Module) {
SymbolVendor &plugin = *Module.GetSymbolVendor();
@@ -523,6 +597,10 @@ Error opts::symbols::verify(lldb_private::Module &Module) {
}
Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
+ if (Verify && DumpAST)
+ return make_string_error(
+ "Cannot both verify symbol information and dump AST.");
+
if (Verify) {
if (Find != FindType::None)
return make_string_error(
@@ -535,6 +613,17 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
return verify;
}
+ if (DumpAST) {
+ if (Find != FindType::None)
+ return make_string_error("Cannot both search and dump AST.");
+ if (Regex || !Context.empty() || !Name.empty() || !File.empty() ||
+ Line != 0)
+ return make_string_error(
+ "-regex, -context, -name, -file and -line options are not "
+ "applicable for dumping AST.");
+ return dumpAST;
+ }
+
if (Regex && !Context.empty())
return make_string_error(
"Cannot search using both regular expressions and context.");
@@ -566,6 +655,15 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
"when searching a function.");
return findFunctions;
+ case FindType::Block:
+ if (File.empty() || Line == 0)
+ return make_string_error("Both file name and line number must be "
+ "specified when searching a block.");
+ if (Regex || getFunctionNameFlags() != 0)
+ return make_string_error("Cannot use regular expression or "
+ "function-flags for searching a block.");
+ return findBlocks;
+
case FindType::Namespace:
if (Regex || !File.empty() || Line != 0)
return make_string_error("Cannot search for namespaces using regular "
@@ -584,6 +682,8 @@ Expected<Error (*)(lldb_private::Module &)> opts::symbols::getAction() {
"using line numbers.");
return findVariables;
}
+
+ llvm_unreachable("Unsupported symbol action.");
}
int opts::symbols::dumpSymbols(Debugger &Dbg) {
@@ -594,28 +694,59 @@ int opts::symbols::dumpSymbols(Debugger &Dbg) {
}
auto Action = *ActionOr;
- int HadErrors = 0;
- for (const auto &File : InputFilenames) {
- outs() << "Module: " << File << "\n";
- ModuleSpec Spec{FileSpec(File, false)};
- Spec.GetSymbolFileSpec().SetFile(File, false, FileSpec::Style::native);
+ outs() << "Module: " << InputFile << "\n";
+ ModuleSpec Spec{FileSpec(InputFile)};
+ StringRef Symbols = SymbolPath.empty() ? InputFile : SymbolPath;
+ Spec.GetSymbolFileSpec().SetFile(Symbols, FileSpec::Style::native);
- auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
- SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
- if (!Vendor) {
- WithColor::error() << "Module has no symbol vendor.\n";
- HadErrors = 1;
- continue;
- }
+ auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
+ SymbolVendor *Vendor = ModulePtr->GetSymbolVendor();
+ if (!Vendor) {
+ WithColor::error() << "Module has no symbol vendor.\n";
+ return 1;
+ }
- if (Error E = Action(*ModulePtr)) {
- WithColor::error() << toString(std::move(E)) << "\n";
- HadErrors = 1;
+ if (Error E = Action(*ModulePtr)) {
+ WithColor::error() << toString(std::move(E)) << "\n";
+ return 1;
+ }
+
+ return 0;
+}
+
+static void dumpSectionList(LinePrinter &Printer, const SectionList &List, bool is_subsection) {
+ size_t Count = List.GetNumSections(0);
+ if (Count == 0) {
+ Printer.formatLine("There are no {0}sections", is_subsection ? "sub" : "");
+ return;
+ }
+ Printer.formatLine("Showing {0} {1}sections", Count,
+ is_subsection ? "sub" : "");
+ for (size_t I = 0; I < Count; ++I) {
+ auto S = List.GetSectionAtIndex(I);
+ assert(S);
+ AutoIndent Indent(Printer, 2);
+ Printer.formatLine("Index: {0}", I);
+ Printer.formatLine("ID: {0:x}", S->GetID());
+ Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
+ Printer.formatLine("Type: {0}", S->GetTypeAsCString());
+ Printer.formatLine("Permissions: {0}", GetPermissionsAsCString(S->GetPermissions()));
+ Printer.formatLine("Thread specific: {0:y}", S->IsThreadSpecific());
+ Printer.formatLine("VM address: {0:x}", S->GetFileAddress());
+ Printer.formatLine("VM size: {0}", S->GetByteSize());
+ Printer.formatLine("File size: {0}", S->GetFileSize());
+
+ if (opts::object::SectionContents) {
+ DataExtractor Data;
+ S->GetSectionData(Data);
+ ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
+ Printer.formatBinary("Data: ", Bytes, 0);
}
- outs().flush();
+ if (S->GetType() == eSectionTypeContainer)
+ dumpSectionList(Printer, S->GetChildren(), true);
+ Printer.NewLine();
}
- return HadErrors;
}
static int dumpObjectFiles(Debugger &Dbg) {
@@ -623,9 +754,17 @@ static int dumpObjectFiles(Debugger &Dbg) {
int HadErrors = 0;
for (const auto &File : opts::object::InputFilenames) {
- ModuleSpec Spec{FileSpec(File, false)};
+ ModuleSpec Spec{FileSpec(File)};
auto ModulePtr = std::make_shared<lldb_private::Module>(Spec);
+
+ ObjectFile *ObjectPtr = ModulePtr->GetObjectFile();
+ if (!ObjectPtr) {
+ WithColor::error() << File << " not recognised as an object file\n";
+ HadErrors = 1;
+ continue;
+ }
+
// Fetch symbol vendor before we get the section list to give the symbol
// vendor a chance to populate it.
ModulePtr->GetSymbolVendor();
@@ -636,27 +775,29 @@ static int dumpObjectFiles(Debugger &Dbg) {
continue;
}
+ Printer.formatLine("Plugin name: {0}", ObjectPtr->GetPluginName());
Printer.formatLine("Architecture: {0}",
ModulePtr->GetArchitecture().GetTriple().getTriple());
Printer.formatLine("UUID: {0}", ModulePtr->GetUUID().GetAsString());
-
- size_t Count = Sections->GetNumSections(0);
- Printer.formatLine("Showing {0} sections", Count);
- for (size_t I = 0; I < Count; ++I) {
- AutoIndent Indent(Printer, 2);
- auto S = Sections->GetSectionAtIndex(I);
- assert(S);
- Printer.formatLine("Index: {0}", I);
- Printer.formatLine("Name: {0}", S->GetName().GetStringRef());
- Printer.formatLine("Type: {0}", S->GetTypeAsCString());
- Printer.formatLine("VM size: {0}", S->GetByteSize());
- Printer.formatLine("File size: {0}", S->GetFileSize());
-
- if (opts::object::SectionContents) {
- DataExtractor Data;
- S->GetSectionData(Data);
- ArrayRef<uint8_t> Bytes = {Data.GetDataStart(), Data.GetDataEnd()};
- Printer.formatBinary("Data: ", Bytes, 0);
+ Printer.formatLine("Executable: {0}", ObjectPtr->IsExecutable());
+ Printer.formatLine("Stripped: {0}", ObjectPtr->IsStripped());
+ Printer.formatLine("Type: {0}", ObjectPtr->GetType());
+ Printer.formatLine("Strata: {0}", ObjectPtr->GetStrata());
+ Printer.formatLine("Base VM address: {0:x}",
+ ObjectPtr->GetBaseAddress().GetFileAddress());
+
+ dumpSectionList(Printer, *Sections, /*is_subsection*/ false);
+
+ if (opts::object::SectionDependentModules) {
+ // A non-empty section list ensures a valid object file.
+ auto Obj = ModulePtr->GetObjectFile();
+ FileSpecList Files;
+ auto Count = Obj->GetDependentModules(Files);
+ Printer.formatLine("Showing {0} dependent module(s)", Count);
+ for (size_t I = 0; I < Files.GetSize(); ++I) {
+ AutoIndent Indent(Printer, 2);
+ Printer.formatLine("Name: {0}",
+ Files.GetFileSpecAtIndex(I).GetCString());
}
Printer.NewLine();
}
@@ -664,13 +805,6 @@ static int dumpObjectFiles(Debugger &Dbg) {
return HadErrors;
}
-/// Check if two half-open intervals intersect:
-/// http://world.std.com/~swmcd/steven/tech/interval.html
-bool opts::irmemorymap::areAllocationsOverlapping(const AllocationT &L,
- const AllocationT &R) {
- return R.first < L.second && L.first < R.second;
-}
-
bool opts::irmemorymap::evalMalloc(StringRef Line,
IRMemoryMapTestState &State) {
// ::= <label> = malloc <size> <alignment>
@@ -717,28 +851,21 @@ bool opts::irmemorymap::evalMalloc(StringRef Line,
exit(1);
}
- // Check that the allocation does not overlap another allocation. Do so by
- // testing each allocation which may cover the interval [Addr, EndOfRegion).
- addr_t EndOfRegion = Addr + Size;
- auto Probe = State.Allocations.begin();
- Probe.advanceTo(Addr); //< First interval s.t stop >= Addr.
- AllocationT NewAllocation = {Addr, EndOfRegion};
- while (Probe != State.Allocations.end() && Probe.start() < EndOfRegion) {
- AllocationT ProbeAllocation = {Probe.start(), Probe.stop()};
- if (areAllocationsOverlapping(ProbeAllocation, NewAllocation)) {
- outs() << "Malloc error: overlapping allocation detected"
- << formatv(", previous allocation at [{0:x}, {1:x})\n",
- Probe.start(), Probe.stop());
- exit(1);
- }
- ++Probe;
+ // In case of Size == 0, we still expect the returned address to be unique and
+ // non-overlapping.
+ addr_t EndOfRegion = Addr + std::max<size_t>(Size, 1);
+ if (State.Allocations.overlaps(Addr, EndOfRegion)) {
+ auto I = State.Allocations.find(Addr);
+ outs() << "Malloc error: overlapping allocation detected"
+ << formatv(", previous allocation at [{0:x}, {1:x})\n", I.start(),
+ I.stop());
+ exit(1);
}
- // Insert the new allocation into the interval map. Use unique allocation IDs
- // to inhibit interval coalescing.
+ // Insert the new allocation into the interval map. Use unique allocation
+ // IDs to inhibit interval coalescing.
static unsigned AllocationID = 0;
- if (Size)
- State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
+ State.Allocations.insert(Addr, EndOfRegion, AllocationID++);
// Store the label -> address mapping.
State.Label2AddrMap[Label] = Addr;
@@ -836,8 +963,13 @@ int main(int argc, const char *argv[]) {
cl::ParseCommandLineOptions(argc, argv, "LLDB Testing Utility\n");
SystemLifetimeManager DebuggerLifetime;
- DebuggerLifetime.Initialize(llvm::make_unique<SystemInitializerTest>(),
- nullptr);
+ if (auto e = DebuggerLifetime.Initialize(
+ llvm::make_unique<SystemInitializerTest>(), {}, nullptr)) {
+ WithColor::error() << "initialization failed: " << toString(std::move(e))
+ << '\n';
+ return 1;
+ }
+
CleanUp TerminateDebugger([&] { DebuggerLifetime.Terminate(); });
auto Dbg = lldb_private::Debugger::CreateInstance();
diff --git a/tools/lldb-vscode/BreakpointBase.cpp b/tools/lldb-vscode/BreakpointBase.cpp
new file mode 100644
index 000000000000..adb7abd1a3a1
--- /dev/null
+++ b/tools/lldb-vscode/BreakpointBase.cpp
@@ -0,0 +1,37 @@
+//===-- BreakpointBase.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BreakpointBase.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace lldb_vscode;
+
+BreakpointBase::BreakpointBase(const llvm::json::Object &obj)
+ : condition(GetString(obj, "condition")),
+ hitCondition(GetString(obj, "hitCondition")),
+ logMessage(GetString(obj, "logMessage")) {}
+
+void BreakpointBase::SetCondition() { bp.SetCondition(condition.c_str()); }
+
+void BreakpointBase::SetHitCondition() {
+ uint64_t hitCount = 0;
+ if (llvm::to_integer(hitCondition, hitCount))
+ bp.SetIgnoreCount(hitCount - 1);
+}
+
+void BreakpointBase::UpdateBreakpoint(const BreakpointBase &request_bp) {
+ if (condition != request_bp.condition) {
+ condition = request_bp.condition;
+ SetCondition();
+ }
+ if (hitCondition != request_bp.hitCondition) {
+ hitCondition = request_bp.hitCondition;
+ SetHitCondition();
+ }
+}
diff --git a/tools/lldb-vscode/BreakpointBase.h b/tools/lldb-vscode/BreakpointBase.h
new file mode 100644
index 000000000000..e27ffe3bd390
--- /dev/null
+++ b/tools/lldb-vscode/BreakpointBase.h
@@ -0,0 +1,44 @@
+//===-- BreakpointBase.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_BREAKPOINTBASE_H_
+#define LLDBVSCODE_BREAKPOINTBASE_H_
+
+#include "JSONUtils.h"
+#include "lldb/API/SBBreakpoint.h"
+#include "llvm/Support/JSON.h"
+#include <string>
+
+namespace lldb_vscode {
+
+struct BreakpointBase {
+
+ // An optional expression for conditional breakpoints.
+ std::string condition;
+ // An optional expression that controls how many hits of the breakpoint are
+ // ignored. The backend is expected to interpret the expression as needed
+ std::string hitCondition;
+ // If this attribute exists and is non-empty, the backend must not 'break'
+ // (stop) but log the message instead. Expressions within {} are
+ // interpolated.
+ std::string logMessage;
+ // The LLDB breakpoint associated wit this source breakpoint
+ lldb::SBBreakpoint bp;
+
+ BreakpointBase() = default;
+ BreakpointBase(const llvm::json::Object &obj);
+
+ void SetCondition();
+ void SetHitCondition();
+ void UpdateBreakpoint(const BreakpointBase &request_bp);
+};
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/CMakeLists.txt b/tools/lldb-vscode/CMakeLists.txt
new file mode 100644
index 000000000000..08511248d335
--- /dev/null
+++ b/tools/lldb-vscode/CMakeLists.txt
@@ -0,0 +1,34 @@
+if ( CMAKE_SYSTEM_NAME MATCHES "Windows" OR CMAKE_SYSTEM_NAME MATCHES "NetBSD" )
+ add_definitions( -DIMPORT_LIBLLDB )
+ list(APPEND extra_libs lldbHost)
+endif ()
+
+if (HAVE_LIBPTHREAD)
+ list(APPEND extra_libs pthread)
+endif ()
+
+# We need to include the llvm components we depend on manually, as liblldb does
+# not re-export those.
+set(LLVM_LINK_COMPONENTS Support)
+add_lldb_tool(lldb-vscode
+ lldb-vscode.cpp
+ BreakpointBase.cpp
+ ExceptionBreakpoint.cpp
+ FunctionBreakpoint.cpp
+ JSONUtils.cpp
+ LLDBUtils.cpp
+ SourceBreakpoint.cpp
+ VSCode.cpp
+
+ LINK_LIBS
+ liblldb
+ ${host_lib}
+ ${extra_libs}
+
+ LINK_COMPONENTS
+ Support
+ )
+
+if(LLDB_BUILD_FRAMEWORK)
+ lldb_setup_framework_rpaths_in_tool(lldb-vscode)
+endif()
diff --git a/tools/lldb-vscode/ExceptionBreakpoint.cpp b/tools/lldb-vscode/ExceptionBreakpoint.cpp
new file mode 100644
index 000000000000..96bc0930e429
--- /dev/null
+++ b/tools/lldb-vscode/ExceptionBreakpoint.cpp
@@ -0,0 +1,32 @@
+//===-- ExceptionBreakpoint.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ExceptionBreakpoint.h"
+#include "VSCode.h"
+
+namespace lldb_vscode {
+
+void ExceptionBreakpoint::SetBreakpoint() {
+ if (bp.IsValid())
+ return;
+ bool catch_value = filter.find("_catch") != std::string::npos;
+ bool throw_value = filter.find("_throw") != std::string::npos;
+ bp = g_vsc.target.BreakpointCreateForException(language, catch_value,
+ throw_value);
+}
+
+void ExceptionBreakpoint::ClearBreakpoint() {
+ if (!bp.IsValid())
+ return;
+ g_vsc.target.BreakpointDelete(bp.GetID());
+ bp = lldb::SBBreakpoint();
+}
+
+} // namespace lldb_vscode
+
diff --git a/tools/lldb-vscode/ExceptionBreakpoint.h b/tools/lldb-vscode/ExceptionBreakpoint.h
new file mode 100644
index 000000000000..f3e1e7068095
--- /dev/null
+++ b/tools/lldb-vscode/ExceptionBreakpoint.h
@@ -0,0 +1,38 @@
+//===-- ExceptionBreakpoint.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_EXCEPTIONBREAKPOINT_H_
+#define LLDBVSCODE_EXCEPTIONBREAKPOINT_H_
+
+#include <string>
+
+#include "lldb/API/SBBreakpoint.h"
+
+namespace lldb_vscode {
+
+struct ExceptionBreakpoint {
+ std::string filter;
+ std::string label;
+ lldb::LanguageType language;
+ bool default_value;
+ lldb::SBBreakpoint bp;
+ ExceptionBreakpoint(std::string f, std::string l, lldb::LanguageType lang) :
+ filter(std::move(f)),
+ label(std::move(l)),
+ language(lang),
+ default_value(false),
+ bp() {}
+
+ void SetBreakpoint();
+ void ClearBreakpoint();
+};
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/FunctionBreakpoint.cpp b/tools/lldb-vscode/FunctionBreakpoint.cpp
new file mode 100644
index 000000000000..f83333dc9895
--- /dev/null
+++ b/tools/lldb-vscode/FunctionBreakpoint.cpp
@@ -0,0 +1,28 @@
+//===-- FunctionBreakpoint.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "FunctionBreakpoint.h"
+#include "VSCode.h"
+
+namespace lldb_vscode {
+
+FunctionBreakpoint::FunctionBreakpoint(const llvm::json::Object &obj)
+ : BreakpointBase(obj), functionName(GetString(obj, "name")) {}
+
+void FunctionBreakpoint::SetBreakpoint() {
+ if (functionName.empty())
+ return;
+ bp = g_vsc.target.BreakpointCreateByName(functionName.c_str());
+ if (!condition.empty())
+ SetCondition();
+ if (!hitCondition.empty())
+ SetHitCondition();
+}
+
+}
diff --git a/tools/lldb-vscode/FunctionBreakpoint.h b/tools/lldb-vscode/FunctionBreakpoint.h
new file mode 100644
index 000000000000..ff4f34dba077
--- /dev/null
+++ b/tools/lldb-vscode/FunctionBreakpoint.h
@@ -0,0 +1,29 @@
+//===-- FunctionBreakpoint.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_FUNCTIONBREAKPOINT_H_
+#define LLDBVSCODE_FUNCTIONBREAKPOINT_H_
+
+#include "BreakpointBase.h"
+
+namespace lldb_vscode {
+
+struct FunctionBreakpoint : public BreakpointBase {
+ std::string functionName;
+
+ FunctionBreakpoint() = default;
+ FunctionBreakpoint(const llvm::json::Object &obj);
+
+ // Set this breakpoint in LLDB as a new breakpoint
+ void SetBreakpoint();
+};
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/JSONUtils.cpp b/tools/lldb-vscode/JSONUtils.cpp
new file mode 100644
index 000000000000..76cd44cc72d1
--- /dev/null
+++ b/tools/lldb-vscode/JSONUtils.cpp
@@ -0,0 +1,892 @@
+//===-- JSONUtils.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <algorithm>
+
+#include "llvm/Support/FormatAdapters.h"
+
+#include "lldb/API/SBBreakpoint.h"
+#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBValue.h"
+#include "lldb/Host/PosixApi.h"
+
+#include "ExceptionBreakpoint.h"
+#include "JSONUtils.h"
+#include "LLDBUtils.h"
+#include "VSCode.h"
+
+namespace lldb_vscode {
+
+void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
+ llvm::StringRef str) {
+ if (LLVM_LIKELY(llvm::json::isUTF8(str)))
+ obj.try_emplace(key, str.str());
+ else
+ obj.try_emplace(key, llvm::json::fixUTF8(str));
+}
+
+llvm::StringRef GetAsString(const llvm::json::Value &value) {
+ if (auto s = value.getAsString())
+ return *s;
+ return llvm::StringRef();
+}
+
+// Gets a string from a JSON object using the key, or returns an empty string.
+llvm::StringRef GetString(const llvm::json::Object &obj, llvm::StringRef key) {
+ if (auto value = obj.getString(key))
+ return GetAsString(*value);
+ return llvm::StringRef();
+}
+
+llvm::StringRef GetString(const llvm::json::Object *obj, llvm::StringRef key) {
+ if (obj == nullptr)
+ return llvm::StringRef();
+ return GetString(*obj, key);
+}
+
+// Gets an unsigned integer from a JSON object using the key, or returns the
+// specified fail value.
+uint64_t GetUnsigned(const llvm::json::Object &obj, llvm::StringRef key,
+ uint64_t fail_value) {
+ if (auto value = obj.getInteger(key))
+ return (uint64_t)*value;
+ return fail_value;
+}
+
+uint64_t GetUnsigned(const llvm::json::Object *obj, llvm::StringRef key,
+ uint64_t fail_value) {
+ if (obj == nullptr)
+ return fail_value;
+ return GetUnsigned(*obj, key, fail_value);
+}
+
+bool GetBoolean(const llvm::json::Object &obj, llvm::StringRef key,
+ bool fail_value) {
+ if (auto value = obj.getBoolean(key))
+ return *value;
+ if (auto value = obj.getInteger(key))
+ return *value != 0;
+ return fail_value;
+}
+
+bool GetBoolean(const llvm::json::Object *obj, llvm::StringRef key,
+ bool fail_value) {
+ if (obj == nullptr)
+ return fail_value;
+ return GetBoolean(*obj, key, fail_value);
+}
+
+int64_t GetSigned(const llvm::json::Object &obj, llvm::StringRef key,
+ int64_t fail_value) {
+ if (auto value = obj.getInteger(key))
+ return *value;
+ return fail_value;
+}
+
+int64_t GetSigned(const llvm::json::Object *obj, llvm::StringRef key,
+ int64_t fail_value) {
+ if (obj == nullptr)
+ return fail_value;
+ return GetSigned(*obj, key, fail_value);
+}
+
+bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key) {
+ return obj.find(key) != obj.end();
+}
+
+std::vector<std::string> GetStrings(const llvm::json::Object *obj,
+ llvm::StringRef key) {
+ std::vector<std::string> strs;
+ auto json_array = obj->getArray(key);
+ if (!json_array)
+ return strs;
+ for (const auto &value : *json_array) {
+ switch (value.kind()) {
+ case llvm::json::Value::String:
+ strs.push_back(value.getAsString()->str());
+ break;
+ case llvm::json::Value::Number:
+ case llvm::json::Value::Boolean: {
+ std::string s;
+ llvm::raw_string_ostream strm(s);
+ strm << value;
+ strs.push_back(strm.str());
+ break;
+ }
+ case llvm::json::Value::Null:
+ case llvm::json::Value::Object:
+ case llvm::json::Value::Array:
+ break;
+ }
+ }
+ return strs;
+}
+
+void SetValueForKey(lldb::SBValue &v, llvm::json::Object &object,
+ llvm::StringRef key) {
+
+ llvm::StringRef value = v.GetValue();
+ llvm::StringRef summary = v.GetSummary();
+ llvm::StringRef type_name = v.GetType().GetDisplayTypeName();
+
+ std::string result;
+ llvm::raw_string_ostream strm(result);
+ if (!value.empty()) {
+ strm << value;
+ if (!summary.empty())
+ strm << ' ' << summary;
+ } else if (!summary.empty()) {
+ strm << ' ' << summary;
+ } else if (!type_name.empty()) {
+ strm << type_name;
+ lldb::addr_t address = v.GetLoadAddress();
+ if (address != LLDB_INVALID_ADDRESS)
+ strm << " @ " << llvm::format_hex(address, 0);
+ }
+ strm.flush();
+ EmplaceSafeString(object, key, result);
+}
+
+void FillResponse(const llvm::json::Object &request,
+ llvm::json::Object &response) {
+ // Fill in all of the needed response fields to a "request" and set "success"
+ // to true by default.
+ response.try_emplace("type", "response");
+ response.try_emplace("seq", (int64_t)0);
+ EmplaceSafeString(response, "command", GetString(request, "command"));
+ const int64_t seq = GetSigned(request, "seq", 0);
+ response.try_emplace("request_seq", seq);
+ response.try_emplace("success", true);
+}
+
+//----------------------------------------------------------------------
+// "Scope": {
+// "type": "object",
+// "description": "A Scope is a named container for variables. Optionally
+// a scope can map to a source or a range within a source.",
+// "properties": {
+// "name": {
+// "type": "string",
+// "description": "Name of the scope such as 'Arguments', 'Locals'."
+// },
+// "variablesReference": {
+// "type": "integer",
+// "description": "The variables of this scope can be retrieved by
+// passing the value of variablesReference to the
+// VariablesRequest."
+// },
+// "namedVariables": {
+// "type": "integer",
+// "description": "The number of named variables in this scope. The
+// client can use this optional information to present
+// the variables in a paged UI and fetch them in chunks."
+// },
+// "indexedVariables": {
+// "type": "integer",
+// "description": "The number of indexed variables in this scope. The
+// client can use this optional information to present
+// the variables in a paged UI and fetch them in chunks."
+// },
+// "expensive": {
+// "type": "boolean",
+// "description": "If true, the number of variables in this scope is
+// large or expensive to retrieve."
+// },
+// "source": {
+// "$ref": "#/definitions/Source",
+// "description": "Optional source for this scope."
+// },
+// "line": {
+// "type": "integer",
+// "description": "Optional start line of the range covered by this
+// scope."
+// },
+// "column": {
+// "type": "integer",
+// "description": "Optional start column of the range covered by this
+// scope."
+// },
+// "endLine": {
+// "type": "integer",
+// "description": "Optional end line of the range covered by this scope."
+// },
+// "endColumn": {
+// "type": "integer",
+// "description": "Optional end column of the range covered by this
+// scope."
+// }
+// },
+// "required": [ "name", "variablesReference", "expensive" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateScope(const llvm::StringRef name,
+ int64_t variablesReference,
+ int64_t namedVariables, bool expensive) {
+ llvm::json::Object object;
+ EmplaceSafeString(object, "name", name.str());
+ object.try_emplace("variablesReference", variablesReference);
+ object.try_emplace("expensive", expensive);
+ object.try_emplace("namedVariables", namedVariables);
+ return llvm::json::Value(std::move(object));
+}
+
+//----------------------------------------------------------------------
+// "Breakpoint": {
+// "type": "object",
+// "description": "Information about a Breakpoint created in setBreakpoints
+// or setFunctionBreakpoints.",
+// "properties": {
+// "id": {
+// "type": "integer",
+// "description": "An optional unique identifier for the breakpoint."
+// },
+// "verified": {
+// "type": "boolean",
+// "description": "If true breakpoint could be set (but not necessarily
+// at the desired location)."
+// },
+// "message": {
+// "type": "string",
+// "description": "An optional message about the state of the breakpoint.
+// This is shown to the user and can be used to explain
+// why a breakpoint could not be verified."
+// },
+// "source": {
+// "$ref": "#/definitions/Source",
+// "description": "The source where the breakpoint is located."
+// },
+// "line": {
+// "type": "integer",
+// "description": "The start line of the actual range covered by the
+// breakpoint."
+// },
+// "column": {
+// "type": "integer",
+// "description": "An optional start column of the actual range covered
+// by the breakpoint."
+// },
+// "endLine": {
+// "type": "integer",
+// "description": "An optional end line of the actual range covered by
+// the breakpoint."
+// },
+// "endColumn": {
+// "type": "integer",
+// "description": "An optional end column of the actual range covered by
+// the breakpoint. If no end line is given, then the end
+// column is assumed to be in the start line."
+// }
+// },
+// "required": [ "verified" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateBreakpoint(lldb::SBBreakpointLocation &bp_loc) {
+ // Each breakpoint location is treated as a separate breakpoint for VS code.
+ // They don't have the notion of a single breakpoint with multiple locations.
+ llvm::json::Object object;
+ if (!bp_loc.IsValid())
+ return llvm::json::Value(std::move(object));
+
+ object.try_emplace("verified", true);
+ const auto vs_id = MakeVSCodeBreakpointID(bp_loc);
+ object.try_emplace("id", vs_id);
+ auto bp_addr = bp_loc.GetAddress();
+ if (bp_addr.IsValid()) {
+ auto line_entry = bp_addr.GetLineEntry();
+ const auto line = line_entry.GetLine();
+ if (line != UINT32_MAX)
+ object.try_emplace("line", line);
+ object.try_emplace("source", CreateSource(line_entry));
+ }
+ return llvm::json::Value(std::move(object));
+}
+
+void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints) {
+ if (!bp.IsValid())
+ return;
+ const auto num_locations = bp.GetNumLocations();
+ if (num_locations == 0)
+ return;
+ for (size_t i = 0; i < num_locations; ++i) {
+ auto bp_loc = bp.GetLocationAtIndex(i);
+ breakpoints.emplace_back(CreateBreakpoint(bp_loc));
+ }
+}
+
+//----------------------------------------------------------------------
+// "Event": {
+// "allOf": [ { "$ref": "#/definitions/ProtocolMessage" }, {
+// "type": "object",
+// "description": "Server-initiated event.",
+// "properties": {
+// "type": {
+// "type": "string",
+// "enum": [ "event" ]
+// },
+// "event": {
+// "type": "string",
+// "description": "Type of event."
+// },
+// "body": {
+// "type": [ "array", "boolean", "integer", "null", "number" ,
+// "object", "string" ],
+// "description": "Event-specific information."
+// }
+// },
+// "required": [ "type", "event" ]
+// }]
+// },
+// "ProtocolMessage": {
+// "type": "object",
+// "description": "Base class of requests, responses, and events.",
+// "properties": {
+// "seq": {
+// "type": "integer",
+// "description": "Sequence number."
+// },
+// "type": {
+// "type": "string",
+// "description": "Message type.",
+// "_enum": [ "request", "response", "event" ]
+// }
+// },
+// "required": [ "seq", "type" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Object CreateEventObject(const llvm::StringRef event_name) {
+ llvm::json::Object event;
+ event.try_emplace("seq", 0);
+ event.try_emplace("type", "event");
+ EmplaceSafeString(event, "event", event_name);
+ return event;
+}
+
+//----------------------------------------------------------------------
+// "ExceptionBreakpointsFilter": {
+// "type": "object",
+// "description": "An ExceptionBreakpointsFilter is shown in the UI as an
+// option for configuring how exceptions are dealt with.",
+// "properties": {
+// "filter": {
+// "type": "string",
+// "description": "The internal ID of the filter. This value is passed
+// to the setExceptionBreakpoints request."
+// },
+// "label": {
+// "type": "string",
+// "description": "The name of the filter. This will be shown in the UI."
+// },
+// "default": {
+// "type": "boolean",
+// "description": "Initial value of the filter. If not specified a value
+// 'false' is assumed."
+// }
+// },
+// "required": [ "filter", "label" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value
+CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp) {
+ llvm::json::Object object;
+ EmplaceSafeString(object, "filter", bp.filter);
+ EmplaceSafeString(object, "label", bp.label);
+ object.try_emplace("default", bp.default_value);
+ return llvm::json::Value(std::move(object));
+}
+
+//----------------------------------------------------------------------
+// "Source": {
+// "type": "object",
+// "description": "A Source is a descriptor for source code. It is returned
+// from the debug adapter as part of a StackFrame and it is
+// used by clients when specifying breakpoints.",
+// "properties": {
+// "name": {
+// "type": "string",
+// "description": "The short name of the source. Every source returned
+// from the debug adapter has a name. When sending a
+// source to the debug adapter this name is optional."
+// },
+// "path": {
+// "type": "string",
+// "description": "The path of the source to be shown in the UI. It is
+// only used to locate and load the content of the
+// source if no sourceReference is specified (or its
+// value is 0)."
+// },
+// "sourceReference": {
+// "type": "number",
+// "description": "If sourceReference > 0 the contents of the source must
+// be retrieved through the SourceRequest (even if a path
+// is specified). A sourceReference is only valid for a
+// session, so it must not be used to persist a source."
+// },
+// "presentationHint": {
+// "type": "string",
+// "description": "An optional hint for how to present the source in the
+// UI. A value of 'deemphasize' can be used to indicate
+// that the source is not available or that it is
+// skipped on stepping.",
+// "enum": [ "normal", "emphasize", "deemphasize" ]
+// },
+// "origin": {
+// "type": "string",
+// "description": "The (optional) origin of this source: possible values
+// 'internal module', 'inlined content from source map',
+// etc."
+// },
+// "sources": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Source"
+// },
+// "description": "An optional list of sources that are related to this
+// source. These may be the source that generated this
+// source."
+// },
+// "adapterData": {
+// "type":["array","boolean","integer","null","number","object","string"],
+// "description": "Optional data that a debug adapter might want to loop
+// through the client. The client should leave the data
+// intact and persist it across sessions. The client
+// should not interpret the data."
+// },
+// "checksums": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Checksum"
+// },
+// "description": "The checksums associated with this file."
+// }
+// }
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateSource(lldb::SBLineEntry &line_entry) {
+ llvm::json::Object object;
+ lldb::SBFileSpec file = line_entry.GetFileSpec();
+ if (file.IsValid()) {
+ const char *name = file.GetFilename();
+ if (name)
+ EmplaceSafeString(object, "name", name);
+ char path[PATH_MAX] = "";
+ file.GetPath(path, sizeof(path));
+ if (path[0]) {
+ EmplaceSafeString(object, "path", std::string(path));
+ }
+ }
+ return llvm::json::Value(std::move(object));
+}
+
+llvm::json::Value CreateSource(lldb::SBFrame &frame, int64_t &disasm_line) {
+ disasm_line = 0;
+ auto line_entry = frame.GetLineEntry();
+ if (line_entry.GetFileSpec().IsValid())
+ return CreateSource(line_entry);
+
+ llvm::json::Object object;
+ const auto pc = frame.GetPC();
+
+ lldb::SBInstructionList insts;
+ lldb::SBFunction function = frame.GetFunction();
+ lldb::addr_t low_pc = LLDB_INVALID_ADDRESS;
+ if (function.IsValid()) {
+ low_pc = function.GetStartAddress().GetLoadAddress(g_vsc.target);
+ auto addr_srcref = g_vsc.addr_to_source_ref.find(low_pc);
+ if (addr_srcref != g_vsc.addr_to_source_ref.end()) {
+ // We have this disassembly cached already, return the existing
+ // sourceReference
+ object.try_emplace("sourceReference", addr_srcref->second);
+ disasm_line = g_vsc.GetLineForPC(addr_srcref->second, pc);
+ } else {
+ insts = function.GetInstructions(g_vsc.target);
+ }
+ } else {
+ lldb::SBSymbol symbol = frame.GetSymbol();
+ if (symbol.IsValid()) {
+ low_pc = symbol.GetStartAddress().GetLoadAddress(g_vsc.target);
+ auto addr_srcref = g_vsc.addr_to_source_ref.find(low_pc);
+ if (addr_srcref != g_vsc.addr_to_source_ref.end()) {
+ // We have this disassembly cached already, return the existing
+ // sourceReference
+ object.try_emplace("sourceReference", addr_srcref->second);
+ disasm_line = g_vsc.GetLineForPC(addr_srcref->second, pc);
+ } else {
+ insts = symbol.GetInstructions(g_vsc.target);
+ }
+ }
+ }
+ const auto num_insts = insts.GetSize();
+ if (low_pc != LLDB_INVALID_ADDRESS && num_insts > 0) {
+ EmplaceSafeString(object, "name", frame.GetFunctionName());
+ SourceReference source;
+ llvm::raw_string_ostream src_strm(source.content);
+ std::string line;
+ for (size_t i = 0; i < num_insts; ++i) {
+ lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);
+ const auto inst_addr = inst.GetAddress().GetLoadAddress(g_vsc.target);
+ const char *m = inst.GetMnemonic(g_vsc.target);
+ const char *o = inst.GetOperands(g_vsc.target);
+ const char *c = inst.GetComment(g_vsc.target);
+ if (pc == inst_addr)
+ disasm_line = i + 1;
+ const auto inst_offset = inst_addr - low_pc;
+ int spaces = 0;
+ if (inst_offset < 10)
+ spaces = 3;
+ else if (inst_offset < 100)
+ spaces = 2;
+ else if (inst_offset < 1000)
+ spaces = 1;
+ line.clear();
+ llvm::raw_string_ostream line_strm(line);
+ line_strm << llvm::formatv("{0:X+}: <{1}> {2} {3,12} {4}", inst_addr,
+ inst_offset, llvm::fmt_repeat(' ', spaces), m,
+ o);
+
+ // If there is a comment append it starting at column 60 or after one
+ // space past the last char
+ const uint32_t comment_row = std::max(line_strm.str().size(), (size_t)60);
+ if (c && c[0]) {
+ if (line.size() < comment_row)
+ line_strm.indent(comment_row - line_strm.str().size());
+ line_strm << " # " << c;
+ }
+ src_strm << line_strm.str() << "\n";
+ source.addr_to_line[inst_addr] = i + 1;
+ }
+ // Flush the source stream
+ src_strm.str();
+ auto sourceReference = VSCode::GetNextSourceReference();
+ g_vsc.source_map[sourceReference] = std::move(source);
+ g_vsc.addr_to_source_ref[low_pc] = sourceReference;
+ object.try_emplace("sourceReference", sourceReference);
+ }
+ return llvm::json::Value(std::move(object));
+}
+
+//----------------------------------------------------------------------
+// "StackFrame": {
+// "type": "object",
+// "description": "A Stackframe contains the source location.",
+// "properties": {
+// "id": {
+// "type": "integer",
+// "description": "An identifier for the stack frame. It must be unique
+// across all threads. This id can be used to retrieve
+// the scopes of the frame with the 'scopesRequest' or
+// to restart the execution of a stackframe."
+// },
+// "name": {
+// "type": "string",
+// "description": "The name of the stack frame, typically a method name."
+// },
+// "source": {
+// "$ref": "#/definitions/Source",
+// "description": "The optional source of the frame."
+// },
+// "line": {
+// "type": "integer",
+// "description": "The line within the file of the frame. If source is
+// null or doesn't exist, line is 0 and must be ignored."
+// },
+// "column": {
+// "type": "integer",
+// "description": "The column within the line. If source is null or
+// doesn't exist, column is 0 and must be ignored."
+// },
+// "endLine": {
+// "type": "integer",
+// "description": "An optional end line of the range covered by the
+// stack frame."
+// },
+// "endColumn": {
+// "type": "integer",
+// "description": "An optional end column of the range covered by the
+// stack frame."
+// },
+// "moduleId": {
+// "type": ["integer", "string"],
+// "description": "The module associated with this frame, if any."
+// },
+// "presentationHint": {
+// "type": "string",
+// "enum": [ "normal", "label", "subtle" ],
+// "description": "An optional hint for how to present this frame in
+// the UI. A value of 'label' can be used to indicate
+// that the frame is an artificial frame that is used
+// as a visual label or separator. A value of 'subtle'
+// can be used to change the appearance of a frame in
+// a 'subtle' way."
+// }
+// },
+// "required": [ "id", "name", "line", "column" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateStackFrame(lldb::SBFrame &frame) {
+ llvm::json::Object object;
+ int64_t frame_id = MakeVSCodeFrameID(frame);
+ object.try_emplace("id", frame_id);
+ EmplaceSafeString(object, "name", frame.GetFunctionName());
+ int64_t disasm_line = 0;
+ object.try_emplace("source", CreateSource(frame, disasm_line));
+
+ auto line_entry = frame.GetLineEntry();
+ if (disasm_line > 0) {
+ object.try_emplace("line", disasm_line);
+ } else {
+ auto line = line_entry.GetLine();
+ if (line == UINT32_MAX)
+ line = 0;
+ object.try_emplace("line", line);
+ }
+ object.try_emplace("column", line_entry.GetColumn());
+ return llvm::json::Value(std::move(object));
+}
+
+//----------------------------------------------------------------------
+// "Thread": {
+// "type": "object",
+// "description": "A Thread",
+// "properties": {
+// "id": {
+// "type": "integer",
+// "description": "Unique identifier for the thread."
+// },
+// "name": {
+// "type": "string",
+// "description": "A name of the thread."
+// }
+// },
+// "required": [ "id", "name" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateThread(lldb::SBThread &thread) {
+ llvm::json::Object object;
+ object.try_emplace("id", (int64_t)thread.GetThreadID());
+ char thread_str[64];
+ snprintf(thread_str, sizeof(thread_str), "Thread #%u", thread.GetIndexID());
+ const char *name = thread.GetName();
+ if (name) {
+ std::string thread_with_name(thread_str);
+ thread_with_name += ' ';
+ thread_with_name += name;
+ EmplaceSafeString(object, "name", thread_with_name);
+ } else {
+ EmplaceSafeString(object, "name", std::string(thread_str));
+ }
+ return llvm::json::Value(std::move(object));
+}
+
+//----------------------------------------------------------------------
+// "StoppedEvent": {
+// "allOf": [ { "$ref": "#/definitions/Event" }, {
+// "type": "object",
+// "description": "Event message for 'stopped' event type. The event
+// indicates that the execution of the debuggee has stopped
+// due to some condition. This can be caused by a break
+// point previously set, a stepping action has completed,
+// by executing a debugger statement etc.",
+// "properties": {
+// "event": {
+// "type": "string",
+// "enum": [ "stopped" ]
+// },
+// "body": {
+// "type": "object",
+// "properties": {
+// "reason": {
+// "type": "string",
+// "description": "The reason for the event. For backward
+// compatibility this string is shown in the UI if
+// the 'description' attribute is missing (but it
+// must not be translated).",
+// "_enum": [ "step", "breakpoint", "exception", "pause", "entry" ]
+// },
+// "description": {
+// "type": "string",
+// "description": "The full reason for the event, e.g. 'Paused
+// on exception'. This string is shown in the UI
+// as is."
+// },
+// "threadId": {
+// "type": "integer",
+// "description": "The thread which was stopped."
+// },
+// "text": {
+// "type": "string",
+// "description": "Additional information. E.g. if reason is
+// 'exception', text contains the exception name.
+// This string is shown in the UI."
+// },
+// "allThreadsStopped": {
+// "type": "boolean",
+// "description": "If allThreadsStopped is true, a debug adapter
+// can announce that all threads have stopped.
+// The client should use this information to
+// enable that all threads can be expanded to
+// access their stacktraces. If the attribute
+// is missing or false, only the thread with the
+// given threadId can be expanded."
+// }
+// },
+// "required": [ "reason" ]
+// }
+// },
+// "required": [ "event", "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateThreadStopped(lldb::SBThread &thread,
+ uint32_t stop_id) {
+ llvm::json::Object event(CreateEventObject("stopped"));
+ llvm::json::Object body;
+ switch (thread.GetStopReason()) {
+ case lldb::eStopReasonTrace:
+ case lldb::eStopReasonPlanComplete:
+ body.try_emplace("reason", "step");
+ break;
+ case lldb::eStopReasonBreakpoint: {
+ ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
+ if (exc_bp) {
+ body.try_emplace("reason", "exception");
+ EmplaceSafeString(body, "description", exc_bp->label);
+ } else {
+ body.try_emplace("reason", "breakpoint");
+ }
+ } break;
+ case lldb::eStopReasonWatchpoint:
+ case lldb::eStopReasonInstrumentation:
+ body.try_emplace("reason", "breakpoint");
+ break;
+ case lldb::eStopReasonSignal:
+ body.try_emplace("reason", "exception");
+ break;
+ case lldb::eStopReasonException:
+ body.try_emplace("reason", "exception");
+ break;
+ case lldb::eStopReasonExec:
+ body.try_emplace("reason", "entry");
+ break;
+ case lldb::eStopReasonThreadExiting:
+ case lldb::eStopReasonInvalid:
+ case lldb::eStopReasonNone:
+ break;
+ }
+ if (stop_id == 0)
+ body.try_emplace("reason", "entry");
+ const lldb::tid_t tid = thread.GetThreadID();
+ body.try_emplace("threadId", (int64_t)tid);
+ // If no description has been set, then set it to the default thread stopped
+ // description. If we have breakpoints that get hit and shouldn't be reported
+ // as breakpoints, then they will set the description above.
+ if (ObjectContainsKey(body, "description")) {
+ char description[1024];
+ if (thread.GetStopDescription(description, sizeof(description))) {
+ EmplaceSafeString(body, "description", std::string(description));
+ }
+ }
+ if (tid == g_vsc.focus_tid) {
+ body.try_emplace("threadCausedFocus", true);
+ }
+ body.try_emplace("preserveFocusHint", tid != g_vsc.focus_tid);
+ body.try_emplace("allThreadsStopped", true);
+ event.try_emplace("body", std::move(body));
+ return llvm::json::Value(std::move(event));
+}
+
+//----------------------------------------------------------------------
+// "Variable": {
+// "type": "object",
+// "description": "A Variable is a name/value pair. Optionally a variable
+// can have a 'type' that is shown if space permits or when
+// hovering over the variable's name. An optional 'kind' is
+// used to render additional properties of the variable,
+// e.g. different icons can be used to indicate that a
+// variable is public or private. If the value is
+// structured (has children), a handle is provided to
+// retrieve the children with the VariablesRequest. If
+// the number of named or indexed children is large, the
+// numbers should be returned via the optional
+// 'namedVariables' and 'indexedVariables' attributes. The
+// client can use this optional information to present the
+// children in a paged UI and fetch them in chunks.",
+// "properties": {
+// "name": {
+// "type": "string",
+// "description": "The variable's name."
+// },
+// "value": {
+// "type": "string",
+// "description": "The variable's value. This can be a multi-line text,
+// e.g. for a function the body of a function."
+// },
+// "type": {
+// "type": "string",
+// "description": "The type of the variable's value. Typically shown in
+// the UI when hovering over the value."
+// },
+// "presentationHint": {
+// "$ref": "#/definitions/VariablePresentationHint",
+// "description": "Properties of a variable that can be used to determine
+// how to render the variable in the UI."
+// },
+// "evaluateName": {
+// "type": "string",
+// "description": "Optional evaluatable name of this variable which can
+// be passed to the 'EvaluateRequest' to fetch the
+// variable's value."
+// },
+// "variablesReference": {
+// "type": "integer",
+// "description": "If variablesReference is > 0, the variable is
+// structured and its children can be retrieved by
+// passing variablesReference to the VariablesRequest."
+// },
+// "namedVariables": {
+// "type": "integer",
+// "description": "The number of named child variables. The client can
+// use this optional information to present the children
+// in a paged UI and fetch them in chunks."
+// },
+// "indexedVariables": {
+// "type": "integer",
+// "description": "The number of indexed child variables. The client
+// can use this optional information to present the
+// children in a paged UI and fetch them in chunks."
+// }
+// },
+// "required": [ "name", "value", "variablesReference" ]
+// }
+//----------------------------------------------------------------------
+llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
+ int64_t varID, bool format_hex) {
+ llvm::json::Object object;
+ auto name = v.GetName();
+ EmplaceSafeString(object, "name", name ? name : "<null>");
+ if (format_hex)
+ v.SetFormat(lldb::eFormatHex);
+ SetValueForKey(v, object, "value");
+ auto type_cstr = v.GetType().GetDisplayTypeName();
+ EmplaceSafeString(object, "type", type_cstr ? type_cstr : NO_TYPENAME);
+ if (varID != INT64_MAX)
+ object.try_emplace("id", varID);
+ if (v.MightHaveChildren())
+ object.try_emplace("variablesReference", variablesReference);
+ else
+ object.try_emplace("variablesReference", (int64_t)0);
+ lldb::SBStream evaluateStream;
+ v.GetExpressionPath(evaluateStream);
+ const char *evaluateName = evaluateStream.GetData();
+ if (evaluateName && evaluateName[0])
+ EmplaceSafeString(object, "evaluateName", std::string(evaluateName));
+ return llvm::json::Value(std::move(object));
+}
+
+} // namespace lldb_vscode
+
diff --git a/tools/lldb-vscode/JSONUtils.h b/tools/lldb-vscode/JSONUtils.h
new file mode 100644
index 000000000000..0ca000ce9385
--- /dev/null
+++ b/tools/lldb-vscode/JSONUtils.h
@@ -0,0 +1,438 @@
+//===-- JSONUtils.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_JSONUTILS_H_
+#define LLDBVSCODE_JSONUTILS_H_
+
+#include <stdint.h>
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/JSON.h"
+#include "VSCodeForward.h"
+
+namespace lldb_vscode {
+
+//------------------------------------------------------------------
+/// Emplace a StringRef in a json::Object after enusring that the
+/// string is valid UTF8. If not, first call llvm::json::fixUTF8
+/// before emplacing.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to emplace the value in
+///
+/// @param[in] key
+/// The key to use when emplacing the value
+///
+/// @param[in] str
+/// The string to emplace
+//------------------------------------------------------------------
+void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
+ llvm::StringRef str);
+
+//------------------------------------------------------------------
+/// Extract simple values as a string.
+///
+/// @param[in] value
+/// A JSON value to extract the string from.
+///
+/// @return
+/// A llvm::StringRef that contains the string value, or an empty
+/// string if \a value isn't a string.
+//------------------------------------------------------------------
+llvm::StringRef GetAsString(const llvm::json::Value &value);
+
+//------------------------------------------------------------------
+/// Extract the string value for the specified key from the
+/// specified object.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to extract the value from
+///
+/// @param[in] key
+/// The key to use when extracting the value
+///
+/// @return
+/// A llvm::StringRef that contains the string value for the
+/// specified \a key, or an empty string if there is no key that
+/// matches or if the value is not a string.
+//------------------------------------------------------------------
+llvm::StringRef GetString(const llvm::json::Object &obj, llvm::StringRef key);
+llvm::StringRef GetString(const llvm::json::Object *obj, llvm::StringRef key);
+
+//------------------------------------------------------------------
+/// Extract the unsigned integer value for the specified key from
+/// the specified object.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to extract the value from
+///
+/// @param[in] key
+/// The key to use when extracting the value
+///
+/// @return
+/// The unsigned integer value for the specified \a key, or
+/// \a fail_value if there is no key that matches or if the
+/// value is not an integer.
+//------------------------------------------------------------------
+uint64_t GetUnsigned(const llvm::json::Object &obj, llvm::StringRef key,
+ uint64_t fail_value);
+uint64_t GetUnsigned(const llvm::json::Object *obj, llvm::StringRef key,
+ uint64_t fail_value);
+
+//------------------------------------------------------------------
+/// Extract the boolean value for the specified key from the
+/// specified object.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to extract the value from
+///
+/// @param[in] key
+/// The key to use when extracting the value
+///
+/// @return
+/// The boolean value for the specified \a key, or \a fail_value
+/// if there is no key that matches or if the value is not a
+/// boolean value of an integer.
+//------------------------------------------------------------------
+bool GetBoolean(const llvm::json::Object &obj, llvm::StringRef key,
+ bool fail_value);
+bool GetBoolean(const llvm::json::Object *obj, llvm::StringRef key,
+ bool fail_value);
+
+//------------------------------------------------------------------
+/// Extract the signed integer for the specified key from the
+/// specified object.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to extract the value from
+///
+/// @param[in] key
+/// The key to use when extracting the value
+///
+/// @return
+/// The signed integer value for the specified \a key, or
+/// \a fail_value if there is no key that matches or if the
+/// value is not an integer.
+//------------------------------------------------------------------
+int64_t GetSigned(const llvm::json::Object &obj, llvm::StringRef key,
+ int64_t fail_value);
+int64_t GetSigned(const llvm::json::Object *obj, llvm::StringRef key,
+ int64_t fail_value);
+
+//------------------------------------------------------------------
+/// Check if the specified key exists in the specified object.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to extract the value from
+///
+/// @param[in] key
+/// The key to check for
+///
+/// @return
+/// \b True if the key exists in the \a obj, \b False otherwise.
+//------------------------------------------------------------------
+bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key);
+
+//------------------------------------------------------------------
+/// Extract an array of strings for the specified key from an object.
+///
+/// String values in the array will be extracted without any quotes
+/// around them. Numbers and Booleans will be converted into
+/// strings. Any NULL, array or objects values in the array will be
+/// ignored.
+///
+/// @param[in] obj
+/// A JSON object that we will attempt to extract the array from
+///
+/// @param[in] key
+/// The key to use when extracting the value
+///
+/// @return
+/// An array of string values for the specified \a key, or
+/// \a fail_value if there is no key that matches or if the
+/// value is not an array or all items in the array are not
+/// strings, numbers or booleans.
+//------------------------------------------------------------------
+std::vector<std::string> GetStrings(const llvm::json::Object *obj,
+ llvm::StringRef key);
+
+//------------------------------------------------------------------
+/// Fill a response object given the request object.
+///
+/// The \a response object will get its "type" set to "response",
+/// the "seq" set to zero, "response_seq" set to the "seq" value from
+/// \a request, "command" set to the "command" from \a request,
+/// and "success" set to true.
+///
+/// @param[in] request
+/// The request object received from a call to VSCode::ReadJSON().
+///
+/// @param[in,out] response
+/// An empty llvm::json::Object object that will be filled
+/// in as noted in description.
+//------------------------------------------------------------------
+void FillResponse(const llvm::json::Object &request,
+ llvm::json::Object &response);
+
+//----------------------------------------------------------------------
+/// Emplace the string value from an SBValue into the supplied object
+/// using \a key as the key that will contain the value.
+///
+/// The value is what we will display in VS Code. Some SBValue objects
+/// can have a value and/or a summary. If a value has both, we
+/// combine the value and the summary into one string. If we only have a
+/// value or summary, then that is considered the value. If there is
+/// no value and no summary then the value is the type name followed by
+/// the address of the type if it has an address.
+///
+///
+/// @param[in] v
+/// A lldb::SBValue object to extract the string value from
+///
+///
+/// @param[in] object
+/// The object to place the value object into
+///
+///
+/// @param[in] key
+/// The key name to use when inserting the value object we create
+//----------------------------------------------------------------------
+void SetValueForKey(lldb::SBValue &v, llvm::json::Object &object,
+ llvm::StringRef key);
+
+//----------------------------------------------------------------------
+/// Converts \a bp to a JSON value and appends all locations to the
+/// \a breakpoints array.
+///
+/// @param[in] bp
+/// A LLDB breakpoint object which will get all locations extracted
+/// and converted into a JSON objects in the \a breakpoints array
+///
+/// @param[in] breakpoints
+/// A JSON array that will get a llvm::json::Value for \a bp
+/// appended to it.
+//----------------------------------------------------------------------
+void AppendBreakpoint(lldb::SBBreakpoint &bp, llvm::json::Array &breakpoints);
+
+//----------------------------------------------------------------------
+/// Converts breakpoint location to a Visual Studio Code "Breakpoint"
+/// JSON object and appends it to the \a breakpoints array.
+///
+/// @param[in] bp_loc
+/// A LLDB breakpoint location object to convert into a JSON value
+///
+/// @return
+/// A "Breakpoint" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateBreakpoint(lldb::SBBreakpointLocation &bp_loc);
+
+//----------------------------------------------------------------------
+/// Create a "Event" JSON object using \a event_name as the event name
+///
+/// @param[in] event_name
+/// The string value to use for the "event" key in the JSON object.
+///
+/// @return
+/// A "Event" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Object CreateEventObject(const llvm::StringRef event_name);
+
+//----------------------------------------------------------------------
+/// Create a "ExceptionBreakpointsFilter" JSON object as described in
+/// the Visual Studio Code debug adaptor definition.
+///
+/// @param[in] bp
+/// The exception breakppoint object to use
+///
+/// @return
+/// A "ExceptionBreakpointsFilter" JSON object with that follows
+/// the formal JSON definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value
+CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp);
+
+//----------------------------------------------------------------------
+/// Create a "Scope" JSON object as described in the Visual Studio Code
+/// debug adaptor definition.
+///
+/// @param[in] name
+/// The value to place into the "name" key
+//
+/// @param[in] variablesReference
+/// The value to place into the "variablesReference" key
+//
+/// @param[in] namedVariables
+/// The value to place into the "namedVariables" key
+//
+/// @param[in] expensive
+/// The value to place into the "expensive" key
+///
+/// @return
+/// A "Scope" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateScope(const llvm::StringRef name,
+ int64_t variablesReference,
+ int64_t namedVariables, bool expensive);
+
+//----------------------------------------------------------------------
+/// Create a "Source" JSON object as described in the Visual Studio Code
+/// debug adaptor definition.
+///
+/// @param[in] line_entry
+/// The LLDB line table to use when populating out the "Source"
+/// object
+///
+/// @return
+/// A "Source" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateSource(lldb::SBLineEntry &line_entry);
+
+//----------------------------------------------------------------------
+/// Create a "Source" object for a given frame.
+///
+/// When there is no source file information for a stack frame, we will
+/// create disassembly for a function and store a permanent
+/// "sourceReference" that contains the textual disassembly for a
+/// function along with address to line information. The "Source" object
+/// that is created will contain a "sourceReference" that the VSCode
+/// protocol can later fetch as text in order to display disassembly.
+/// The PC will be extracted from the frame and the disassembly line
+/// within the source referred to by "sourceReference" will be filled
+/// in.
+///
+/// @param[in] frame
+/// The LLDB stack frame to use when populating out the "Source"
+/// object.
+///
+/// @param[out] disasm_line
+/// The line within the "sourceReference" file that the PC from
+/// \a frame matches.
+///
+/// @return
+/// A "Source" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateSource(lldb::SBFrame &frame, int64_t &disasm_line);
+
+//----------------------------------------------------------------------
+/// Create a "StackFrame" object for a LLDB frame object.
+///
+/// This function will fill in the following keys in the returned
+/// object:
+/// "id" - the stack frame ID as an integer
+/// "name" - the function name as a string
+/// "source" - source file information as a "Source" VSCode object
+/// "line" - the source file line number as an integer
+/// "column" - the source file column number as an integer
+///
+/// @param[in] frame
+/// The LLDB stack frame to use when populating out the "StackFrame"
+/// object.
+///
+/// @return
+/// A "StackFrame" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateStackFrame(lldb::SBFrame &frame);
+
+//----------------------------------------------------------------------
+/// Create a "Thread" object for a LLDB thread object.
+///
+/// This function will fill in the following keys in the returned
+/// object:
+/// "id" - the thread ID as an integer
+/// "name" - the thread name as a string which combines the LLDB
+/// thread index ID along with the string name of the thread
+/// from the OS if it has a name.
+///
+/// @param[in] thread
+/// The LLDB thread to use when populating out the "Thread"
+/// object.
+///
+/// @return
+/// A "Thread" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateThread(lldb::SBThread &thread);
+
+//----------------------------------------------------------------------
+/// Create a "StoppedEvent" object for a LLDB thread object.
+///
+/// This function will fill in the following keys in the returned
+/// object's "body" object:
+/// "reason" - With a valid stop reason enumeration string value
+/// that Microsoft specifies
+/// "threadId" - The thread ID as an integer
+/// "description" - a stop description (like "breakpoint 12.3") as a
+/// string
+/// "preserveFocusHint" - a boolean value that states if this thread
+/// should keep the focus in the GUI.
+/// "allThreadsStopped" - set to True to indicate that all threads
+/// stop when any thread stops.
+///
+/// @param[in] thread
+/// The LLDB thread to use when populating out the "StoppedEvent"
+/// object.
+///
+/// @return
+/// A "StoppedEvent" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateThreadStopped(lldb::SBThread &thread, uint32_t stop_id);
+
+//----------------------------------------------------------------------
+/// Create a "Variable" object for a LLDB thread object.
+///
+/// This function will fill in the following keys in the returned
+/// object:
+/// "name" - the name of the variable
+/// "value" - the value of the variable as a string
+/// "type" - the typename of the variable as a string
+/// "id" - a unique identifier for a value in case there are multiple
+/// variables with the same name. Other parts of the VSCode
+/// protocol refer to values by name so this can help
+/// disambiguate such cases if a IDE passes this "id" value
+/// back down.
+/// "variablesReference" - Zero if the variable has no children,
+/// non-zero integer otherwise which can be used to expand
+/// the variable.
+/// "evaluateName" - The name of the variable to use in expressions
+/// as a string.
+///
+/// @param[in] v
+/// The LLDB value to use when populating out the "Variable"
+/// object.
+///
+/// @param[in] variablesReference
+/// The variable reference. Zero if this value isn't structured
+/// and has no children, non-zero if it does have children and
+/// might be asked to expand itself.
+///
+/// @param[in] varID
+/// A unique variable identifier to help in properly identifying
+/// variables with the same name. This is an extension to the
+/// VS protocol.
+///
+/// @param[in] format_hex
+/// It set to true the variable will be formatted as hex in
+/// the "value" key value pair for the value of the variable.
+///
+/// @return
+/// A "Variable" JSON object with that follows the formal JSON
+/// definition outlined by Microsoft.
+//----------------------------------------------------------------------
+llvm::json::Value CreateVariable(lldb::SBValue v, int64_t variablesReference,
+ int64_t varID, bool format_hex);
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/LLDBUtils.cpp b/tools/lldb-vscode/LLDBUtils.cpp
new file mode 100644
index 000000000000..9653522a2d3a
--- /dev/null
+++ b/tools/lldb-vscode/LLDBUtils.cpp
@@ -0,0 +1,98 @@
+//===-- LLDBUtils.cpp -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LLDBUtils.h"
+#include "VSCode.h"
+
+namespace lldb_vscode {
+
+void RunLLDBCommands(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands,
+ llvm::raw_ostream &strm) {
+ if (commands.empty())
+ return;
+ lldb::SBCommandInterpreter interp = g_vsc.debugger.GetCommandInterpreter();
+ if (!prefix.empty())
+ strm << prefix << "\n";
+ for (const auto &command : commands) {
+ lldb::SBCommandReturnObject result;
+ strm << "(lldb) " << command << "\n";
+ interp.HandleCommand(command.c_str(), result);
+ auto output_len = result.GetOutputSize();
+ if (output_len) {
+ const char *output = result.GetOutput();
+ strm << output;
+ }
+ auto error_len = result.GetErrorSize();
+ if (error_len) {
+ const char *error = result.GetError();
+ strm << error;
+ }
+ }
+}
+
+std::string RunLLDBCommands(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands) {
+ std::string s;
+ llvm::raw_string_ostream strm(s);
+ RunLLDBCommands(prefix, commands, strm);
+ strm.flush();
+ return s;
+}
+
+bool ThreadHasStopReason(lldb::SBThread &thread) {
+ switch (thread.GetStopReason()) {
+ case lldb::eStopReasonTrace:
+ case lldb::eStopReasonPlanComplete:
+ case lldb::eStopReasonBreakpoint:
+ case lldb::eStopReasonWatchpoint:
+ case lldb::eStopReasonInstrumentation:
+ case lldb::eStopReasonSignal:
+ case lldb::eStopReasonException:
+ case lldb::eStopReasonExec:
+ return true;
+ case lldb::eStopReasonThreadExiting:
+ case lldb::eStopReasonInvalid:
+ case lldb::eStopReasonNone:
+ break;
+ }
+ return false;
+}
+
+static uint32_t constexpr THREAD_INDEX_SHIFT = 19;
+
+uint32_t GetLLDBThreadIndexID(uint64_t dap_frame_id) {
+ return dap_frame_id >> THREAD_INDEX_SHIFT;
+}
+
+uint32_t GetLLDBFrameID(uint64_t dap_frame_id) {
+ return dap_frame_id & ((1u << THREAD_INDEX_SHIFT) - 1);
+}
+
+int64_t MakeVSCodeFrameID(lldb::SBFrame &frame) {
+ return (int64_t)(frame.GetThread().GetIndexID() << THREAD_INDEX_SHIFT |
+ frame.GetFrameID());
+}
+
+static uint32_t constexpr BREAKPOINT_ID_SHIFT = 22;
+
+uint32_t GetLLDBBreakpointID(uint64_t dap_breakpoint_id) {
+ return dap_breakpoint_id >> BREAKPOINT_ID_SHIFT;
+}
+
+uint32_t GetLLDBBreakpointLocationID(uint64_t dap_breakpoint_id) {
+ return dap_breakpoint_id & ((1u << BREAKPOINT_ID_SHIFT) - 1);
+}
+
+int64_t MakeVSCodeBreakpointID(lldb::SBBreakpointLocation &bp_loc) {
+ return (int64_t)(bp_loc.GetBreakpoint().GetID() << BREAKPOINT_ID_SHIFT |
+ bp_loc.GetID());
+}
+
+} // namespace lldb_vscode
diff --git a/tools/lldb-vscode/LLDBUtils.h b/tools/lldb-vscode/LLDBUtils.h
new file mode 100644
index 000000000000..96ebb85f14b1
--- /dev/null
+++ b/tools/lldb-vscode/LLDBUtils.h
@@ -0,0 +1,170 @@
+//===-- LLDBUtils.h ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_LLDBUTILS_H_
+#define LLDBVSCODE_LLDBUTILS_H_
+
+#include "VSCodeForward.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <vector>
+
+namespace lldb_vscode {
+
+///----------------------------------------------------------------------
+/// Run a list of LLDB commands in the LLDB command interpreter.
+///
+/// All output from every command, including the prompt + the command
+/// is placed into the "strm" argument.
+///
+/// @param[in] prefix
+/// A string that will be printed into \a strm prior to emitting
+/// the prompt + command and command output. Can be NULL.
+///
+/// @param[in] commands
+/// An array of LLDB commands to execute.
+///
+/// @param[in] strm
+/// The stream that will receive the prefix, prompt + command and
+/// all command output.
+//----------------------------------------------------------------------
+void RunLLDBCommands(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands,
+ llvm::raw_ostream &strm);
+
+///----------------------------------------------------------------------
+/// Run a list of LLDB commands in the LLDB command interpreter.
+///
+/// All output from every command, including the prompt + the command
+/// is returned in the std::string return value.
+///
+/// @param[in] prefix
+/// A string that will be printed into \a strm prior to emitting
+/// the prompt + command and command output. Can be NULL.
+///
+/// @param[in] commands
+/// An array of LLDB commands to execute.
+///
+/// @return
+/// A std::string that contains the prefix and all commands and
+/// command output
+//----------------------------------------------------------------------
+std::string RunLLDBCommands(llvm::StringRef prefix,
+ const llvm::ArrayRef<std::string> &commands);
+
+///----------------------------------------------------------------------
+/// Check if a thread has a stop reason.
+///
+/// @param[in] thread
+/// The LLDB thread object to check
+///
+/// @return
+/// \b True if the thread has a valid stop reason, \b false
+/// otherwise.
+//----------------------------------------------------------------------
+bool ThreadHasStopReason(lldb::SBThread &thread);
+
+///----------------------------------------------------------------------
+/// Given a LLDB frame, make a frame ID that is unique to a specific
+/// thread and frame.
+///
+/// VSCode requires a Stackframe "id" to be unique, so we use the frame
+/// index in the lower 32 bits and the thread index ID in the upper 32
+/// bits.
+///
+/// @param[in] frame
+/// The LLDB stack frame object generate the ID for
+///
+/// @return
+/// A unique integer that allows us to easily find the right
+/// stack frame within a thread on subsequent VS code requests.
+//----------------------------------------------------------------------
+int64_t MakeVSCodeFrameID(lldb::SBFrame &frame);
+
+///----------------------------------------------------------------------
+/// Given a VSCode frame ID, convert to a LLDB thread index id.
+///
+/// VSCode requires a Stackframe "id" to be unique, so we use the frame
+/// index in the lower THREAD_INDEX_SHIFT bits and the thread index ID in
+/// the upper 32 - THREAD_INDEX_SHIFT bits.
+///
+/// @param[in] dap_frame_id
+/// The VSCode frame ID to convert to a thread index ID.
+///
+/// @return
+/// The LLDB thread index ID.
+//----------------------------------------------------------------------
+uint32_t GetLLDBThreadIndexID(uint64_t dap_frame_id);
+
+///----------------------------------------------------------------------
+/// Given a VSCode frame ID, convert to a LLDB frame ID.
+///
+/// VSCode requires a Stackframe "id" to be unique, so we use the frame
+/// index in the lower THREAD_INDEX_SHIFT bits and the thread index ID in
+/// the upper 32 - THREAD_INDEX_SHIFT bits.
+///
+/// @param[in] dap_frame_id
+/// The VSCode frame ID to convert to a frame ID.
+///
+/// @return
+/// The LLDB frame index ID.
+//----------------------------------------------------------------------
+uint32_t GetLLDBFrameID(uint64_t dap_frame_id);
+
+///----------------------------------------------------------------------
+/// Given a LLDB breakpoint, make a breakpoint ID that is unique to a
+/// specific breakpoint and breakpoint location.
+///
+/// VSCode requires a Breakpoint "id" to be unique, so we use the
+/// breakpoint ID in the lower BREAKPOINT_ID_SHIFT bits and the
+/// breakpoint location ID in the upper BREAKPOINT_ID_SHIFT bits.
+///
+/// @param[in] frame
+/// The LLDB stack frame object generate the ID for
+///
+/// @return
+/// A unique integer that allows us to easily find the right
+/// stack frame within a thread on subsequent VS code requests.
+//----------------------------------------------------------------------
+int64_t MakeVSCodeBreakpointID(lldb::SBBreakpointLocation &bp_loc);
+
+///----------------------------------------------------------------------
+/// Given a VSCode breakpoint ID, convert to a LLDB breakpoint ID.
+///
+/// VSCode requires a Breakpoint "id" to be unique, so we use the
+/// breakpoint ID in the lower BREAKPOINT_ID_SHIFT bits and the
+/// breakpoint location ID in the upper BREAKPOINT_ID_SHIFT bits.
+///
+/// @param[in] dap_breakpoint_id
+/// The VSCode breakpoint ID to convert to an LLDB breakpoint ID.
+///
+/// @return
+/// The LLDB breakpoint ID.
+//----------------------------------------------------------------------
+uint32_t GetLLDBBreakpointID(uint64_t dap_breakpoint_id);
+
+///----------------------------------------------------------------------
+/// Given a VSCode breakpoint ID, convert to a LLDB breakpoint location ID.
+///
+/// VSCode requires a Breakpoint "id" to be unique, so we use the
+/// breakpoint ID in the lower BREAKPOINT_ID_SHIFT bits and the
+/// breakpoint location ID in the upper BREAKPOINT_ID_SHIFT bits.
+///
+/// @param[in] dap_breakpoint_id
+/// The VSCode frame ID to convert to a breakpoint location ID.
+///
+/// @return
+/// The LLDB breakpoint location ID.
+//----------------------------------------------------------------------
+uint32_t GetLLDBBreakpointLocationID(uint64_t dap_breakpoint_id);
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/README.md b/tools/lldb-vscode/README.md
new file mode 100644
index 000000000000..2294659fc294
--- /dev/null
+++ b/tools/lldb-vscode/README.md
@@ -0,0 +1,195 @@
+
+# Table of Contents
+
+- [Introduction](#Introduction)
+- [Installation](#Installation-Visual-Studio-Code)
+- [Configurations](#configurations)
+ - [Launch Configuration Settings](#launch-configuration-settings)
+ - [Attach Configuration Settings](#attach-configuration-settings)
+ - [Example configurations](#example-configurations)
+ - [Launching](#launching)
+ - [Attach to process using process ID](#attach-using-pid)
+ - [Attach to process by name](#attach-by-name)
+ - [Loading a core file](#loading-a-core-file)
+
+# Introduction
+
+The `lldb-vscode` tool creates a command line tool that implements the [Visual
+Studio Code Debug API](https://code.visualstudio.com/docs/extensionAPI/api-debugging).
+It can be installed as an extension for the Visual Studio Code and Nuclide IDE.
+The protocol is easy to run remotely and also can allow other tools and IDEs to
+get a full featured debugger with a well defined protocol.
+
+# Installation for Visual Studio Code
+
+Installing the plug-in involves creating a directory in the `~/.vscode/extensions` folder and copying the package.json file that is in the same directory as this
+documentation into it, and copying to symlinking a lldb-vscode binary into
+the `bin` directory inside the plug-in directory.
+
+If you want to make a stand alone plug-in that you can send to others on unix systems:
+
+```
+$ mkdir -p ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
+$ cp package.json ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0
+$ cd ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
+$ cp /path/to/a/built/lldb-vscode .
+$ cp /path/to/a/built/liblldb.so .
+```
+
+
+If you want to make a stand alone plug-in that you can send to others on macOS systems:
+
+```
+$ mkdir -p ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
+$ cp package.json ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0
+$ cd ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
+$ cp /path/to/a/built/lldb-vscode .
+$ rsync -av /path/to/a/built/LLDB.framework LLDB.framework
+```
+
+You might need to create additional directories for the `liblldb.so` or `LLDB.framework` inside or next to the `bin` folder depending on how the [rpath](https://en.wikipedia.org/wiki/Rpath) is set in your `lldb-vscode` binary. By default the `Debug` builds of LLDB usually includes
+the current executable directory in the rpath, so these steps should work for most people.
+
+To create a plug-in that symlinks into your `lldb-vscode` in your build directory:
+
+```
+$ mkdir -p ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
+$ cp package.json ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0
+$ cd ~/.vscode/extensions/llvm-org.lldb-vscode-0.1.0/bin
+$ ln -s /path/to/a/built/lldb-vscode
+```
+
+This is handy if you want to debug and develope the `lldb-vscode` executable when adding features or fixing bugs.
+
+# Configurations
+
+Launching to attaching require you to create a [launch configuration](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations). This file
+defines arguments that get passed to `lldb-vscode` and the configuration settings
+control how the launch or attach happens.
+
+## Launch Configuration Settings
+
+When you launch a program with Visual Studio Code you will need to create a [launch.json](https://code.visualstudio.com/Docs/editor/debugging#_launch-configurations)
+file that defines how your program will be run. The JSON configuration file can contain the following `lldb-vscode` specific launch key/value pairs:
+
+|parameter |type|req | |
+|-------------------|----|:--:|---------|
+|**name** |string|Y| A configuration name that will be displayed in the IDE.
+|**type** |string|Y| Must be "lldb-vscode".
+|**request** |string|Y| Must be "launch".
+|**program** |string|Y| Path to the executable to launch.
+|**args** |[string]|| An array of command line argument strings to be passed to the program being launched.
+|**cwd** |string| | The program working directory.
+|**env** |dictionary| | Environment variables to set when launching the program. The format of each environment variable string is "VAR=VALUE" for environment variables with values or just "VAR" for environment variables with no values.
+|**stopOnEntry** |boolean| | Whether to stop program immediately after launching.
+|**initCommands** |[string]| | LLDB commands executed upon debugger startup prior to creating the LLDB target. Commands and command output will be sent to the debugger console when they are executed.
+|**preRunCommands** |[string]| | LLDB commands executed just before launching after the LLDB target has been created. Commands and command output will be sent to the debugger console when they are executed.
+|**stopCommands** |[string]| | LLDB commands executed just after each stop. Commands and command output will be sent to the debugger console when they are executed.
+|**exitCommands** |[string]| | LLDB commands executed when the program exits. Commands and command output will be sent to the debugger console when they are executed.
+|**sourceMap** |[string[2]]| | Specify an array of path re-mappings. Each element in the array must be a two element array containing a source and destination pathname.
+|**debuggerRoot** | string| |Specify a working directory to use when launching lldb-vscode. If the debug information in your executable contains relative paths, this option can be used so that `lldb-vscode` can find source files and object files that have relative paths.
+
+## Attaching Settings
+
+When attaching to a process using LLDB you can attach in a few ways
+
+1. Attach to an existing process using the process ID
+2. Attach to an existing process by name
+3. Attach by name by waiting for the next instance of a process to launch
+
+The JSON configuration file can contain the following `lldb-vscode` specific launch key/value pairs:
+
+|parameter |type |req | |
+|-------------------|--------|:--:|---------|
+|**name** |string |Y| A configuration name that will be displayed in the IDE.
+|**type** |string |Y| Must be "lldb-vscode".
+|**request** |string |Y| Must be "attach".
+|**program** |string | | Path to the executable to attach to. This value is optional but can help to resolve breakpoints prior the attaching to the program.
+|**pid** |number | | The process id of the process you wish to attach to. If **pid** is omitted, the debugger will attempt to attach to the program by finding a process whose file name matches the file name from **porgram**. Setting this value to `${command:pickMyProcess}` will allow interactive process selection in the IDE.
+|**stopOnEntry** |boolean| | Whether to stop program immediately after launching.
+|**waitFor** |boolean | | Wait for the process to launch.
+|**initCommands** |[string]| | LLDB commands executed upon debugger startup prior to creating the LLDB target. Commands and command output will be sent to the debugger console when they are executed.
+|**preRunCommands** |[string]| | LLDB commands executed just before launching after the LLDB target has been created. Commands and command output will be sent to the debugger console when they are executed.
+|**stopCommands** |[string]| | LLDB commands executed just after each stop. Commands and command output will be sent to the debugger console when they are executed.
+|**exitCommands** |[string]| | LLDB commands executed when the program exits. Commands and command output will be sent to the debugger console when they are executed.
+|**attachCommands** |[string]| | LLDB commands that will be executed after **preRunCommands** which take place of the code that normally does the attach. The commands can create a new target and attach or launch it however desired. This allows custom launch and attach configurations. Core files can use `target create --core /path/to/core` to attach to core files.
+
+
+## Example configurations
+
+### Launching
+
+This will launch `/tmp/a.out` with arguments `one`, `two`, and `three` and
+adds `FOO=1` and `bar` to the environment:
+
+```javascript
+{
+ "type": "lldb-vscode",
+ "request": "launch",
+ "name": "Debug",
+ "program": "/tmp/a.out",
+ "args": [ "one", "two", "three" ],
+ "env": [ "FOO=1", "BAR" ],
+}
+```
+
+### Attach using PID
+
+This will attach to a process `a.out` whose process ID is 123:
+
+```javascript
+{
+ "type": "lldb-vscode",
+ "request": "attach",
+ "name": "Attach to PID",
+ "program": "/tmp/a.out",
+ "pid": 123
+}
+```
+
+### Attach by Name
+
+This will attach to an existing process whose base
+name matches `a.out`. All we have to do is leave the `pid` value out of the
+above configuration:
+
+```javascript
+{
+ "name": "Attach to Name",
+ "type": "lldb-vscode",
+ "request": "attach",
+ "program": "/tmp/a.out",
+}
+```
+
+If you want to ignore any existing a.out processes and wait for the next instance
+to be launched you can add the "waitFor" key value pair:
+
+```javascript
+{
+ "name": "Attach to Name (wait)",
+ "type": "lldb-vscode",
+ "request": "attach",
+ "program": "/tmp/a.out",
+ "waitFor": true
+}
+```
+
+This will work as long as the architecture, vendor and OS supports waiting
+for processes. Currently MacOS is the only platform that supports this.
+
+
+### Loading a Core File
+
+Loading a core file can use the `"attach"` request along with the
+`"attachCommands"` to implement a custom attach:
+
+```javascript
+{
+ "name": "Attach to Name (wait)",
+ "type": "lldb-vscode",
+ "request": "attach",
+ "attachCommands": ["target create -c /path/to/123.core /path/to/executable"],
+ "stopOnEntry": false
+}
+```
diff --git a/tools/lldb-vscode/SourceBreakpoint.cpp b/tools/lldb-vscode/SourceBreakpoint.cpp
new file mode 100644
index 000000000000..f2a286c9eca2
--- /dev/null
+++ b/tools/lldb-vscode/SourceBreakpoint.cpp
@@ -0,0 +1,27 @@
+//===-- SourceBreakpoint.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SourceBreakpoint.h"
+#include "VSCode.h"
+
+namespace lldb_vscode {
+
+SourceBreakpoint::SourceBreakpoint(const llvm::json::Object &obj)
+ : BreakpointBase(obj), line(GetUnsigned(obj, "line", 0)),
+ column(GetUnsigned(obj, "column", 0)) {}
+
+void SourceBreakpoint::SetBreakpoint(const llvm::StringRef source_path) {
+ bp = g_vsc.target.BreakpointCreateByLocation(source_path.str().c_str(), line);
+ if (!condition.empty())
+ SetCondition();
+ if (!hitCondition.empty())
+ SetHitCondition();
+}
+
+} // namespace lldb_vscode
diff --git a/tools/lldb-vscode/SourceBreakpoint.h b/tools/lldb-vscode/SourceBreakpoint.h
new file mode 100644
index 000000000000..8af647ca8fe5
--- /dev/null
+++ b/tools/lldb-vscode/SourceBreakpoint.h
@@ -0,0 +1,39 @@
+//===-- SourceBreakpoint.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_SOURCEBREAKPOINT_H_
+#define LLDBVSCODE_SOURCEBREAKPOINT_H_
+
+#include "llvm/ADT/StringRef.h"
+#include "BreakpointBase.h"
+
+namespace lldb_vscode {
+
+struct SourceBreakpoint : public BreakpointBase {
+
+ uint32_t line; ///< The source line of the breakpoint or logpoint
+ uint32_t column; ///< An optional source column of the breakpoint
+
+ SourceBreakpoint() : BreakpointBase(), line(0), column(0) {}
+ SourceBreakpoint(const llvm::json::Object &obj);
+
+ // Set this breakpoint in LLDB as a new breakpoint
+ void SetBreakpoint(const llvm::StringRef source_path);
+};
+
+inline bool operator<(const SourceBreakpoint &lhs,
+ const SourceBreakpoint &rhs) {
+ if (lhs.line == rhs.line)
+ return lhs.column < rhs.column;
+ return lhs.line < rhs.line;
+}
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/SourceReference.h b/tools/lldb-vscode/SourceReference.h
new file mode 100644
index 000000000000..f047143e6c84
--- /dev/null
+++ b/tools/lldb-vscode/SourceReference.h
@@ -0,0 +1,33 @@
+//===-- SourceReference.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_SOURCEREFERENCE_H_
+#define LLDBVSCODE_SOURCEREFERENCE_H_
+
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/DenseMap.h"
+#include <string>
+
+namespace lldb_vscode {
+
+struct SourceReference {
+ std::string content;
+ llvm::DenseMap<lldb::addr_t, int64_t> addr_to_line;
+
+ int64_t GetLineForPC(lldb::addr_t pc) const {
+ auto addr_line = addr_to_line.find(pc);
+ if (addr_line != addr_to_line.end())
+ return addr_line->second;
+ return 0;
+ }
+};
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/VSCode.cpp b/tools/lldb-vscode/VSCode.cpp
new file mode 100644
index 000000000000..0f138ec77707
--- /dev/null
+++ b/tools/lldb-vscode/VSCode.cpp
@@ -0,0 +1,349 @@
+//===-- VSCode.cpp ----------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdarg.h>
+#include <fstream>
+#include <mutex>
+
+#include "VSCode.h"
+#include "LLDBUtils.h"
+
+#if defined(_WIN32)
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+using namespace lldb_vscode;
+
+namespace {
+ inline bool IsEmptyLine(llvm::StringRef S) {
+ return S.ltrim().empty();
+ }
+} // namespace
+
+namespace lldb_vscode {
+
+VSCode g_vsc;
+
+VSCode::VSCode()
+ : in(stdin), out(stdout), launch_info(nullptr), variables(),
+ broadcaster("lldb-vscode"), num_regs(0), num_locals(0), num_globals(0),
+ log(), exception_breakpoints(
+ {{"cpp_catch", "C++ Catch", lldb::eLanguageTypeC_plus_plus},
+ {"cpp_throw", "C++ Throw", lldb::eLanguageTypeC_plus_plus},
+ {"objc_catch", "Objective C Catch", lldb::eLanguageTypeObjC},
+ {"objc_throw", "Objective C Throw", lldb::eLanguageTypeObjC},
+ {"swift_catch", "Swift Catch", lldb::eLanguageTypeSwift},
+ {"swift_throw", "Swift Throw", lldb::eLanguageTypeSwift}}),
+ focus_tid(LLDB_INVALID_THREAD_ID), sent_terminated_event(false),
+ stop_at_entry(false) {
+ const char *log_file_path = getenv("LLDBVSCODE_LOG");
+#if defined(_WIN32)
+// Windows opens stdout and stdin in text mode which converts \n to 13,10
+// while the value is just 10 on Darwin/Linux. Setting the file mode to binary
+// fixes this.
+ assert(_setmode(fileno(stdout), _O_BINARY));
+ assert(_setmode(fileno(stdin), _O_BINARY));
+#endif
+ if (log_file_path)
+ log.reset(new std::ofstream(log_file_path));
+}
+
+VSCode::~VSCode() {
+ CloseInputStream();
+ CloseOutputStream();
+}
+
+void VSCode::CloseInputStream() {
+ if (in != stdin) {
+ fclose(in);
+ in = nullptr;
+ }
+}
+
+void VSCode::CloseOutputStream() {
+ if (out != stdout) {
+ fclose(out);
+ out = nullptr;
+ }
+}
+
+int64_t VSCode::GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const {
+ auto pos = source_map.find(sourceReference);
+ if (pos != source_map.end())
+ return pos->second.GetLineForPC(pc);
+ return 0;
+}
+
+ExceptionBreakpoint *VSCode::GetExceptionBreakpoint(const std::string &filter) {
+ for (auto &bp : exception_breakpoints) {
+ if (bp.filter == filter)
+ return &bp;
+ }
+ return nullptr;
+}
+
+ExceptionBreakpoint *
+VSCode::GetExceptionBreakpoint(const lldb::break_id_t bp_id) {
+ for (auto &bp : exception_breakpoints) {
+ if (bp.bp.GetID() == bp_id)
+ return &bp;
+ }
+ return nullptr;
+}
+
+//----------------------------------------------------------------------
+// Send the JSON in "json_str" to the "out" stream. Correctly send the
+// "Content-Length:" field followed by the length, followed by the raw
+// JSON bytes.
+//----------------------------------------------------------------------
+void VSCode::SendJSON(const std::string &json_str) {
+ fprintf(out, "Content-Length: %u\r\n\r\n%s", (uint32_t)json_str.size(),
+ json_str.c_str());
+ fflush(out);
+ if (log) {
+ *log << "<-- " << std::endl
+ << "Content-Length: " << json_str.size() << "\r\n\r\n"
+ << json_str << std::endl;
+ }
+}
+
+//----------------------------------------------------------------------
+// Serialize the JSON value into a string and send the JSON packet to
+// the "out" stream.
+//----------------------------------------------------------------------
+void VSCode::SendJSON(const llvm::json::Value &json) {
+ std::string s;
+ llvm::raw_string_ostream strm(s);
+ strm << json;
+ static std::mutex mutex;
+ std::lock_guard<std::mutex> locker(mutex);
+ SendJSON(strm.str());
+}
+
+//----------------------------------------------------------------------
+// Read a JSON packet from the "in" stream.
+//----------------------------------------------------------------------
+std::string VSCode::ReadJSON() {
+ static std::string header("Content-Length: ");
+
+ uint32_t packet_len = 0;
+ std::string json_str;
+ char line[1024];
+
+ while (fgets(line, sizeof(line), in)) {
+ if (strncmp(line, header.data(), header.size()) == 0) {
+ packet_len = atoi(line + header.size());
+ if (fgets(line, sizeof(line), in)) {
+ if (!IsEmptyLine(line))
+ if (log)
+ *log << "warning: expected empty line but got: \"" << line << "\""
+ << std::endl;
+ break;
+ }
+ } else {
+ if (log)
+ *log << "warning: expected \"" << header << "\" but got: \"" << line
+ << "\"" << std::endl;
+ }
+ }
+ // This is followed by two windows newline sequences ("\r\n\r\n") so eat
+ // two the newline sequences
+ if (packet_len > 0) {
+ json_str.resize(packet_len);
+ auto bytes_read = fread(&json_str[0], 1, packet_len, in);
+ if (bytes_read < packet_len) {
+ if (log)
+ *log << "error: read fewer bytes (" << bytes_read
+ << ") than requested (" << packet_len << ")" << std::endl;
+ json_str.erase(bytes_read);
+ }
+ if (log) {
+ *log << "--> " << std::endl;
+ *log << header << packet_len << "\r\n\r\n" << json_str << std::endl;
+ }
+ }
+ return json_str;
+}
+
+//----------------------------------------------------------------------
+// "OutputEvent": {
+// "allOf": [ { "$ref": "#/definitions/Event" }, {
+// "type": "object",
+// "description": "Event message for 'output' event type. The event
+// indicates that the target has produced some output.",
+// "properties": {
+// "event": {
+// "type": "string",
+// "enum": [ "output" ]
+// },
+// "body": {
+// "type": "object",
+// "properties": {
+// "category": {
+// "type": "string",
+// "description": "The output category. If not specified,
+// 'console' is assumed.",
+// "_enum": [ "console", "stdout", "stderr", "telemetry" ]
+// },
+// "output": {
+// "type": "string",
+// "description": "The output to report."
+// },
+// "variablesReference": {
+// "type": "number",
+// "description": "If an attribute 'variablesReference' exists
+// and its value is > 0, the output contains
+// objects which can be retrieved by passing
+// variablesReference to the VariablesRequest."
+// },
+// "source": {
+// "$ref": "#/definitions/Source",
+// "description": "An optional source location where the output
+// was produced."
+// },
+// "line": {
+// "type": "integer",
+// "description": "An optional source location line where the
+// output was produced."
+// },
+// "column": {
+// "type": "integer",
+// "description": "An optional source location column where the
+// output was produced."
+// },
+// "data": {
+// "type":["array","boolean","integer","null","number","object",
+// "string"],
+// "description": "Optional data to report. For the 'telemetry'
+// category the data will be sent to telemetry, for
+// the other categories the data is shown in JSON
+// format."
+// }
+// },
+// "required": ["output"]
+// }
+// },
+// "required": [ "event", "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void VSCode::SendOutput(OutputType o, const llvm::StringRef output) {
+ if (output.empty())
+ return;
+
+ llvm::json::Object event(CreateEventObject("output"));
+ llvm::json::Object body;
+ const char *category = nullptr;
+ switch (o) {
+ case OutputType::Console:
+ category = "console";
+ break;
+ case OutputType::Stdout:
+ category = "stdout";
+ break;
+ case OutputType::Stderr:
+ category = "stderr";
+ break;
+ case OutputType::Telemetry:
+ category = "telemetry";
+ break;
+ }
+ body.try_emplace("category", category);
+ EmplaceSafeString(body, "output", output.str());
+ event.try_emplace("body", std::move(body));
+ SendJSON(llvm::json::Value(std::move(event)));
+}
+
+void __attribute__((format(printf, 3, 4)))
+VSCode::SendFormattedOutput(OutputType o, const char *format, ...) {
+ char buffer[1024];
+ va_list args;
+ va_start(args, format);
+ int actual_length = vsnprintf(buffer, sizeof(buffer), format, args);
+ va_end(args);
+ SendOutput(o, llvm::StringRef(buffer,
+ std::min<int>(actual_length, sizeof(buffer))));
+}
+
+int64_t VSCode::GetNextSourceReference() {
+ static int64_t ref = 0;
+ return ++ref;
+}
+
+ExceptionBreakpoint *
+VSCode::GetExceptionBPFromStopReason(lldb::SBThread &thread) {
+ const auto num = thread.GetStopReasonDataCount();
+ // Check to see if have hit an exception breakpoint and change the
+ // reason to "exception", but only do so if all breakpoints that were
+ // hit are exception breakpoints.
+ ExceptionBreakpoint *exc_bp = nullptr;
+ for (size_t i = 0; i < num; i += 2) {
+ // thread.GetStopReasonDataAtIndex(i) will return the bp ID and
+ // thread.GetStopReasonDataAtIndex(i+1) will return the location
+ // within that breakpoint. We only care about the bp ID so we can
+ // see if this is an exception breakpoint that is getting hit.
+ lldb::break_id_t bp_id = thread.GetStopReasonDataAtIndex(i);
+ exc_bp = GetExceptionBreakpoint(bp_id);
+ // If any breakpoint is not an exception breakpoint, then stop and
+ // report this as a normal breakpoint
+ if (exc_bp == nullptr)
+ return nullptr;
+ }
+ return exc_bp;
+}
+
+lldb::SBThread VSCode::GetLLDBThread(const llvm::json::Object &arguments) {
+ auto tid = GetSigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
+ return target.GetProcess().GetThreadByID(tid);
+}
+
+lldb::SBFrame VSCode::GetLLDBFrame(const llvm::json::Object &arguments) {
+ const uint64_t frame_id = GetUnsigned(arguments, "frameId", UINT64_MAX);
+ lldb::SBProcess process = target.GetProcess();
+ // Upper 32 bits is the thread index ID
+ lldb::SBThread thread =
+ process.GetThreadByIndexID(GetLLDBThreadIndexID(frame_id));
+ // Lower 32 bits is the frame index
+ return thread.GetFrameAtIndex(GetLLDBFrameID(frame_id));
+}
+
+llvm::json::Value VSCode::CreateTopLevelScopes() {
+ llvm::json::Array scopes;
+ scopes.emplace_back(CreateScope("Locals", VARREF_LOCALS, num_locals, false));
+ scopes.emplace_back(
+ CreateScope("Globals", VARREF_GLOBALS, num_globals, false));
+ scopes.emplace_back(CreateScope("Registers", VARREF_REGS, num_regs, false));
+ return llvm::json::Value(std::move(scopes));
+}
+
+void VSCode::RunLLDBCommands(llvm::StringRef prefix,
+ const std::vector<std::string> &commands) {
+ SendOutput(OutputType::Console,
+ llvm::StringRef(::RunLLDBCommands(prefix, commands)));
+}
+
+void VSCode::RunInitCommands() {
+ RunLLDBCommands("Running initCommands:", init_commands);
+}
+
+void VSCode::RunPreRunCommands() {
+ RunLLDBCommands("Running preRunCommands:", pre_run_commands);
+}
+
+void VSCode::RunStopCommands() {
+ RunLLDBCommands("Running stopCommands:", stop_commands);
+}
+
+void VSCode::RunExitCommands() {
+ RunLLDBCommands("Running exitCommands:", exit_commands);
+}
+
+} // namespace lldb_vscode
+
diff --git a/tools/lldb-vscode/VSCode.h b/tools/lldb-vscode/VSCode.h
new file mode 100644
index 000000000000..142be3318367
--- /dev/null
+++ b/tools/lldb-vscode/VSCode.h
@@ -0,0 +1,146 @@
+//===-- VSCode.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_VSCODE_H_
+#define LLDBVSCODE_VSCODE_H_
+
+#include <iosfwd>
+#include <map>
+#include <set>
+#include <stdio.h>
+#include <thread>
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+
+#include "lldb/API/SBAttachInfo.h"
+#include "lldb/API/SBBreakpoint.h"
+#include "lldb/API/SBBreakpointLocation.h"
+#include "lldb/API/SBCommandInterpreter.h"
+#include "lldb/API/SBCommandReturnObject.h"
+#include "lldb/API/SBCommunication.h"
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBEvent.h"
+#include "lldb/API/SBHostOS.h"
+#include "lldb/API/SBInstruction.h"
+#include "lldb/API/SBInstructionList.h"
+#include "lldb/API/SBLanguageRuntime.h"
+#include "lldb/API/SBLaunchInfo.h"
+#include "lldb/API/SBLineEntry.h"
+#include "lldb/API/SBListener.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBTarget.h"
+#include "lldb/API/SBThread.h"
+
+#include "ExceptionBreakpoint.h"
+#include "FunctionBreakpoint.h"
+#include "SourceBreakpoint.h"
+#include "SourceReference.h"
+
+#define VARREF_LOCALS (int64_t)1
+#define VARREF_GLOBALS (int64_t)2
+#define VARREF_REGS (int64_t)3
+#define VARREF_FIRST_VAR_IDX (int64_t)4
+#define VARREF_IS_SCOPE(v) (VARREF_LOCALS <= 1 && v < VARREF_FIRST_VAR_IDX)
+#define VARIDX_TO_VARREF(i) ((i) + VARREF_FIRST_VAR_IDX)
+#define VARREF_TO_VARIDX(v) ((v)-VARREF_FIRST_VAR_IDX)
+#define NO_TYPENAME "<no-type>"
+
+namespace lldb_vscode {
+
+typedef llvm::DenseMap<uint32_t, SourceBreakpoint> SourceBreakpointMap;
+typedef llvm::StringMap<FunctionBreakpoint> FunctionBreakpointMap;
+enum class OutputType { Console, Stdout, Stderr, Telemetry };
+
+struct VSCode {
+ FILE *in;
+ FILE *out;
+ lldb::SBDebugger debugger;
+ lldb::SBTarget target;
+ lldb::SBAttachInfo attach_info;
+ lldb::SBLaunchInfo launch_info;
+ lldb::SBValueList variables;
+ lldb::SBBroadcaster broadcaster;
+ int64_t num_regs;
+ int64_t num_locals;
+ int64_t num_globals;
+ std::thread event_thread;
+ std::unique_ptr<std::ofstream> log;
+ llvm::DenseMap<lldb::addr_t, int64_t> addr_to_source_ref;
+ llvm::DenseMap<int64_t, SourceReference> source_map;
+ llvm::StringMap<SourceBreakpointMap> source_breakpoints;
+ FunctionBreakpointMap function_breakpoints;
+ std::vector<ExceptionBreakpoint> exception_breakpoints;
+ std::vector<std::string> init_commands;
+ std::vector<std::string> pre_run_commands;
+ std::vector<std::string> exit_commands;
+ std::vector<std::string> stop_commands;
+ lldb::tid_t focus_tid;
+ bool sent_terminated_event;
+ bool stop_at_entry;
+ // Keep track of the last stop thread index IDs as threads won't go away
+ // unless we send a "thread" event to indicate the thread exited.
+ llvm::DenseSet<lldb::tid_t> thread_ids;
+ VSCode();
+ ~VSCode();
+ VSCode(const VSCode &rhs) = delete;
+ void operator=(const VSCode &rhs) = delete;
+ void CloseInputStream();
+ void CloseOutputStream();
+ int64_t GetLineForPC(int64_t sourceReference, lldb::addr_t pc) const;
+ ExceptionBreakpoint *GetExceptionBreakpoint(const std::string &filter);
+ ExceptionBreakpoint *GetExceptionBreakpoint(const lldb::break_id_t bp_id);
+ //----------------------------------------------------------------------
+ // Send the JSON in "json_str" to the "out" stream. Correctly send the
+ // "Content-Length:" field followed by the length, followed by the raw
+ // JSON bytes.
+ //----------------------------------------------------------------------
+ void SendJSON(const std::string &json_str);
+
+ //----------------------------------------------------------------------
+ // Serialize the JSON value into a string and send the JSON packet to
+ // the "out" stream.
+ //----------------------------------------------------------------------
+ void SendJSON(const llvm::json::Value &json);
+
+ std::string ReadJSON();
+
+ void SendOutput(OutputType o, const llvm::StringRef output);
+
+ void __attribute__((format(printf, 3, 4)))
+ SendFormattedOutput(OutputType o, const char *format, ...);
+
+ static int64_t GetNextSourceReference();
+
+ ExceptionBreakpoint *GetExceptionBPFromStopReason(lldb::SBThread &thread);
+
+ lldb::SBThread GetLLDBThread(const llvm::json::Object &arguments);
+
+ lldb::SBFrame GetLLDBFrame(const llvm::json::Object &arguments);
+
+ llvm::json::Value CreateTopLevelScopes();
+
+ void RunLLDBCommands(llvm::StringRef prefix,
+ const std::vector<std::string> &commands);
+
+ void RunInitCommands();
+ void RunPreRunCommands();
+ void RunStopCommands();
+ void RunExitCommands();
+};
+
+extern VSCode g_vsc;
+
+} // namespace lldb_vscode
+
+#endif
diff --git a/tools/lldb-vscode/VSCodeForward.h b/tools/lldb-vscode/VSCodeForward.h
new file mode 100644
index 000000000000..d5b7f8d53f77
--- /dev/null
+++ b/tools/lldb-vscode/VSCodeForward.h
@@ -0,0 +1,47 @@
+//===-- VSCodeForward.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDBVSCODE_VSCODEFORWARD_H_
+#define LLDBVSCODE_VSCODEFORWARD_H_
+
+
+namespace lldb_vscode {
+struct BreakpointBase;
+struct ExceptionBreakpoint;
+struct FunctionBreakpoint;
+struct SourceBreakpoint;
+struct SourceReference;
+} // namespace lldb_vscode
+
+namespace lldb {
+class SBAttachInfo;
+class SBBreakpoint;
+class SBBreakpointLocation;
+class SBCommandInterpreter;
+class SBCommandReturnObject;
+class SBCommunication;
+class SBDebugger;
+class SBEvent;
+class SBFrame;
+class SBHostOS;
+class SBInstruction;
+class SBInstructionList;
+class SBLanguageRuntime;
+class SBLaunchInfo;
+class SBLineEntry;
+class SBListener;
+class SBProcess;
+class SBStream;
+class SBStringList;
+class SBTarget;
+class SBThread;
+class SBValue;
+} // namespace lldb
+
+#endif
diff --git a/tools/lldb-vscode/lldb-vscode-Info.plist b/tools/lldb-vscode/lldb-vscode-Info.plist
new file mode 100644
index 000000000000..a6b824372546
--- /dev/null
+++ b/tools/lldb-vscode/lldb-vscode-Info.plist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.apple.lldb-vscode</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>lldb-vscode</string>
+ <key>CFBundleVersion</key>
+ <string>360.99.0</string>
+ <key>SecTaskAccess</key>
+ <array>
+ <string>allowed</string>
+ <string>debug</string>
+ </array>
+</dict>
+</plist>
diff --git a/tools/lldb-vscode/lldb-vscode.cpp b/tools/lldb-vscode/lldb-vscode.cpp
new file mode 100644
index 000000000000..2aad7977efa0
--- /dev/null
+++ b/tools/lldb-vscode/lldb-vscode.cpp
@@ -0,0 +1,2706 @@
+//===-- lldb-vscode.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#if defined(_WIN32)
+// We need to #define NOMINMAX in order to skip `min()` and `max()` macro
+// definitions that conflict with other system headers.
+// We also need to #undef GetObject (which is defined to GetObjectW) because
+// the JSON code we use also has methods named `GetObject()` and we conflict
+// against these.
+#define NOMINMAX
+#include <windows.h>
+#undef GetObject
+#else
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <chrono>
+#include <fstream>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <sstream>
+#include <thread>
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "JSONUtils.h"
+#include "LLDBUtils.h"
+#include "VSCode.h"
+
+#if defined(_WIN32)
+#define PATH_MAX MAX_PATH
+typedef int socklen_t;
+constexpr const char *dev_null_path = "nul";
+
+#else
+typedef int SOCKET;
+constexpr const char *dev_null_path = "/dev/null";
+
+#endif
+
+using namespace lldb_vscode;
+
+namespace {
+
+typedef void (*RequestCallback)(const llvm::json::Object &command);
+
+enum LaunchMethod { Launch, Attach, AttachForSuspendedLaunch };
+
+enum VSCodeBroadcasterBits { eBroadcastBitStopEventThread = 1u << 0 };
+
+int AcceptConnection(int portno) {
+ // Accept a socket connection from any host on "portno".
+ int newsockfd = -1;
+ struct sockaddr_in serv_addr, cli_addr;
+ SOCKET sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ if (g_vsc.log)
+ *g_vsc.log << "error: opening socket (" << strerror(errno) << ")"
+ << std::endl;
+ } else {
+ memset((char *)&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ // serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ serv_addr.sin_port = htons(portno);
+ if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
+ if (g_vsc.log)
+ *g_vsc.log << "error: binding socket (" << strerror(errno) << ")"
+ << std::endl;
+ } else {
+ listen(sockfd, 5);
+ socklen_t clilen = sizeof(cli_addr);
+ newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
+ if (newsockfd < 0)
+ if (g_vsc.log)
+ *g_vsc.log << "error: accept (" << strerror(errno) << ")"
+ << std::endl;
+ }
+#if defined(_WIN32)
+ closesocket(sockfd);
+#else
+ close(sockfd);
+#endif
+ }
+ return newsockfd;
+}
+
+std::vector<const char *> MakeArgv(const llvm::ArrayRef<std::string> &strs) {
+ // Create and return an array of "const char *", one for each C string in
+ // "strs" and terminate the list with a NULL. This can be used for argument
+ // vectors (argv) or environment vectors (envp) like those passed to the
+ // "main" function in C programs.
+ std::vector<const char *> argv;
+ for (const auto &s : strs)
+ argv.push_back(s.c_str());
+ argv.push_back(nullptr);
+ return argv;
+}
+
+//----------------------------------------------------------------------
+// Send a "exited" event to indicate the process has exited.
+//----------------------------------------------------------------------
+void SendProcessExitedEvent(lldb::SBProcess &process) {
+ llvm::json::Object event(CreateEventObject("exited"));
+ llvm::json::Object body;
+ body.try_emplace("exitCode", (int64_t)process.GetExitStatus());
+ event.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(event)));
+}
+
+void SendThreadExitedEvent(lldb::tid_t tid) {
+ llvm::json::Object event(CreateEventObject("thread"));
+ llvm::json::Object body;
+ body.try_emplace("reason", "exited");
+ body.try_emplace("threadId", (int64_t)tid);
+ event.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(event)));
+}
+
+//----------------------------------------------------------------------
+// Send a "terminated" event to indicate the process is done being
+// debugged.
+//----------------------------------------------------------------------
+void SendTerminatedEvent() {
+ if (!g_vsc.sent_terminated_event) {
+ g_vsc.sent_terminated_event = true;
+ // Send a "terminated" event
+ llvm::json::Object event(CreateEventObject("terminated"));
+ g_vsc.SendJSON(llvm::json::Value(std::move(event)));
+ }
+}
+
+//----------------------------------------------------------------------
+// Send a thread stopped event for all threads as long as the process
+// is stopped.
+//----------------------------------------------------------------------
+void SendThreadStoppedEvent() {
+ lldb::SBProcess process = g_vsc.target.GetProcess();
+ if (process.IsValid()) {
+ auto state = process.GetState();
+ if (state == lldb::eStateStopped) {
+ llvm::DenseSet<lldb::tid_t> old_thread_ids;
+ old_thread_ids.swap(g_vsc.thread_ids);
+ uint32_t stop_id = process.GetStopID();
+ const uint32_t num_threads = process.GetNumThreads();
+
+ // First make a pass through the threads to see if the focused thread
+ // has a stop reason. In case the focus thread doesn't have a stop
+ // reason, remember the first thread that has a stop reason so we can
+ // set it as the focus thread if below if needed.
+ lldb::tid_t first_tid_with_reason = LLDB_INVALID_THREAD_ID;
+ uint32_t num_threads_with_reason = 0;
+ for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
+ lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
+ const lldb::tid_t tid = thread.GetThreadID();
+ const bool has_reason = ThreadHasStopReason(thread);
+ // If the focus thread doesn't have a stop reason, clear the thread ID
+ if (tid == g_vsc.focus_tid && !has_reason)
+ g_vsc.focus_tid = LLDB_INVALID_THREAD_ID;
+ if (has_reason) {
+ ++num_threads_with_reason;
+ if (first_tid_with_reason == LLDB_INVALID_THREAD_ID)
+ first_tid_with_reason = tid;
+ }
+ }
+
+ // We will have cleared g_vsc.focus_tid if he focus thread doesn't
+ // have a stop reason, so if it was cleared, or wasn't set, then set the
+ // focus thread to the first thread with a stop reason.
+ if (g_vsc.focus_tid == LLDB_INVALID_THREAD_ID)
+ g_vsc.focus_tid = first_tid_with_reason;
+
+ // If no threads stopped with a reason, then report the first one so
+ // we at least let the UI know we stopped.
+ if (num_threads_with_reason == 0) {
+ lldb::SBThread thread = process.GetThreadAtIndex(0);
+ g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
+ } else {
+ for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
+ lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
+ g_vsc.thread_ids.insert(thread.GetThreadID());
+ if (ThreadHasStopReason(thread)) {
+ g_vsc.SendJSON(CreateThreadStopped(thread, stop_id));
+ }
+ }
+ }
+
+ for (auto tid : old_thread_ids) {
+ auto end = g_vsc.thread_ids.end();
+ auto pos = g_vsc.thread_ids.find(tid);
+ if (pos == end)
+ SendThreadExitedEvent(tid);
+ }
+ } else {
+ if (g_vsc.log)
+ *g_vsc.log << "error: SendThreadStoppedEvent() when process"
+ " isn't stopped ("
+ << lldb::SBDebugger::StateAsCString(state) << ')'
+ << std::endl;
+ }
+ } else {
+ if (g_vsc.log)
+ *g_vsc.log << "error: SendThreadStoppedEvent() invalid process"
+ << std::endl;
+ }
+ g_vsc.RunStopCommands();
+}
+
+//----------------------------------------------------------------------
+// "ProcessEvent": {
+// "allOf": [
+// { "$ref": "#/definitions/Event" },
+// {
+// "type": "object",
+// "description": "Event message for 'process' event type. The event
+// indicates that the debugger has begun debugging a
+// new process. Either one that it has launched, or one
+// that it has attached to.",
+// "properties": {
+// "event": {
+// "type": "string",
+// "enum": [ "process" ]
+// },
+// "body": {
+// "type": "object",
+// "properties": {
+// "name": {
+// "type": "string",
+// "description": "The logical name of the process. This is
+// usually the full path to process's executable
+// file. Example: /home/myproj/program.js."
+// },
+// "systemProcessId": {
+// "type": "integer",
+// "description": "The system process id of the debugged process.
+// This property will be missing for non-system
+// processes."
+// },
+// "isLocalProcess": {
+// "type": "boolean",
+// "description": "If true, the process is running on the same
+// computer as the debug adapter."
+// },
+// "startMethod": {
+// "type": "string",
+// "enum": [ "launch", "attach", "attachForSuspendedLaunch" ],
+// "description": "Describes how the debug engine started
+// debugging this process.",
+// "enumDescriptions": [
+// "Process was launched under the debugger.",
+// "Debugger attached to an existing process.",
+// "A project launcher component has launched a new process in
+// a suspended state and then asked the debugger to attach."
+// ]
+// }
+// },
+// "required": [ "name" ]
+// }
+// },
+// "required": [ "event", "body" ]
+// }
+// ]
+// }
+//----------------------------------------------------------------------
+void SendProcessEvent(LaunchMethod launch_method) {
+ lldb::SBFileSpec exe_fspec = g_vsc.target.GetExecutable();
+ char exe_path[PATH_MAX];
+ exe_fspec.GetPath(exe_path, sizeof(exe_path));
+ llvm::json::Object event(CreateEventObject("process"));
+ llvm::json::Object body;
+ EmplaceSafeString(body, "name", std::string(exe_path));
+ const auto pid = g_vsc.target.GetProcess().GetProcessID();
+ body.try_emplace("systemProcessId", (int64_t)pid);
+ body.try_emplace("isLocalProcess", true);
+ const char *startMethod = nullptr;
+ switch (launch_method) {
+ case Launch:
+ startMethod = "launch";
+ break;
+ case Attach:
+ startMethod = "attach";
+ break;
+ case AttachForSuspendedLaunch:
+ startMethod = "attachForSuspendedLaunch";
+ break;
+ }
+ body.try_emplace("startMethod", startMethod);
+ event.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(event)));
+}
+
+//----------------------------------------------------------------------
+// Grab any STDOUT and STDERR from the process and send it up to VS Code
+// via an "output" event to the "stdout" and "stderr" categories.
+//----------------------------------------------------------------------
+void SendStdOutStdErr(lldb::SBProcess &process) {
+ char buffer[1024];
+ size_t count;
+ while ((count = process.GetSTDOUT(buffer, sizeof(buffer))) > 0)
+ g_vsc.SendOutput(OutputType::Stdout, llvm::StringRef(buffer, count));
+ while ((count = process.GetSTDERR(buffer, sizeof(buffer))) > 0)
+ g_vsc.SendOutput(OutputType::Stderr, llvm::StringRef(buffer, count));
+}
+
+//----------------------------------------------------------------------
+// All events from the debugger, target, process, thread and frames are
+// received in this function that runs in its own thread. We are using a
+// "FILE *" to output packets back to VS Code and they have mutexes in them
+// them prevent multiple threads from writing simultaneously so no locking
+// is required.
+//----------------------------------------------------------------------
+void EventThreadFunction() {
+ lldb::SBEvent event;
+ lldb::SBListener listener = g_vsc.debugger.GetListener();
+ bool done = false;
+ while (!done) {
+ if (listener.WaitForEvent(1, event)) {
+ const auto event_mask = event.GetType();
+ if (lldb::SBProcess::EventIsProcessEvent(event)) {
+ lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(event);
+ if (event_mask & lldb::SBProcess::eBroadcastBitStateChanged) {
+ auto state = lldb::SBProcess::GetStateFromEvent(event);
+ switch (state) {
+ case lldb::eStateInvalid:
+ // Not a state event
+ break;
+ case lldb::eStateUnloaded:
+ break;
+ case lldb::eStateConnected:
+ break;
+ case lldb::eStateAttaching:
+ break;
+ case lldb::eStateLaunching:
+ break;
+ case lldb::eStateStepping:
+ break;
+ case lldb::eStateCrashed:
+ break;
+ case lldb::eStateDetached:
+ break;
+ case lldb::eStateSuspended:
+ break;
+ case lldb::eStateStopped:
+ // Only report a stopped event if the process was not restarted.
+ if (!lldb::SBProcess::GetRestartedFromEvent(event)) {
+ SendStdOutStdErr(process);
+ SendThreadStoppedEvent();
+ }
+ break;
+ case lldb::eStateRunning:
+ break;
+ case lldb::eStateExited: {
+ // Run any exit LLDB commands the user specified in the
+ // launch.json
+ g_vsc.RunExitCommands();
+ SendProcessExitedEvent(process);
+ SendTerminatedEvent();
+ done = true;
+ } break;
+ }
+ } else if ((event_mask & lldb::SBProcess::eBroadcastBitSTDOUT) ||
+ (event_mask & lldb::SBProcess::eBroadcastBitSTDERR)) {
+ SendStdOutStdErr(process);
+ }
+ } else if (lldb::SBBreakpoint::EventIsBreakpointEvent(event)) {
+ if (event_mask & lldb::SBTarget::eBroadcastBitBreakpointChanged) {
+ auto event_type =
+ lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(event);
+ const auto num_locs =
+ lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(event);
+ auto bp = lldb::SBBreakpoint::GetBreakpointFromEvent(event);
+ bool added = event_type & lldb::eBreakpointEventTypeLocationsAdded;
+ bool removed =
+ event_type & lldb::eBreakpointEventTypeLocationsRemoved;
+ if (added || removed) {
+ for (size_t i = 0; i < num_locs; ++i) {
+ auto bp_loc =
+ lldb::SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(
+ event, i);
+ auto bp_event = CreateEventObject("breakpoint");
+ llvm::json::Object body;
+ body.try_emplace("breakpoint", CreateBreakpoint(bp_loc));
+ if (added)
+ body.try_emplace("reason", "new");
+ else
+ body.try_emplace("reason", "removed");
+ bp_event.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(bp_event)));
+ }
+ }
+ }
+ } else if (event.BroadcasterMatchesRef(g_vsc.broadcaster)) {
+ if (event_mask & eBroadcastBitStopEventThread) {
+ done = true;
+ }
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+// Both attach and launch take a either a sourcePath or sourceMap
+// argument (or neither), from which we need to set the target.source-map.
+//----------------------------------------------------------------------
+void SetSourceMapFromArguments(const llvm::json::Object &arguments) {
+ const char *sourceMapHelp =
+ "source must be be an array of two-element arrays, "
+ "each containing a source and replacement path string.\n";
+
+ std::string sourceMapCommand;
+ llvm::raw_string_ostream strm(sourceMapCommand);
+ strm << "settings set target.source-map ";
+ auto sourcePath = GetString(arguments, "sourcePath");
+
+ // sourceMap is the new, more general form of sourcePath and overrides it.
+ auto sourceMap = arguments.getArray("sourceMap");
+ if (sourceMap) {
+ for (const auto &value : *sourceMap) {
+ auto mapping = value.getAsArray();
+ if (mapping == nullptr || mapping->size() != 2 ||
+ (*mapping)[0].kind() != llvm::json::Value::String ||
+ (*mapping)[1].kind() != llvm::json::Value::String) {
+ g_vsc.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
+ return;
+ }
+ auto mapFrom = GetAsString((*mapping)[0]);
+ auto mapTo = GetAsString((*mapping)[1]);
+ strm << "\"" << mapFrom << "\" \"" << mapTo << "\"";
+ }
+ } else {
+ if (ObjectContainsKey(arguments, "sourceMap")) {
+ g_vsc.SendOutput(OutputType::Console, llvm::StringRef(sourceMapHelp));
+ return;
+ }
+ if (sourcePath.empty())
+ return;
+ // Do any source remapping needed before we create our targets
+ strm << "\".\" \"" << sourcePath << "\"";
+ }
+ strm.flush();
+ if (!sourceMapCommand.empty()) {
+ g_vsc.RunLLDBCommands("Setting source map:", {sourceMapCommand});
+ }
+}
+
+//----------------------------------------------------------------------
+// "AttachRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Attach request; value of command field is 'attach'.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "attach" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/AttachRequestArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "AttachRequestArguments": {
+// "type": "object",
+// "description": "Arguments for 'attach' request.\nThe attach request has no
+// standardized attributes."
+// },
+// "AttachResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'attach' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_attach(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ lldb::SBError error;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ const lldb::pid_t pid =
+ GetUnsigned(arguments, "pid", LLDB_INVALID_PROCESS_ID);
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ g_vsc.attach_info.SetProcessID(pid);
+ const auto wait_for = GetBoolean(arguments, "waitFor", false);
+ g_vsc.attach_info.SetWaitForLaunch(wait_for, false /*async*/);
+ g_vsc.init_commands = GetStrings(arguments, "initCommands");
+ g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
+ g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
+ g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
+ auto attachCommands = GetStrings(arguments, "attachCommands");
+ g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
+ const auto debuggerRoot = GetString(arguments, "debuggerRoot");
+
+ // This is a hack for loading DWARF in .o files on Mac where the .o files
+ // in the debug map of the main executable have relative paths which require
+ // the lldb-vscode binary to have its working directory set to that relative
+ // root for the .o files in order to be able to load debug info.
+ if (!debuggerRoot.empty()) {
+ llvm::sys::fs::set_current_path(debuggerRoot.data());
+ }
+
+ // Run any initialize LLDB commands the user specified in the launch.json
+ g_vsc.RunInitCommands();
+
+ // Grab the name of the program we need to debug and set it as the first
+ // argument that will be passed to the program we will debug.
+ const auto program = GetString(arguments, "program");
+ if (!program.empty()) {
+ lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
+
+ g_vsc.launch_info.SetExecutableFile(program_fspec,
+ false /*add_as_first_arg*/);
+ const char *target_triple = nullptr;
+ const char *uuid_cstr = nullptr;
+ // Stand alone debug info file if different from executable
+ const char *symfile = nullptr;
+ g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
+ if (error.Fail()) {
+ response.try_emplace("success", false);
+ EmplaceSafeString(response, "message", std::string(error.GetCString()));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+ return;
+ }
+ }
+
+ const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
+ g_vsc.launch_info.SetDetachOnError(detatchOnError);
+
+ // Run any pre run LLDB commands the user specified in the launch.json
+ g_vsc.RunPreRunCommands();
+
+ if (pid == LLDB_INVALID_PROCESS_ID && wait_for) {
+ char attach_info[256];
+ auto attach_info_len =
+ snprintf(attach_info, sizeof(attach_info),
+ "Waiting to attach to \"%s\"...", program.data());
+ g_vsc.SendOutput(OutputType::Console, llvm::StringRef(attach_info,
+ attach_info_len));
+ }
+ if (attachCommands.empty()) {
+ // No "attachCommands", just attach normally.
+ // Disable async events so the attach will be successful when we return from
+ // the launch call and the launch will happen synchronously
+ g_vsc.debugger.SetAsync(false);
+ g_vsc.target.Attach(g_vsc.attach_info, error);
+ // Reenable async events
+ g_vsc.debugger.SetAsync(true);
+ } else {
+ // We have "attachCommands" that are a set of commands that are expected
+ // to execute the commands after which a process should be created. If there
+ // is no valid process after running these commands, we have failed.
+ g_vsc.RunLLDBCommands("Running attachCommands:", attachCommands);
+ // The custom commands might have created a new target so we should use the
+ // selected target after these commands are run.
+ g_vsc.target = g_vsc.debugger.GetSelectedTarget();
+ }
+
+ SetSourceMapFromArguments(*arguments);
+
+ if (error.Success()) {
+ auto attached_pid = g_vsc.target.GetProcess().GetProcessID();
+ if (attached_pid == LLDB_INVALID_PROCESS_ID) {
+ if (attachCommands.empty())
+ error.SetErrorString("failed to attach to a process");
+ else
+ error.SetErrorString("attachCommands failed to attach to a process");
+ }
+ }
+
+ if (error.Fail()) {
+ response.try_emplace("success", false);
+ EmplaceSafeString(response, "message", std::string(error.GetCString()));
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+ if (error.Success()) {
+ SendProcessEvent(Attach);
+ g_vsc.SendJSON(CreateEventObject("initialized"));
+ // SendThreadStoppedEvent();
+ }
+}
+
+//----------------------------------------------------------------------
+// "ContinueRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Continue request; value of command field is 'continue'.
+// The request starts the debuggee to run again.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "continue" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/ContinueArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "ContinueArguments": {
+// "type": "object",
+// "description": "Arguments for 'continue' request.",
+// "properties": {
+// "threadId": {
+// "type": "integer",
+// "description": "Continue execution for the specified thread (if
+// possible). If the backend cannot continue on a single
+// thread but will continue on all threads, it should
+// set the allThreadsContinued attribute in the response
+// to true."
+// }
+// },
+// "required": [ "threadId" ]
+// },
+// "ContinueResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'continue' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "allThreadsContinued": {
+// "type": "boolean",
+// "description": "If true, the continue request has ignored the
+// specified thread and continued all threads
+// instead. If this attribute is missing a value
+// of 'true' is assumed for backward
+// compatibility."
+// }
+// }
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_continue(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ lldb::SBProcess process = g_vsc.target.GetProcess();
+ auto arguments = request.getObject("arguments");
+ // Remember the thread ID that caused the resume so we can set the
+ // "threadCausedFocus" boolean value in the "stopped" events.
+ g_vsc.focus_tid = GetUnsigned(arguments, "threadId", LLDB_INVALID_THREAD_ID);
+ lldb::SBError error = process.Continue();
+ llvm::json::Object body;
+ body.try_emplace("allThreadsContinued", true);
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "ConfigurationDoneRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "ConfigurationDone request; value of command field
+// is 'configurationDone'.\nThe client of the debug protocol must
+// send this request at the end of the sequence of configuration
+// requests (which was started by the InitializedEvent).",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "configurationDone" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/ConfigurationDoneArguments"
+// }
+// },
+// "required": [ "command" ]
+// }]
+// },
+// "ConfigurationDoneArguments": {
+// "type": "object",
+// "description": "Arguments for 'configurationDone' request.\nThe
+// configurationDone request has no standardized attributes."
+// },
+// "ConfigurationDoneResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'configurationDone' request. This is
+// just an acknowledgement, so no body field is required."
+// }]
+// },
+//----------------------------------------------------------------------
+void request_configurationDone(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+ if (g_vsc.stop_at_entry)
+ SendThreadStoppedEvent();
+ else
+ g_vsc.target.GetProcess().Continue();
+}
+
+//----------------------------------------------------------------------
+// "DisconnectRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Disconnect request; value of command field is
+// 'disconnect'.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "disconnect" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/DisconnectArguments"
+// }
+// },
+// "required": [ "command" ]
+// }]
+// },
+// "DisconnectArguments": {
+// "type": "object",
+// "description": "Arguments for 'disconnect' request.",
+// "properties": {
+// "terminateDebuggee": {
+// "type": "boolean",
+// "description": "Indicates whether the debuggee should be terminated
+// when the debugger is disconnected. If unspecified,
+// the debug adapter is free to do whatever it thinks
+// is best. A client can only rely on this attribute
+// being properly honored if a debug adapter returns
+// true for the 'supportTerminateDebuggee' capability."
+// },
+// "restart": {
+// "type": "boolean",
+// "description": "Indicates whether the debuggee should be restart
+// the process."
+// }
+// }
+// },
+// "DisconnectResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'disconnect' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_disconnect(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+
+ bool terminateDebuggee = GetBoolean(arguments, "terminateDebuggee", false);
+ lldb::SBProcess process = g_vsc.target.GetProcess();
+ auto state = process.GetState();
+
+ switch (state) {
+ case lldb::eStateInvalid:
+ case lldb::eStateUnloaded:
+ case lldb::eStateDetached:
+ case lldb::eStateExited:
+ break;
+ case lldb::eStateConnected:
+ case lldb::eStateAttaching:
+ case lldb::eStateLaunching:
+ case lldb::eStateStepping:
+ case lldb::eStateCrashed:
+ case lldb::eStateSuspended:
+ case lldb::eStateStopped:
+ case lldb::eStateRunning:
+ g_vsc.debugger.SetAsync(false);
+ if (terminateDebuggee)
+ process.Kill();
+ else
+ process.Detach();
+ g_vsc.debugger.SetAsync(true);
+ break;
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+ SendTerminatedEvent();
+ if (g_vsc.event_thread.joinable()) {
+ g_vsc.broadcaster.BroadcastEventByType(eBroadcastBitStopEventThread);
+ g_vsc.event_thread.join();
+ }
+}
+
+void request_exceptionInfo(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ llvm::json::Object body;
+ lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
+ if (thread.IsValid()) {
+ auto stopReason = thread.GetStopReason();
+ if (stopReason == lldb::eStopReasonSignal)
+ body.try_emplace("exceptionId", "signal");
+ else if (stopReason == lldb::eStopReasonBreakpoint) {
+ ExceptionBreakpoint *exc_bp = g_vsc.GetExceptionBPFromStopReason(thread);
+ if (exc_bp) {
+ EmplaceSafeString(body, "exceptionId", exc_bp->filter);
+ EmplaceSafeString(body, "description", exc_bp->label);
+ } else {
+ body.try_emplace("exceptionId", "exception");
+ }
+ } else {
+ body.try_emplace("exceptionId", "exception");
+ }
+ if (!ObjectContainsKey(body, "description")) {
+ char description[1024];
+ if (thread.GetStopDescription(description, sizeof(description))) {
+ EmplaceSafeString(body, "description", std::string(description));
+ }
+ }
+ body.try_emplace("breakMode", "always");
+ // auto excInfoCount = thread.GetStopReasonDataCount();
+ // for (auto i=0; i<excInfoCount; ++i) {
+ // uint64_t exc_data = thread.GetStopReasonDataAtIndex(i);
+ // }
+ } else {
+ response.try_emplace("success", false);
+ }
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "EvaluateRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Evaluate request; value of command field is 'evaluate'.
+// Evaluates the given expression in the context of the
+// top most stack frame. The expression has access to any
+// variables and arguments that are in scope.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "evaluate" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/EvaluateArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "EvaluateArguments": {
+// "type": "object",
+// "description": "Arguments for 'evaluate' request.",
+// "properties": {
+// "expression": {
+// "type": "string",
+// "description": "The expression to evaluate."
+// },
+// "frameId": {
+// "type": "integer",
+// "description": "Evaluate the expression in the scope of this stack
+// frame. If not specified, the expression is evaluated
+// in the global scope."
+// },
+// "context": {
+// "type": "string",
+// "_enum": [ "watch", "repl", "hover" ],
+// "enumDescriptions": [
+// "evaluate is run in a watch.",
+// "evaluate is run from REPL console.",
+// "evaluate is run from a data hover."
+// ],
+// "description": "The context in which the evaluate request is run."
+// },
+// "format": {
+// "$ref": "#/definitions/ValueFormat",
+// "description": "Specifies details on how to format the Evaluate
+// result."
+// }
+// },
+// "required": [ "expression" ]
+// },
+// "EvaluateResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'evaluate' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "result": {
+// "type": "string",
+// "description": "The result of the evaluate request."
+// },
+// "type": {
+// "type": "string",
+// "description": "The optional type of the evaluate result."
+// },
+// "presentationHint": {
+// "$ref": "#/definitions/VariablePresentationHint",
+// "description": "Properties of a evaluate result that can be
+// used to determine how to render the result in
+// the UI."
+// },
+// "variablesReference": {
+// "type": "number",
+// "description": "If variablesReference is > 0, the evaluate
+// result is structured and its children can be
+// retrieved by passing variablesReference to the
+// VariablesRequest."
+// },
+// "namedVariables": {
+// "type": "number",
+// "description": "The number of named child variables. The
+// client can use this optional information to
+// present the variables in a paged UI and fetch
+// them in chunks."
+// },
+// "indexedVariables": {
+// "type": "number",
+// "description": "The number of indexed child variables. The
+// client can use this optional information to
+// present the variables in a paged UI and fetch
+// them in chunks."
+// }
+// },
+// "required": [ "result", "variablesReference" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_evaluate(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Object body;
+ auto arguments = request.getObject("arguments");
+ lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
+ const auto expression = GetString(arguments, "expression");
+
+ if (!expression.empty() && expression[0] == '`') {
+ auto result = RunLLDBCommands(llvm::StringRef(),
+ {expression.substr(1)});
+ EmplaceSafeString(body, "result", result);
+ body.try_emplace("variablesReference", (int64_t)0);
+ } else {
+ // Always try to get the answer from the local variables if possible. If
+ // this fails, then actually evaluate an expression using the expression
+ // parser. "frame variable" is more reliable than the expression parser in
+ // many cases and it is faster.
+ lldb::SBValue value = frame.GetValueForVariablePath(
+ expression.data(), lldb::eDynamicDontRunTarget);
+ if (value.GetError().Fail())
+ value = frame.EvaluateExpression(expression.data());
+ if (value.GetError().Fail()) {
+ response.try_emplace("success", false);
+ const char *error_cstr = value.GetError().GetCString();
+ if (error_cstr && error_cstr[0])
+ EmplaceSafeString(response, "message", std::string(error_cstr));
+ else
+ EmplaceSafeString(response, "message", "evaluate failed");
+ } else {
+ SetValueForKey(value, body, "result");
+ auto value_typename = value.GetType().GetDisplayTypeName();
+ EmplaceSafeString(body, "type", value_typename ? value_typename : NO_TYPENAME);
+ if (value.MightHaveChildren()) {
+ auto variablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
+ g_vsc.variables.Append(value);
+ body.try_emplace("variablesReference", variablesReference);
+ } else {
+ body.try_emplace("variablesReference", (int64_t)0);
+ }
+ }
+ }
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "InitializeRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Initialize request; value of command field is
+// 'initialize'.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "initialize" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/InitializeRequestArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "InitializeRequestArguments": {
+// "type": "object",
+// "description": "Arguments for 'initialize' request.",
+// "properties": {
+// "clientID": {
+// "type": "string",
+// "description": "The ID of the (frontend) client using this adapter."
+// },
+// "adapterID": {
+// "type": "string",
+// "description": "The ID of the debug adapter."
+// },
+// "locale": {
+// "type": "string",
+// "description": "The ISO-639 locale of the (frontend) client using
+// this adapter, e.g. en-US or de-CH."
+// },
+// "linesStartAt1": {
+// "type": "boolean",
+// "description": "If true all line numbers are 1-based (default)."
+// },
+// "columnsStartAt1": {
+// "type": "boolean",
+// "description": "If true all column numbers are 1-based (default)."
+// },
+// "pathFormat": {
+// "type": "string",
+// "_enum": [ "path", "uri" ],
+// "description": "Determines in what format paths are specified. The
+// default is 'path', which is the native format."
+// },
+// "supportsVariableType": {
+// "type": "boolean",
+// "description": "Client supports the optional type attribute for
+// variables."
+// },
+// "supportsVariablePaging": {
+// "type": "boolean",
+// "description": "Client supports the paging of variables."
+// },
+// "supportsRunInTerminalRequest": {
+// "type": "boolean",
+// "description": "Client supports the runInTerminal request."
+// }
+// },
+// "required": [ "adapterID" ]
+// },
+// "InitializeResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'initialize' request.",
+// "properties": {
+// "body": {
+// "$ref": "#/definitions/Capabilities",
+// "description": "The capabilities of this debug adapter."
+// }
+// }
+// }]
+// }
+//----------------------------------------------------------------------
+void request_initialize(const llvm::json::Object &request) {
+ g_vsc.debugger = lldb::SBDebugger::Create(true /*source_init_files*/);
+ // Create an empty target right away since we might get breakpoint requests
+ // before we are given an executable to launch in a "launch" request, or a
+ // executable when attaching to a process by process ID in a "attach"
+ // request.
+ FILE *out = fopen(dev_null_path, "w");
+ if (out) {
+ // Set the output and error file handles to redirect into nothing otherwise
+ // if any code in LLDB prints to the debugger file handles, the output and
+ // error file handles are initialized to STDOUT and STDERR and any output
+ // will kill our debug session.
+ g_vsc.debugger.SetOutputFileHandle(out, true);
+ g_vsc.debugger.SetErrorFileHandle(out, false);
+ }
+
+ g_vsc.target = g_vsc.debugger.CreateTarget(nullptr);
+ lldb::SBListener listener = g_vsc.debugger.GetListener();
+ listener.StartListeningForEvents(
+ g_vsc.target.GetBroadcaster(),
+ lldb::SBTarget::eBroadcastBitBreakpointChanged);
+ listener.StartListeningForEvents(g_vsc.broadcaster,
+ eBroadcastBitStopEventThread);
+ // Start our event thread so we can receive events from the debugger, target,
+ // process and more.
+ g_vsc.event_thread = std::thread(EventThreadFunction);
+
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Object body;
+ // The debug adapter supports the configurationDoneRequest.
+ body.try_emplace("supportsConfigurationDoneRequest", true);
+ // The debug adapter supports function breakpoints.
+ body.try_emplace("supportsFunctionBreakpoints", true);
+ // The debug adapter supports conditional breakpoints.
+ body.try_emplace("supportsConditionalBreakpoints", true);
+ // The debug adapter supports breakpoints that break execution after a
+ // specified number of hits.
+ body.try_emplace("supportsHitConditionalBreakpoints", true);
+ // The debug adapter supports a (side effect free) evaluate request for
+ // data hovers.
+ body.try_emplace("supportsEvaluateForHovers", true);
+ // Available filters or options for the setExceptionBreakpoints request.
+ llvm::json::Array filters;
+ for (const auto &exc_bp : g_vsc.exception_breakpoints) {
+ filters.emplace_back(CreateExceptionBreakpointFilter(exc_bp));
+ }
+ body.try_emplace("exceptionBreakpointFilters", std::move(filters));
+ // The debug adapter supports stepping back via the stepBack and
+ // reverseContinue requests.
+ body.try_emplace("supportsStepBack", false);
+ // The debug adapter supports setting a variable to a value.
+ body.try_emplace("supportsSetVariable", true);
+ // The debug adapter supports restarting a frame.
+ body.try_emplace("supportsRestartFrame", false);
+ // The debug adapter supports the gotoTargetsRequest.
+ body.try_emplace("supportsGotoTargetsRequest", false);
+ // The debug adapter supports the stepInTargetsRequest.
+ body.try_emplace("supportsStepInTargetsRequest", false);
+ // The debug adapter supports the completionsRequest.
+ body.try_emplace("supportsCompletionsRequest", false);
+ // The debug adapter supports the modules request.
+ body.try_emplace("supportsModulesRequest", false);
+ // The set of additional module information exposed by the debug adapter.
+ // body.try_emplace("additionalModuleColumns"] = ColumnDescriptor
+ // Checksum algorithms supported by the debug adapter.
+ // body.try_emplace("supportedChecksumAlgorithms"] = ChecksumAlgorithm
+ // The debug adapter supports the RestartRequest. In this case a client
+ // should not implement 'restart' by terminating and relaunching the adapter
+ // but by calling the RestartRequest.
+ body.try_emplace("supportsRestartRequest", false);
+ // The debug adapter supports 'exceptionOptions' on the
+ // setExceptionBreakpoints request.
+ body.try_emplace("supportsExceptionOptions", true);
+ // The debug adapter supports a 'format' attribute on the stackTraceRequest,
+ // variablesRequest, and evaluateRequest.
+ body.try_emplace("supportsValueFormattingOptions", true);
+ // The debug adapter supports the exceptionInfo request.
+ body.try_emplace("supportsExceptionInfoRequest", true);
+ // The debug adapter supports the 'terminateDebuggee' attribute on the
+ // 'disconnect' request.
+ body.try_emplace("supportTerminateDebuggee", true);
+ // The debug adapter supports the delayed loading of parts of the stack,
+ // which requires that both the 'startFrame' and 'levels' arguments and the
+ // 'totalFrames' result of the 'StackTrace' request are supported.
+ body.try_emplace("supportsDelayedStackTraceLoading", true);
+ // The debug adapter supports the 'loadedSources' request.
+ body.try_emplace("supportsLoadedSourcesRequest", false);
+
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "LaunchRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Launch request; value of command field is 'launch'.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "launch" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/LaunchRequestArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "LaunchRequestArguments": {
+// "type": "object",
+// "description": "Arguments for 'launch' request.",
+// "properties": {
+// "noDebug": {
+// "type": "boolean",
+// "description": "If noDebug is true the launch request should launch
+// the program without enabling debugging."
+// }
+// }
+// },
+// "LaunchResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'launch' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_launch(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ lldb::SBError error;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ g_vsc.init_commands = GetStrings(arguments, "initCommands");
+ g_vsc.pre_run_commands = GetStrings(arguments, "preRunCommands");
+ g_vsc.stop_commands = GetStrings(arguments, "stopCommands");
+ g_vsc.exit_commands = GetStrings(arguments, "exitCommands");
+ g_vsc.stop_at_entry = GetBoolean(arguments, "stopOnEntry", false);
+ const auto debuggerRoot = GetString(arguments, "debuggerRoot");
+
+ // This is a hack for loading DWARF in .o files on Mac where the .o files
+ // in the debug map of the main executable have relative paths which require
+ // the lldb-vscode binary to have its working directory set to that relative
+ // root for the .o files in order to be able to load debug info.
+ if (!debuggerRoot.empty()) {
+ llvm::sys::fs::set_current_path(debuggerRoot.data());
+ }
+
+ SetSourceMapFromArguments(*arguments);
+
+ // Run any initialize LLDB commands the user specified in the launch.json
+ g_vsc.RunInitCommands();
+
+ // Grab the current working directory if there is one and set it in the
+ // launch info.
+ const auto cwd = GetString(arguments, "cwd");
+ if (!cwd.empty())
+ g_vsc.launch_info.SetWorkingDirectory(cwd.data());
+
+ // Grab the name of the program we need to debug and set it as the first
+ // argument that will be passed to the program we will debug.
+ const auto program = GetString(arguments, "program");
+ if (!program.empty()) {
+ lldb::SBFileSpec program_fspec(program.data(), true /*resolve_path*/);
+
+ g_vsc.launch_info.SetExecutableFile(program_fspec,
+ true /*add_as_first_arg*/);
+ const char *target_triple = nullptr;
+ const char *uuid_cstr = nullptr;
+ // Stand alone debug info file if different from executable
+ const char *symfile = nullptr;
+ g_vsc.target.AddModule(program.data(), target_triple, uuid_cstr, symfile);
+ if (error.Fail()) {
+ response.try_emplace("success", false);
+ EmplaceSafeString(response, "message", std::string(error.GetCString()));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+ }
+ }
+
+ // Extract any extra arguments and append them to our program arguments for
+ // when we launch
+ auto args = GetStrings(arguments, "args");
+ if (!args.empty())
+ g_vsc.launch_info.SetArguments(MakeArgv(args).data(), true);
+
+ // Pass any environment variables along that the user specified.
+ auto envs = GetStrings(arguments, "env");
+ if (!envs.empty())
+ g_vsc.launch_info.SetEnvironmentEntries(MakeArgv(envs).data(), true);
+
+ auto flags = g_vsc.launch_info.GetLaunchFlags();
+
+ if (GetBoolean(arguments, "disableASLR", true))
+ flags |= lldb::eLaunchFlagDisableASLR;
+ if (GetBoolean(arguments, "disableSTDIO", false))
+ flags |= lldb::eLaunchFlagDisableSTDIO;
+ if (GetBoolean(arguments, "shellExpandArguments", false))
+ flags |= lldb::eLaunchFlagShellExpandArguments;
+ const bool detatchOnError = GetBoolean(arguments, "detachOnError", false);
+ g_vsc.launch_info.SetDetachOnError(detatchOnError);
+ g_vsc.launch_info.SetLaunchFlags(flags | lldb::eLaunchFlagDebug |
+ lldb::eLaunchFlagStopAtEntry);
+
+ // Run any pre run LLDB commands the user specified in the launch.json
+ g_vsc.RunPreRunCommands();
+
+ // Disable async events so the launch will be successful when we return from
+ // the launch call and the launch will happen synchronously
+ g_vsc.debugger.SetAsync(false);
+ g_vsc.target.Launch(g_vsc.launch_info, error);
+ if (error.Fail()) {
+ response.try_emplace("success", false);
+ EmplaceSafeString(response, "message", std::string(error.GetCString()));
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+
+ SendProcessEvent(Launch);
+ g_vsc.SendJSON(llvm::json::Value(CreateEventObject("initialized")));
+ // Reenable async events and start the event thread to catch async events.
+ g_vsc.debugger.SetAsync(true);
+}
+
+//----------------------------------------------------------------------
+// "NextRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Next request; value of command field is 'next'. The
+// request starts the debuggee to run again for one step.
+// The debug adapter first sends the NextResponse and then
+// a StoppedEvent (event type 'step') after the step has
+// completed.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "next" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/NextArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "NextArguments": {
+// "type": "object",
+// "description": "Arguments for 'next' request.",
+// "properties": {
+// "threadId": {
+// "type": "integer",
+// "description": "Execute 'next' for this thread."
+// }
+// },
+// "required": [ "threadId" ]
+// },
+// "NextResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'next' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_next(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
+ if (thread.IsValid()) {
+ // Remember the thread ID that caused the resume so we can set the
+ // "threadCausedFocus" boolean value in the "stopped" events.
+ g_vsc.focus_tid = thread.GetThreadID();
+ thread.StepOver();
+ } else {
+ response.try_emplace("success", false);
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "PauseRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Pause request; value of command field is 'pause'. The
+// request suspenses the debuggee. The debug adapter first sends the
+// PauseResponse and then a StoppedEvent (event type 'pause') after the
+// thread has been paused successfully.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "pause" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/PauseArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "PauseArguments": {
+// "type": "object",
+// "description": "Arguments for 'pause' request.",
+// "properties": {
+// "threadId": {
+// "type": "integer",
+// "description": "Pause execution for this thread."
+// }
+// },
+// "required": [ "threadId" ]
+// },
+// "PauseResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'pause' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_pause(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ lldb::SBProcess process = g_vsc.target.GetProcess();
+ lldb::SBError error = process.Stop();
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "ScopesRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Scopes request; value of command field is 'scopes'. The
+// request returns the variable scopes for a given stackframe ID.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "scopes" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/ScopesArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "ScopesArguments": {
+// "type": "object",
+// "description": "Arguments for 'scopes' request.",
+// "properties": {
+// "frameId": {
+// "type": "integer",
+// "description": "Retrieve the scopes for this stackframe."
+// }
+// },
+// "required": [ "frameId" ]
+// },
+// "ScopesResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'scopes' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "scopes": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Scope"
+// },
+// "description": "The scopes of the stackframe. If the array has
+// length zero, there are no scopes available."
+// }
+// },
+// "required": [ "scopes" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_scopes(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Object body;
+ auto arguments = request.getObject("arguments");
+ lldb::SBFrame frame = g_vsc.GetLLDBFrame(*arguments);
+ g_vsc.variables.Clear();
+ g_vsc.variables.Append(frame.GetVariables(true, // arguments
+ true, // locals
+ false, // statics
+ true)); // in_scope_only
+ g_vsc.num_locals = g_vsc.variables.GetSize();
+ g_vsc.variables.Append(frame.GetVariables(false, // arguments
+ false, // locals
+ true, // statics
+ true)); // in_scope_only
+ g_vsc.num_globals = g_vsc.variables.GetSize() - (g_vsc.num_locals);
+ g_vsc.variables.Append(frame.GetRegisters());
+ g_vsc.num_regs =
+ g_vsc.variables.GetSize() - (g_vsc.num_locals + g_vsc.num_globals);
+ body.try_emplace("scopes", g_vsc.CreateTopLevelScopes());
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "SetBreakpointsRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "SetBreakpoints request; value of command field is
+// 'setBreakpoints'. Sets multiple breakpoints for a single source and
+// clears all previous breakpoints in that source. To clear all breakpoint
+// for a source, specify an empty array. When a breakpoint is hit, a
+// StoppedEvent (event type 'breakpoint') is generated.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "setBreakpoints" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/SetBreakpointsArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "SetBreakpointsArguments": {
+// "type": "object",
+// "description": "Arguments for 'setBreakpoints' request.",
+// "properties": {
+// "source": {
+// "$ref": "#/definitions/Source",
+// "description": "The source location of the breakpoints; either
+// source.path or source.reference must be specified."
+// },
+// "breakpoints": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/SourceBreakpoint"
+// },
+// "description": "The code locations of the breakpoints."
+// },
+// "lines": {
+// "type": "array",
+// "items": {
+// "type": "integer"
+// },
+// "description": "Deprecated: The code locations of the breakpoints."
+// },
+// "sourceModified": {
+// "type": "boolean",
+// "description": "A value of true indicates that the underlying source
+// has been modified which results in new breakpoint locations."
+// }
+// },
+// "required": [ "source" ]
+// },
+// "SetBreakpointsResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'setBreakpoints' request. Returned is
+// information about each breakpoint created by this request. This includes
+// the actual code location and whether the breakpoint could be verified.
+// The breakpoints returned are in the same order as the elements of the
+// 'breakpoints' (or the deprecated 'lines') in the
+// SetBreakpointsArguments.", "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "breakpoints": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Breakpoint"
+// },
+// "description": "Information about the breakpoints. The array
+// elements are in the same order as the elements of the
+// 'breakpoints' (or the deprecated 'lines') in the
+// SetBreakpointsArguments."
+// }
+// },
+// "required": [ "breakpoints" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// },
+// "SourceBreakpoint": {
+// "type": "object",
+// "description": "Properties of a breakpoint or logpoint passed to the
+// setBreakpoints request.", "properties": {
+// "line": {
+// "type": "integer",
+// "description": "The source line of the breakpoint or logpoint."
+// },
+// "column": {
+// "type": "integer",
+// "description": "An optional source column of the breakpoint."
+// },
+// "condition": {
+// "type": "string",
+// "description": "An optional expression for conditional breakpoints."
+// },
+// "hitCondition": {
+// "type": "string",
+// "description": "An optional expression that controls how many hits of
+// the breakpoint are ignored. The backend is expected to interpret the
+// expression as needed."
+// },
+// "logMessage": {
+// "type": "string",
+// "description": "If this attribute exists and is non-empty, the backend
+// must not 'break' (stop) but log the message instead. Expressions within
+// {} are interpolated."
+// }
+// },
+// "required": [ "line" ]
+// }
+//----------------------------------------------------------------------
+void request_setBreakpoints(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ lldb::SBError error;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ auto source = arguments->getObject("source");
+ const auto path = GetString(source, "path");
+ auto breakpoints = arguments->getArray("breakpoints");
+ llvm::json::Array response_breakpoints;
+ // Decode the source breakpoint infos for this "setBreakpoints" request
+ SourceBreakpointMap request_bps;
+ for (const auto &bp : *breakpoints) {
+ auto bp_obj = bp.getAsObject();
+ if (bp_obj) {
+ SourceBreakpoint src_bp(*bp_obj);
+ request_bps[src_bp.line] = std::move(src_bp);
+ }
+ }
+
+ // See if we already have breakpoints set for this source file from a
+ // previous "setBreakpoints" request
+ auto old_src_bp_pos = g_vsc.source_breakpoints.find(path);
+ if (old_src_bp_pos != g_vsc.source_breakpoints.end()) {
+
+ // We have already set breakpoints in this source file and they are giving
+ // use a new list of lines to set breakpoints on. Some breakpoints might
+ // already be set, and some might not. We need to remove any breakpoints
+ // whose lines are not contained in the any breakpoints lines in in the
+ // "breakpoints" array.
+
+ // Delete any breakpoints in this source file that aren't in the
+ // request_bps set. There is no call to remove breakpoints other than
+ // calling this function with a smaller or empty "breakpoints" list.
+ std::vector<uint32_t> remove_lines;
+ for (auto &pair: old_src_bp_pos->second) {
+ auto request_pos = request_bps.find(pair.first);
+ if (request_pos == request_bps.end()) {
+ // This breakpoint no longer exists in this source file, delete it
+ g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
+ remove_lines.push_back(pair.first);
+ } else {
+ pair.second.UpdateBreakpoint(request_pos->second);
+ // Remove this breakpoint from the request breakpoints since we have
+ // handled it here and we don't need to set a new breakpoint below.
+ request_bps.erase(request_pos);
+ // Add this breakpoint info to the response
+ AppendBreakpoint(pair.second.bp, response_breakpoints);
+ }
+ }
+ // Remove any lines from this existing source breakpoint map
+ for (auto line: remove_lines)
+ old_src_bp_pos->second.erase(line);
+
+ // Now add any breakpoint infos left over in request_bps are the
+ // breakpoints that weren't set in this source file yet. We need to update
+ // thread source breakpoint info for the source file in the variable
+ // "old_src_bp_pos->second" so the info for this source file is up to date.
+ for (auto &pair : request_bps) {
+ pair.second.SetBreakpoint(path.data());
+ // Add this breakpoint info to the response
+ AppendBreakpoint(pair.second.bp, response_breakpoints);
+ old_src_bp_pos->second[pair.first] = std::move(pair.second);
+ }
+ } else {
+ // No breakpoints were set for this source file yet. Set all breakpoints
+ // for each line and add them to the response and create an entry in
+ // g_vsc.source_breakpoints for this source file.
+ for (auto &pair : request_bps) {
+ pair.second.SetBreakpoint(path.data());
+ // Add this breakpoint info to the response
+ AppendBreakpoint(pair.second.bp, response_breakpoints);
+ }
+ g_vsc.source_breakpoints[path] = std::move(request_bps);
+ }
+
+ llvm::json::Object body;
+ body.try_emplace("breakpoints", std::move(response_breakpoints));
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "SetExceptionBreakpointsRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "SetExceptionBreakpoints request; value of command field
+// is 'setExceptionBreakpoints'. The request configures the debuggers
+// response to thrown exceptions. If an exception is configured to break, a
+// StoppedEvent is fired (event type 'exception').", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "setExceptionBreakpoints" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/SetExceptionBreakpointsArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "SetExceptionBreakpointsArguments": {
+// "type": "object",
+// "description": "Arguments for 'setExceptionBreakpoints' request.",
+// "properties": {
+// "filters": {
+// "type": "array",
+// "items": {
+// "type": "string"
+// },
+// "description": "IDs of checked exception options. The set of IDs is
+// returned via the 'exceptionBreakpointFilters' capability."
+// },
+// "exceptionOptions": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/ExceptionOptions"
+// },
+// "description": "Configuration options for selected exceptions."
+// }
+// },
+// "required": [ "filters" ]
+// },
+// "SetExceptionBreakpointsResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'setExceptionBreakpoints' request. This is
+// just an acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_setExceptionBreakpoints(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ lldb::SBError error;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ auto filters = arguments->getArray("filters");
+ // Keep a list of any exception breakpoint filter names that weren't set
+ // so we can clear any exception breakpoints if needed.
+ std::set<std::string> unset_filters;
+ for (const auto &bp : g_vsc.exception_breakpoints)
+ unset_filters.insert(bp.filter);
+
+ for (const auto &value : *filters) {
+ const auto filter = GetAsString(value);
+ auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
+ if (exc_bp) {
+ exc_bp->SetBreakpoint();
+ unset_filters.erase(filter);
+ }
+ }
+ for (const auto &filter : unset_filters) {
+ auto exc_bp = g_vsc.GetExceptionBreakpoint(filter);
+ if (exc_bp)
+ exc_bp->ClearBreakpoint();
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "SetFunctionBreakpointsRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "SetFunctionBreakpoints request; value of command field is
+// 'setFunctionBreakpoints'. Sets multiple function breakpoints and clears
+// all previous function breakpoints. To clear all function breakpoint,
+// specify an empty array. When a function breakpoint is hit, a StoppedEvent
+// (event type 'function breakpoint') is generated.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "setFunctionBreakpoints" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/SetFunctionBreakpointsArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "SetFunctionBreakpointsArguments": {
+// "type": "object",
+// "description": "Arguments for 'setFunctionBreakpoints' request.",
+// "properties": {
+// "breakpoints": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/FunctionBreakpoint"
+// },
+// "description": "The function names of the breakpoints."
+// }
+// },
+// "required": [ "breakpoints" ]
+// },
+// "FunctionBreakpoint": {
+// "type": "object",
+// "description": "Properties of a breakpoint passed to the
+// setFunctionBreakpoints request.", "properties": {
+// "name": {
+// "type": "string",
+// "description": "The name of the function."
+// },
+// "condition": {
+// "type": "string",
+// "description": "An optional expression for conditional breakpoints."
+// },
+// "hitCondition": {
+// "type": "string",
+// "description": "An optional expression that controls how many hits of
+// the breakpoint are ignored. The backend is expected to interpret the
+// expression as needed."
+// }
+// },
+// "required": [ "name" ]
+// },
+// "SetFunctionBreakpointsResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'setFunctionBreakpoints' request. Returned is
+// information about each breakpoint created by this request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "breakpoints": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Breakpoint"
+// },
+// "description": "Information about the breakpoints. The array
+// elements correspond to the elements of the 'breakpoints' array."
+// }
+// },
+// "required": [ "breakpoints" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_setFunctionBreakpoints(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ lldb::SBError error;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ auto breakpoints = arguments->getArray("breakpoints");
+ FunctionBreakpointMap request_bps;
+ llvm::json::Array response_breakpoints;
+ for (const auto &value : *breakpoints) {
+ auto bp_obj = value.getAsObject();
+ if (bp_obj == nullptr)
+ continue;
+ FunctionBreakpoint func_bp(*bp_obj);
+ request_bps[func_bp.functionName] = std::move(func_bp);
+ }
+
+ std::vector<llvm::StringRef> remove_names;
+ // Disable any function breakpoints that aren't in the request_bps.
+ // There is no call to remove function breakpoints other than calling this
+ // function with a smaller or empty "breakpoints" list.
+ for (auto &pair: g_vsc.function_breakpoints) {
+ auto request_pos = request_bps.find(pair.first());
+ if (request_pos == request_bps.end()) {
+ // This function breakpoint no longer exists delete it from LLDB
+ g_vsc.target.BreakpointDelete(pair.second.bp.GetID());
+ remove_names.push_back(pair.first());
+ } else {
+ // Update the existing breakpoint as any setting withing the function
+ // breakpoint might have changed.
+ pair.second.UpdateBreakpoint(request_pos->second);
+ // Remove this breakpoint from the request breakpoints since we have
+ // handled it here and we don't need to set a new breakpoint below.
+ request_bps.erase(request_pos);
+ // Add this breakpoint info to the response
+ AppendBreakpoint(pair.second.bp, response_breakpoints);
+ }
+ }
+ // Remove any breakpoints that are no longer in our list
+ for (const auto &name: remove_names)
+ g_vsc.function_breakpoints.erase(name);
+
+ // Any breakpoints that are left in "request_bps" are breakpoints that
+ // need to be set.
+ for (auto &pair : request_bps) {
+ pair.second.SetBreakpoint();
+ // Add this breakpoint info to the response
+ AppendBreakpoint(pair.second.bp, response_breakpoints);
+ g_vsc.function_breakpoints[pair.first()] = std::move(pair.second);
+ }
+
+ llvm::json::Object body;
+ body.try_emplace("breakpoints", std::move(response_breakpoints));
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "SourceRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Source request; value of command field is 'source'. The
+// request retrieves the source code for a given source reference.",
+// "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "source" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/SourceArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "SourceArguments": {
+// "type": "object",
+// "description": "Arguments for 'source' request.",
+// "properties": {
+// "source": {
+// "$ref": "#/definitions/Source",
+// "description": "Specifies the source content to load. Either
+// source.path or source.sourceReference must be specified."
+// },
+// "sourceReference": {
+// "type": "integer",
+// "description": "The reference to the source. This is the same as
+// source.sourceReference. This is provided for backward compatibility
+// since old backends do not understand the 'source' attribute."
+// }
+// },
+// "required": [ "sourceReference" ]
+// },
+// "SourceResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'source' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "content": {
+// "type": "string",
+// "description": "Content of the source reference."
+// },
+// "mimeType": {
+// "type": "string",
+// "description": "Optional content type (mime type) of the source."
+// }
+// },
+// "required": [ "content" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_source(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Object body;
+
+ auto arguments = request.getObject("arguments");
+ auto source = arguments->getObject("source");
+ auto sourceReference = GetSigned(source, "sourceReference", -1);
+ auto pos = g_vsc.source_map.find((lldb::addr_t)sourceReference);
+ if (pos != g_vsc.source_map.end()) {
+ EmplaceSafeString(body, "content", pos->second.content);
+ } else {
+ response.try_emplace("success", false);
+ }
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "StackTraceRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "StackTrace request; value of command field is
+// 'stackTrace'. The request returns a stacktrace from the current execution
+// state.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "stackTrace" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/StackTraceArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "StackTraceArguments": {
+// "type": "object",
+// "description": "Arguments for 'stackTrace' request.",
+// "properties": {
+// "threadId": {
+// "type": "integer",
+// "description": "Retrieve the stacktrace for this thread."
+// },
+// "startFrame": {
+// "type": "integer",
+// "description": "The index of the first frame to return; if omitted
+// frames start at 0."
+// },
+// "levels": {
+// "type": "integer",
+// "description": "The maximum number of frames to return. If levels is
+// not specified or 0, all frames are returned."
+// },
+// "format": {
+// "$ref": "#/definitions/StackFrameFormat",
+// "description": "Specifies details on how to format the stack frames."
+// }
+// },
+// "required": [ "threadId" ]
+// },
+// "StackTraceResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'stackTrace' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "stackFrames": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/StackFrame"
+// },
+// "description": "The frames of the stackframe. If the array has
+// length zero, there are no stackframes available. This means that
+// there is no location information available."
+// },
+// "totalFrames": {
+// "type": "integer",
+// "description": "The total number of frames available."
+// }
+// },
+// "required": [ "stackFrames" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_stackTrace(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ lldb::SBError error;
+ auto arguments = request.getObject("arguments");
+ lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
+ llvm::json::Array stackFrames;
+ llvm::json::Object body;
+
+ if (thread.IsValid()) {
+ const auto startFrame = GetUnsigned(arguments, "startFrame", 0);
+ const auto levels = GetUnsigned(arguments, "levels", 0);
+ const auto endFrame = (levels == 0) ? INT64_MAX : (startFrame + levels);
+ for (uint32_t i = startFrame; i < endFrame; ++i) {
+ auto frame = thread.GetFrameAtIndex(i);
+ if (!frame.IsValid())
+ break;
+ stackFrames.emplace_back(CreateStackFrame(frame));
+ }
+ }
+ body.try_emplace("stackFrames", std::move(stackFrames));
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "StepInRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "StepIn request; value of command field is 'stepIn'. The
+// request starts the debuggee to step into a function/method if possible.
+// If it cannot step into a target, 'stepIn' behaves like 'next'. The debug
+// adapter first sends the StepInResponse and then a StoppedEvent (event
+// type 'step') after the step has completed. If there are multiple
+// function/method calls (or other targets) on the source line, the optional
+// argument 'targetId' can be used to control into which target the 'stepIn'
+// should occur. The list of possible targets for a given source line can be
+// retrieved via the 'stepInTargets' request.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "stepIn" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/StepInArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "StepInArguments": {
+// "type": "object",
+// "description": "Arguments for 'stepIn' request.",
+// "properties": {
+// "threadId": {
+// "type": "integer",
+// "description": "Execute 'stepIn' for this thread."
+// },
+// "targetId": {
+// "type": "integer",
+// "description": "Optional id of the target to step into."
+// }
+// },
+// "required": [ "threadId" ]
+// },
+// "StepInResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'stepIn' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_stepIn(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
+ if (thread.IsValid()) {
+ // Remember the thread ID that caused the resume so we can set the
+ // "threadCausedFocus" boolean value in the "stopped" events.
+ g_vsc.focus_tid = thread.GetThreadID();
+ thread.StepInto();
+ } else {
+ response.try_emplace("success", false);
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "StepOutRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "StepOut request; value of command field is 'stepOut'. The
+// request starts the debuggee to run again for one step. The debug adapter
+// first sends the StepOutResponse and then a StoppedEvent (event type
+// 'step') after the step has completed.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "stepOut" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/StepOutArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "StepOutArguments": {
+// "type": "object",
+// "description": "Arguments for 'stepOut' request.",
+// "properties": {
+// "threadId": {
+// "type": "integer",
+// "description": "Execute 'stepOut' for this thread."
+// }
+// },
+// "required": [ "threadId" ]
+// },
+// "StepOutResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'stepOut' request. This is just an
+// acknowledgement, so no body field is required."
+// }]
+// }
+//----------------------------------------------------------------------
+void request_stepOut(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ auto arguments = request.getObject("arguments");
+ lldb::SBThread thread = g_vsc.GetLLDBThread(*arguments);
+ if (thread.IsValid()) {
+ // Remember the thread ID that caused the resume so we can set the
+ // "threadCausedFocus" boolean value in the "stopped" events.
+ g_vsc.focus_tid = thread.GetThreadID();
+ thread.StepOut();
+ } else {
+ response.try_emplace("success", false);
+ }
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "ThreadsRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Thread request; value of command field is 'threads'. The
+// request retrieves a list of all threads.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "threads" ]
+// }
+// },
+// "required": [ "command" ]
+// }]
+// },
+// "ThreadsResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'threads' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "threads": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Thread"
+// },
+// "description": "All threads."
+// }
+// },
+// "required": [ "threads" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_threads(const llvm::json::Object &request) {
+
+ lldb::SBProcess process = g_vsc.target.GetProcess();
+ llvm::json::Object response;
+ FillResponse(request, response);
+
+ const uint32_t num_threads = process.GetNumThreads();
+ llvm::json::Array threads;
+ for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
+ lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
+ threads.emplace_back(CreateThread(thread));
+ }
+ if (threads.size() == 0) {
+ response.try_emplace("success", false);
+ }
+ llvm::json::Object body;
+ body.try_emplace("threads", std::move(threads));
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "SetVariableRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "setVariable request; value of command field is
+// 'setVariable'. Set the variable with the given name in the variable
+// container to a new value.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "setVariable" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/SetVariableArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "SetVariableArguments": {
+// "type": "object",
+// "description": "Arguments for 'setVariable' request.",
+// "properties": {
+// "variablesReference": {
+// "type": "integer",
+// "description": "The reference of the variable container."
+// },
+// "name": {
+// "type": "string",
+// "description": "The name of the variable."
+// },
+// "value": {
+// "type": "string",
+// "description": "The value of the variable."
+// },
+// "format": {
+// "$ref": "#/definitions/ValueFormat",
+// "description": "Specifies details on how to format the response value."
+// }
+// },
+// "required": [ "variablesReference", "name", "value" ]
+// },
+// "SetVariableResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'setVariable' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "value": {
+// "type": "string",
+// "description": "The new value of the variable."
+// },
+// "type": {
+// "type": "string",
+// "description": "The type of the new value. Typically shown in the
+// UI when hovering over the value."
+// },
+// "variablesReference": {
+// "type": "number",
+// "description": "If variablesReference is > 0, the new value is
+// structured and its children can be retrieved by passing
+// variablesReference to the VariablesRequest."
+// },
+// "namedVariables": {
+// "type": "number",
+// "description": "The number of named child variables. The client
+// can use this optional information to present the variables in a
+// paged UI and fetch them in chunks."
+// },
+// "indexedVariables": {
+// "type": "number",
+// "description": "The number of indexed child variables. The client
+// can use this optional information to present the variables in a
+// paged UI and fetch them in chunks."
+// }
+// },
+// "required": [ "value" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_setVariable(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Array variables;
+ llvm::json::Object body;
+ auto arguments = request.getObject("arguments");
+ // This is a reference to the containing variable/scope
+ const auto variablesReference =
+ GetUnsigned(arguments, "variablesReference", 0);
+ const auto name = GetString(arguments, "name");
+ const auto value = GetString(arguments, "value");
+ // Set success to false just in case we don't find the variable by name
+ response.try_emplace("success", false);
+
+ lldb::SBValue variable;
+ int64_t newVariablesReference = 0;
+
+ // The "id" is the unique integer ID that is unique within the enclosing
+ // variablesReference. It is optionally added to any "interface Variable"
+ // objects to uniquely identify a variable within an enclosing
+ // variablesReference. It helps to disambiguate between two variables that
+ // have the same name within the same scope since the "setVariables" request
+ // only specifies the variable reference of the enclosing scope/variable, and
+ // the name of the variable. We could have two shadowed variables with the
+ // same name in "Locals" or "Globals". In our case the "id" absolute index
+ // of the variable within the g_vsc.variables list.
+ const auto id_value = GetUnsigned(arguments, "id", UINT64_MAX);
+ if (id_value != UINT64_MAX) {
+ variable = g_vsc.variables.GetValueAtIndex(id_value);
+ } else if (VARREF_IS_SCOPE(variablesReference)) {
+ // variablesReference is one of our scopes, not an actual variable it is
+ // asking for a variable in locals or globals or registers
+ int64_t start_idx = 0;
+ int64_t end_idx = 0;
+ switch (variablesReference) {
+ case VARREF_LOCALS:
+ start_idx = 0;
+ end_idx = start_idx + g_vsc.num_locals;
+ break;
+ case VARREF_GLOBALS:
+ start_idx = g_vsc.num_locals;
+ end_idx = start_idx + g_vsc.num_globals;
+ break;
+ case VARREF_REGS:
+ start_idx = g_vsc.num_locals + g_vsc.num_globals;
+ end_idx = start_idx + g_vsc.num_regs;
+ break;
+ default:
+ break;
+ }
+
+ // Find the variable by name in the correct scope and hope we don't have
+ // multiple variables with the same name. We search backwards because
+ // the list of variables has the top most variables first and variables
+ // in deeper scopes are last. This means we will catch the deepest
+ // variable whose name matches which is probably what the user wants.
+ for (int64_t i = end_idx - 1; i >= start_idx; --i) {
+ auto curr_variable = g_vsc.variables.GetValueAtIndex(i);
+ llvm::StringRef variable_name(curr_variable.GetName());
+ if (variable_name == name) {
+ variable = curr_variable;
+ if (curr_variable.MightHaveChildren())
+ newVariablesReference = i;
+ break;
+ }
+ }
+ } else {
+ // We have a named item within an actual variable so we need to find it
+ // withing the container variable by name.
+ const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
+ lldb::SBValue container = g_vsc.variables.GetValueAtIndex(var_idx);
+ variable = container.GetChildMemberWithName(name.data());
+ if (!variable.IsValid()) {
+ if (name.startswith("[")) {
+ llvm::StringRef index_str(name.drop_front(1));
+ uint64_t index = 0;
+ if (!index_str.consumeInteger(0, index)) {
+ if (index_str == "]")
+ variable = container.GetChildAtIndex(index);
+ }
+ }
+ }
+
+ // We don't know the index of the variable in our g_vsc.variables
+ if (variable.IsValid()) {
+ if (variable.MightHaveChildren()) {
+ newVariablesReference = VARIDX_TO_VARREF(g_vsc.variables.GetSize());
+ g_vsc.variables.Append(variable);
+ }
+ }
+ }
+
+ if (variable.IsValid()) {
+ lldb::SBError error;
+ bool success = variable.SetValueFromCString(value.data(), error);
+ if (success) {
+ SetValueForKey(variable, body, "value");
+ EmplaceSafeString(body, "type", variable.GetType().GetDisplayTypeName());
+ body.try_emplace("variablesReference", newVariablesReference);
+ } else {
+ EmplaceSafeString(body, "message", std::string(error.GetCString()));
+ }
+ response.try_emplace("success", success);
+ }
+
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+//----------------------------------------------------------------------
+// "VariablesRequest": {
+// "allOf": [ { "$ref": "#/definitions/Request" }, {
+// "type": "object",
+// "description": "Variables request; value of command field is 'variables'.
+// Retrieves all child variables for the given variable reference. An
+// optional filter can be used to limit the fetched children to either named
+// or indexed children.", "properties": {
+// "command": {
+// "type": "string",
+// "enum": [ "variables" ]
+// },
+// "arguments": {
+// "$ref": "#/definitions/VariablesArguments"
+// }
+// },
+// "required": [ "command", "arguments" ]
+// }]
+// },
+// "VariablesArguments": {
+// "type": "object",
+// "description": "Arguments for 'variables' request.",
+// "properties": {
+// "variablesReference": {
+// "type": "integer",
+// "description": "The Variable reference."
+// },
+// "filter": {
+// "type": "string",
+// "enum": [ "indexed", "named" ],
+// "description": "Optional filter to limit the child variables to either
+// named or indexed. If ommited, both types are fetched."
+// },
+// "start": {
+// "type": "integer",
+// "description": "The index of the first variable to return; if omitted
+// children start at 0."
+// },
+// "count": {
+// "type": "integer",
+// "description": "The number of variables to return. If count is missing
+// or 0, all variables are returned."
+// },
+// "format": {
+// "$ref": "#/definitions/ValueFormat",
+// "description": "Specifies details on how to format the Variable
+// values."
+// }
+// },
+// "required": [ "variablesReference" ]
+// },
+// "VariablesResponse": {
+// "allOf": [ { "$ref": "#/definitions/Response" }, {
+// "type": "object",
+// "description": "Response to 'variables' request.",
+// "properties": {
+// "body": {
+// "type": "object",
+// "properties": {
+// "variables": {
+// "type": "array",
+// "items": {
+// "$ref": "#/definitions/Variable"
+// },
+// "description": "All (or a range) of variables for the given
+// variable reference."
+// }
+// },
+// "required": [ "variables" ]
+// }
+// },
+// "required": [ "body" ]
+// }]
+// }
+//----------------------------------------------------------------------
+void request_variables(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Array variables;
+ auto arguments = request.getObject("arguments");
+ const auto variablesReference =
+ GetUnsigned(arguments, "variablesReference", 0);
+ const int64_t start = GetSigned(arguments, "start", 0);
+ const int64_t count = GetSigned(arguments, "count", 0);
+ bool hex = false;
+ auto format = arguments->getObject("format");
+ if (format)
+ hex = GetBoolean(format, "hex", false);
+
+ if (VARREF_IS_SCOPE(variablesReference)) {
+ // variablesReference is one of our scopes, not an actual variable it is
+ // asking for the list of args, locals or globals.
+ int64_t start_idx = 0;
+ int64_t num_children = 0;
+ switch (variablesReference) {
+ case VARREF_LOCALS:
+ start_idx = start;
+ num_children = g_vsc.num_locals;
+ break;
+ case VARREF_GLOBALS:
+ start_idx = start + g_vsc.num_locals + start;
+ num_children = g_vsc.num_globals;
+ break;
+ case VARREF_REGS:
+ start_idx = start + g_vsc.num_locals + g_vsc.num_globals;
+ num_children = g_vsc.num_regs;
+ break;
+ default:
+ break;
+ }
+ const int64_t end_idx = start_idx + ((count == 0) ? num_children : count);
+ for (auto i = start_idx; i < end_idx; ++i) {
+ lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(i);
+ if (!variable.IsValid())
+ break;
+ variables.emplace_back(
+ CreateVariable(variable, VARIDX_TO_VARREF(i), i, hex));
+ }
+ } else {
+ // We are expanding a variable that has children, so we will return its
+ // children.
+ const int64_t var_idx = VARREF_TO_VARIDX(variablesReference);
+ lldb::SBValue variable = g_vsc.variables.GetValueAtIndex(var_idx);
+ if (variable.IsValid()) {
+ const auto num_children = variable.GetNumChildren();
+ const int64_t end_idx = start + ((count == 0) ? num_children : count);
+ for (auto i = start; i < end_idx; ++i) {
+ lldb::SBValue child = variable.GetChildAtIndex(i);
+ if (!child.IsValid())
+ break;
+ if (child.MightHaveChildren()) {
+ const int64_t var_idx = g_vsc.variables.GetSize();
+ auto childVariablesReferences = VARIDX_TO_VARREF(var_idx);
+ variables.emplace_back(
+ CreateVariable(child, childVariablesReferences, var_idx, hex));
+ g_vsc.variables.Append(child);
+ } else {
+ variables.emplace_back(CreateVariable(child, 0, INT64_MAX, hex));
+ }
+ }
+ }
+ }
+ llvm::json::Object body;
+ body.try_emplace("variables", std::move(variables));
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+// A request used in testing to get the details on all breakpoints that are
+// currently set in the target. This helps us to test "setBreakpoints" and
+// "setFunctionBreakpoints" requests to verify we have the correct set of
+// breakpoints currently set in LLDB.
+void request__testGetTargetBreakpoints(const llvm::json::Object &request) {
+ llvm::json::Object response;
+ FillResponse(request, response);
+ llvm::json::Array response_breakpoints;
+ for (uint32_t i = 0; g_vsc.target.GetBreakpointAtIndex(i).IsValid(); ++i) {
+ auto bp = g_vsc.target.GetBreakpointAtIndex(i);
+ AppendBreakpoint(bp, response_breakpoints);
+ }
+ llvm::json::Object body;
+ body.try_emplace("breakpoints", std::move(response_breakpoints));
+ response.try_emplace("body", std::move(body));
+ g_vsc.SendJSON(llvm::json::Value(std::move(response)));
+}
+
+const std::map<std::string, RequestCallback> &GetRequestHandlers() {
+#define REQUEST_CALLBACK(name) \
+ { #name, request_##name }
+ static std::map<std::string, RequestCallback> g_request_handlers = {
+ // VSCode Debug Adaptor requests
+ REQUEST_CALLBACK(attach),
+ REQUEST_CALLBACK(continue),
+ REQUEST_CALLBACK(configurationDone),
+ REQUEST_CALLBACK(disconnect),
+ REQUEST_CALLBACK(evaluate),
+ REQUEST_CALLBACK(exceptionInfo),
+ REQUEST_CALLBACK(initialize),
+ REQUEST_CALLBACK(launch),
+ REQUEST_CALLBACK(next),
+ REQUEST_CALLBACK(pause),
+ REQUEST_CALLBACK(scopes),
+ REQUEST_CALLBACK(setBreakpoints),
+ REQUEST_CALLBACK(setExceptionBreakpoints),
+ REQUEST_CALLBACK(setFunctionBreakpoints),
+ REQUEST_CALLBACK(setVariable),
+ REQUEST_CALLBACK(source),
+ REQUEST_CALLBACK(stackTrace),
+ REQUEST_CALLBACK(stepIn),
+ REQUEST_CALLBACK(stepOut),
+ REQUEST_CALLBACK(threads),
+ REQUEST_CALLBACK(variables),
+ // Testing requests
+ REQUEST_CALLBACK(_testGetTargetBreakpoints),
+ };
+#undef REQUEST_CALLBACK
+ return g_request_handlers;
+}
+
+} // anonymous namespace
+
+int main(int argc, char *argv[]) {
+
+ // Initialize LLDB first before we do anything.
+ lldb::SBDebugger::Initialize();
+
+ if (argc == 2) {
+ const char *arg = argv[1];
+#if !defined(_WIN32)
+ if (strcmp(arg, "-g") == 0) {
+ printf("Paused waiting for debugger to attach (pid = %i)...\n", getpid());
+ pause();
+ } else {
+#else
+ {
+#endif
+ int portno = atoi(arg);
+ printf("Listening on port %i...\n", portno);
+ int socket_fd = AcceptConnection(portno);
+ if (socket_fd >= 0) {
+ // We must open two FILE objects, one for reading and one for writing
+ // the FILE objects have a mutex in them that won't allow reading and
+ // writing to the socket stream.
+ g_vsc.in = fdopen(socket_fd, "r");
+ g_vsc.out = fdopen(socket_fd, "w");
+ if (g_vsc.in == nullptr || g_vsc.out == nullptr) {
+ if (g_vsc.log)
+ *g_vsc.log << "fdopen failed (" << strerror(errno) << ")"
+ << std::endl;
+ exit(1);
+ }
+ } else {
+ exit(1);
+ }
+ }
+ }
+ auto request_handlers = GetRequestHandlers();
+ uint32_t packet_idx = 0;
+ while (true) {
+ std::string json = g_vsc.ReadJSON();
+ if (json.empty())
+ break;
+
+ llvm::StringRef json_sref(json);
+ llvm::Expected<llvm::json::Value> json_value = llvm::json::parse(json_sref);
+ if (!json_value) {
+ auto error = json_value.takeError();
+ if (g_vsc.log) {
+ std::string error_str;
+ llvm::raw_string_ostream strm(error_str);
+ strm << error;
+ strm.flush();
+
+ *g_vsc.log << "error: failed to parse JSON: " << error_str << std::endl
+ << json << std::endl;
+ }
+ return 1;
+ }
+
+ auto object = json_value->getAsObject();
+ if (!object) {
+ if (g_vsc.log)
+ *g_vsc.log << "error: json packet isn't a object" << std::endl;
+ return 1;
+ }
+
+ const auto packet_type = GetString(object, "type");
+ if (packet_type == "request") {
+ const auto command = GetString(object, "command");
+ auto handler_pos = request_handlers.find(command);
+ if (handler_pos != request_handlers.end()) {
+ handler_pos->second(*object);
+ } else {
+ if (g_vsc.log)
+ *g_vsc.log << "error: unhandled command \"" << command.data() << std::endl;
+ return 1;
+ }
+ }
+ ++packet_idx;
+ }
+
+ // We must terminate the debugger in a thread before the C++ destructor
+ // chain messes everything up.
+ lldb::SBDebugger::Terminate();
+ return 0;
+}
diff --git a/tools/lldb-vscode/package.json b/tools/lldb-vscode/package.json
new file mode 100644
index 000000000000..aa3de65c172f
--- /dev/null
+++ b/tools/lldb-vscode/package.json
@@ -0,0 +1,242 @@
+{
+ "name": "lldb-vscode",
+ "displayName": "LLDB native Debug stub",
+ "version": "0.1.0",
+ "publisher": "llvm.org",
+ "description": "Debug adapter for LLDB which uses a C++ tool to interface directly with LLDB.",
+ "author": {
+ "name": "Greg Clayton",
+ "email": "clayborg@gmail.com"
+ },
+ "license": "LLVM",
+ "keywords": [
+ "multi-root ready"
+ ],
+ "engines": {
+ "vscode": "^1.18.0",
+ "node": "^7.9.0"
+ },
+ "icon": "images/lldb.png",
+ "categories": [
+ "Debuggers"
+ ],
+ "private": true,
+ "devDependencies": {
+ "@types/node": "7.0.43",
+ "@types/mocha": "2.2.45",
+ "typescript": "2.6.2",
+ "mocha": "4.0.1",
+ "vscode": "1.1.10",
+ "vscode-debugadapter-testsupport": "1.25.0",
+ "tslint": "5.8.0",
+ "vsce": "1.35.0"
+ },
+ "contributes": {
+ "debuggers": [
+ {
+ "type": "lldb-vscode",
+ "label": "Native LLDB Debugger",
+ "enableBreakpointsFor": {
+ "languageIds": [
+ "ada",
+ "arm",
+ "asm",
+ "c",
+ "cpp",
+ "crystal",
+ "d",
+ "fortan",
+ "fortran-modern",
+ "nim",
+ "objective-c",
+ "objectpascal",
+ "pascal",
+ "rust",
+ "swift"
+ ]
+ },
+ "program": "./bin/lldb-vscode",
+ "configurationAttributes": {
+ "launch": {
+ "required": [
+ "program"
+ ],
+ "properties": {
+ "program": {
+ "type": "string",
+ "description": "Path to the program to debug."
+ },
+ "args": {
+ "type": [ "array", "string" ],
+ "description": "Program arguments.",
+ "default": []
+ },
+ "cwd": {
+ "type": "string",
+ "description": "Program working directory.",
+ "default": "${workspaceRoot}"
+ },
+ "env": {
+ "type": "array",
+ "description": "Additional environment variables.",
+ "default": []
+ },
+ "stopOnEntry": {
+ "type": "boolean",
+ "description": "Automatically stop after launch.",
+ "default": false
+ },
+ "disableASLR": {
+ "type": "boolean",
+ "description": "Enable or disable Address space layout randomization if the debugger supports it.",
+ "default": true
+ },
+ "disableSTDIO": {
+ "type": "boolean",
+ "description": "Don't retrieve STDIN, STDOUT and STDERR as the program is running.",
+ "default": false
+ },
+ "shellExpandArguments": {
+ "type": "boolean",
+ "description": "Expand program arguments as a shell would without actually launching the program in a shell.",
+ "default": false
+ },
+ "detachOnError": {
+ "type": "boolean",
+ "description": "Detach from the program.",
+ "default": false
+ },
+ "trace": {
+ "type": "boolean",
+ "description": "Enable logging of the Debug Adapter Protocol.",
+ "default": true
+ },
+ "sourcePath": {
+ "type": "string",
+ "description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
+ },
+ "sourceMap": {
+ "type": "array",
+ "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and desination pathname. Overrides sourcePath.",
+ "default": []
+ },
+ "debuggerRoot": {
+ "type": "string",
+ "description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
+ },
+ "initCommands": {
+ "type": "array",
+ "description": "Initialization commands executed upon debugger startup.",
+ "default": []
+ },
+ "preRunCommands": {
+ "type": "array",
+ "description": "Commands executed just before the program is launched.",
+ "default": []
+ },
+ "stopCommands": {
+ "type": "array",
+ "description": "Commands executed each time the program stops.",
+ "default": []
+ },
+ "exitCommands": {
+ "type": "array",
+ "description": "Commands executed at the end of debugging session.",
+ "default": []
+ }
+ }
+ },
+ "attach": {
+ "properties": {
+ "program": {
+ "type": "string",
+ "description": "Path to the program to attach to."
+ },
+ "pid": {
+ "type": [
+ "number",
+ "string"
+ ],
+ "description": "System process ID to attach to."
+ },
+ "waitFor": {
+ "type": "boolean",
+ "description": "If set to true, then wait for the process to launch by looking for a process with a basename that matches `program`. No process ID needs to be specified when using this flag.",
+ "default": true
+ },
+ "trace": {
+ "type": "boolean",
+ "description": "Enable logging of the Debug Adapter Protocol.",
+ "default": true
+ },
+ "sourcePath": {
+ "type": "string",
+ "description": "Specify a source path to remap \"./\" to allow full paths to be used when setting breakpoints in binaries that have relative source paths."
+ },
+ "sourceMap": {
+ "type": "array",
+ "description": "Specify an array of path remappings; each element must itself be a two element array containing a source and desination pathname. Overrides sourcePath.",
+ "default": []
+ },
+ "debuggerRoot": {
+ "type": "string",
+ "description": "Specify a working directory to set the debug adaptor to so relative object files can be located."
+ },
+ "attachCommands": {
+ "type": "array",
+ "description": "Custom commands that are executed instead of attaching to a process ID or to a process by name. These commands may optionally create a new target and must perform an attach. A valid process must exist after these commands complete or the \"attach\" will fail.",
+ "default": []
+ },
+ "initCommands": {
+ "type": "array",
+ "description": "Initialization commands executed upon debugger startup.",
+ "default": []
+ },
+ "preRunCommands": {
+ "type": "array",
+ "description": "Commands executed just before the program is attached to.",
+ "default": []
+ },
+ "stopCommands": {
+ "type": "array",
+ "description": "Commands executed each time the program stops.",
+ "default": []
+ },
+ "exitCommands": {
+ "type": "array",
+ "description": "Commands executed at the end of debugging session.",
+ "default": []
+ }
+ }
+ }
+ },
+ "initialConfigurations": [
+ {
+ "type": "lldb-vscode",
+ "request": "launch",
+ "name": "Debug",
+ "program": "${workspaceRoot}/<your program>",
+ "args": [],
+ "env": [],
+ "cwd": "${workspaceRoot}"
+ }
+ ],
+ "configurationSnippets": [
+ {
+ "label": "LLDB: Launch",
+ "description": "",
+ "body": {
+ "type": "lldb-vscode",
+ "request": "launch",
+ "name": "${2:Launch}",
+ "program": "^\"\\${workspaceRoot}/${1:<your program>}\"",
+ "args": [],
+ "env": [],
+ "cwd": "^\"\\${workspaceRoot}\""
+ }
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt
index 0cb6fdb527ca..1ffae834dfb2 100644
--- a/unittests/CMakeLists.txt
+++ b/unittests/CMakeLists.txt
@@ -60,6 +60,7 @@ endfunction()
add_subdirectory(TestingSupport)
add_subdirectory(Breakpoint)
add_subdirectory(Core)
+add_subdirectory(Disassembler)
add_subdirectory(Editline)
add_subdirectory(Expression)
add_subdirectory(Host)
diff --git a/unittests/Core/CMakeLists.txt b/unittests/Core/CMakeLists.txt
index 4affb8cabca9..374de8cf4a7f 100644
--- a/unittests/Core/CMakeLists.txt
+++ b/unittests/Core/CMakeLists.txt
@@ -1,17 +1,25 @@
add_lldb_unittest(LLDBCoreTests
- BroadcasterTest.cpp
- DataExtractorTest.cpp
- EventTest.cpp
- ListenerTest.cpp
MangledTest.cpp
- ScalarTest.cpp
- StateTest.cpp
+ RangeMapTest.cpp
+ RangeTest.cpp
+ RichManglingContextTest.cpp
StreamCallbackTest.cpp
LINK_LIBS
lldbCore
lldbHost
- LLVMTestingSupport
+ lldbSymbol
+ lldbPluginObjectFileELF
+ lldbPluginSymbolVendorELF
+ lldbUtilityHelpers
LINK_COMPONENTS
Support
)
+
+add_dependencies(LLDBCoreTests yaml2obj)
+add_definitions(-DYAML2OBJ="$<TARGET_FILE:yaml2obj>")
+
+set(test_inputs
+ mangled-function-names.yaml
+ )
+add_unittest_inputs(LLDBCoreTests "${test_inputs}")
diff --git a/unittests/Core/Inputs/mangled-function-names.yaml b/unittests/Core/Inputs/mangled-function-names.yaml
new file mode 100644
index 000000000000..56fc9bdc3627
--- /dev/null
+++ b/unittests/Core/Inputs/mangled-function-names.yaml
@@ -0,0 +1,116 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000010
+ Content: 554889E58B0425A80000005DC30F1F00
+ - Name: .anothertext
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0000000000000010
+ AddressAlign: 0x0000000000000010
+ Content: 554889E54883EC20488D0425A8000000C745FC00000000488945F0488B45F08B08894DECE8C7FFFFFF8B4DEC01C189C84883C4205D746573742073747200C3
+ - Name: .eh_frame
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0000000000000050
+ AddressAlign: 0x0000000000000008
+ Content: 1400000000000000017A5200017810011B0C0708900100001C0000001C00000090FFFFFF0D00000000410E108602430D06000000000000001C0000003C00000080FFFFFF3F00000000410E108602430D0600000000000000
+ - Name: .data
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x00000000000000A8
+ AddressAlign: 0x0000000000000004
+ Content: '01000000'
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 5562756E747520636C616E672076657273696F6E20332E352D317562756E74753120287472756E6B2920286261736564206F6E204C4C564D20332E352900
+Symbols:
+ Local:
+ - Type: STT_SECTION
+ Section: .text
+ - Type: STT_SECTION
+ Section: .anothertext
+ Value: 0x0000000000000010
+ - Type: STT_SECTION
+ Section: .eh_frame
+ Value: 0x0000000000000050
+ - Type: STT_SECTION
+ Section: .data
+ Value: 0x00000000000000A8
+ - Type: STT_SECTION
+ Section: .comment
+ - Name: /tmp/a.c
+ Type: STT_FILE
+ - Type: STT_FILE
+ Global:
+ - Name: somedata
+ Type: STT_OBJECT
+ Section: .anothertext
+ Value: 0x0000000000000045
+ - Name: main
+ Type: STT_FUNC
+ Section: .anothertext
+ Value: 0x0000000000000010
+ Size: 0x000000000000003F
+ - Name: _Z3foov
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: puts@GLIBC_2.5
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: puts@GLIBC_2.6
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _Z5annotv@VERSION3
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _ZN1AC2Ev
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _ZN1AD2Ev
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _ZN1A3barEv
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _ZGVZN4llvm4dbgsEvE7thestrm
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _ZZN4llvm4dbgsEvE7thestrm
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _ZTVN5clang4DeclE
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: -[ObjCfoo]
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: +[B ObjCbar(WithCategory)]
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+ - Name: _Z12undemangableEvx42
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x000000000000000D
+...
diff --git a/unittests/Core/MangledTest.cpp b/unittests/Core/MangledTest.cpp
index 7deb901f5601..2fb37b57ffe1 100644
--- a/unittests/Core/MangledTest.cpp
+++ b/unittests/Core/MangledTest.cpp
@@ -7,9 +7,22 @@
//
//===----------------------------------------------------------------------===//
-#include "gtest/gtest.h"
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
+#include "TestingSupport/TestUtilities.h"
#include "lldb/Core/Mangled.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+#include "llvm/Support/FileUtilities.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+
+#include "gtest/gtest.h"
using namespace lldb;
using namespace lldb_private;
@@ -36,3 +49,125 @@ TEST(MangledTest, EmptyForInvalidName) {
EXPECT_STREQ("", TheDemangled.GetCString());
}
+
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ llvm::SmallString<128> MessageStorage; \
+ llvm::raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ } else { \
+ }
+
+TEST(MangledTest, NameIndexes_FindFunctionSymbols) {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ ObjectFileELF::Initialize();
+ SymbolVendorELF::Initialize();
+
+ std::string Yaml = GetInputFilePath("mangled-function-names.yaml");
+ llvm::SmallString<128> Obj;
+ ASSERT_NO_ERROR(llvm::sys::fs::createTemporaryFile(
+ "mangled-function-names-%%%%%%", "obj", Obj));
+
+ llvm::FileRemover Deleter(Obj);
+ llvm::StringRef Args[] = {YAML2OBJ, Yaml};
+ llvm::StringRef ObjRef = Obj;
+ const llvm::Optional<llvm::StringRef> redirects[] = {llvm::None, ObjRef,
+ llvm::None};
+ ASSERT_EQ(0,
+ llvm::sys::ExecuteAndWait(YAML2OBJ, Args, llvm::None, redirects));
+ uint64_t Size;
+ ASSERT_NO_ERROR(llvm::sys::fs::file_size(Obj, Size));
+ ASSERT_GT(Size, 0u);
+
+ ModuleSpec Spec{FileSpec(Obj)};
+ Spec.GetSymbolFileSpec().SetFile(Obj, FileSpec::Style::native);
+ auto M = std::make_shared<Module>(Spec);
+
+ auto Count = [M](const char *Name, FunctionNameType Type) -> int {
+ SymbolContextList SymList;
+ return M->FindFunctionSymbols(ConstString(Name), Type, SymList);
+ };
+
+ // Unmangled
+ EXPECT_EQ(1, Count("main", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("main", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("main", eFunctionNameTypeMethod));
+
+ // Itanium mangled
+ EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_Z3foov", eFunctionNameTypeBase));
+ EXPECT_EQ(1, Count("foo", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("foo", eFunctionNameTypeMethod));
+
+ // Unmangled with linker annotation
+ EXPECT_EQ(1, Count("puts@GLIBC_2.5", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("puts@GLIBC_2.6", eFunctionNameTypeFull));
+ EXPECT_EQ(2, Count("puts", eFunctionNameTypeFull));
+ EXPECT_EQ(2, Count("puts", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("puts", eFunctionNameTypeMethod));
+
+ // Itanium mangled with linker annotation
+ EXPECT_EQ(1, Count("_Z5annotv@VERSION3", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_Z5annotv", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("annot", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("annot", eFunctionNameTypeMethod));
+
+ // Itanium mangled ctor A::A()
+ EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_ZN1AC2Ev", eFunctionNameTypeBase));
+ EXPECT_EQ(1, Count("A", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("A", eFunctionNameTypeBase));
+
+ // Itanium mangled dtor A::~A()
+ EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_ZN1AD2Ev", eFunctionNameTypeBase));
+ EXPECT_EQ(1, Count("~A", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("~A", eFunctionNameTypeBase));
+
+ // Itanium mangled method A::bar()
+ EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_ZN1A3barEv", eFunctionNameTypeBase));
+ EXPECT_EQ(1, Count("bar", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("bar", eFunctionNameTypeBase));
+
+ // Itanium mangled names that are explicitly excluded from parsing
+ EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_ZGVZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
+ EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_ZZN4llvm4dbgsEvE7thestrm", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("dbgs", eFunctionNameTypeBase));
+ EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_ZTVN5clang4DeclE", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("Decl", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("Decl", eFunctionNameTypeBase));
+
+ // ObjC mangled static
+ EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("-[ObjCfoo]", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("ObjCfoo", eFunctionNameTypeMethod));
+
+ // ObjC mangled method with category
+ EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("+[B ObjCbar(WithCategory)]", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("ObjCbar", eFunctionNameTypeMethod));
+
+ // Invalid things: unable to decode but still possible to find by full name
+ EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeFull));
+ EXPECT_EQ(1, Count("_Z12undemangableEvx42", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("_Z12undemangableEvx42", eFunctionNameTypeMethod));
+ EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeBase));
+ EXPECT_EQ(0, Count("undemangable", eFunctionNameTypeMethod));
+
+ SymbolVendorELF::Terminate();
+ ObjectFileELF::Terminate();
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+}
diff --git a/unittests/Core/RangeMapTest.cpp b/unittests/Core/RangeMapTest.cpp
new file mode 100644
index 000000000000..55167311b0c1
--- /dev/null
+++ b/unittests/Core/RangeMapTest.cpp
@@ -0,0 +1,55 @@
+//===-- RangeTest.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/RangeMap.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+using RangeDataVectorT = RangeDataVector<uint32_t, uint32_t, uint32_t>;
+using EntryT = RangeDataVectorT::Entry;
+
+static testing::Matcher<const EntryT *> EntryIs(uint32_t ID) {
+ return testing::Pointee(testing::Field(&EntryT::data, ID));
+}
+
+TEST(RangeDataVector, FindEntryThatContains) {
+ RangeDataVectorT Map;
+ uint32_t NextID = 0;
+ Map.Append(EntryT(0, 10, NextID++));
+ Map.Append(EntryT(10, 10, NextID++));
+ Map.Append(EntryT(20, 10, NextID++));
+ Map.Sort();
+
+ EXPECT_THAT(Map.FindEntryThatContains(0), EntryIs(0));
+ EXPECT_THAT(Map.FindEntryThatContains(9), EntryIs(0));
+ EXPECT_THAT(Map.FindEntryThatContains(10), EntryIs(1));
+ EXPECT_THAT(Map.FindEntryThatContains(19), EntryIs(1));
+ EXPECT_THAT(Map.FindEntryThatContains(20), EntryIs(2));
+ EXPECT_THAT(Map.FindEntryThatContains(29), EntryIs(2));
+ EXPECT_THAT(Map.FindEntryThatContains(30), nullptr);
+}
+
+TEST(RangeDataVector, FindEntryThatContains_Overlap) {
+ RangeDataVectorT Map;
+ uint32_t NextID = 0;
+ Map.Append(EntryT(0, 40, NextID++));
+ Map.Append(EntryT(10, 20, NextID++));
+ Map.Append(EntryT(20, 10, NextID++));
+ Map.Sort();
+
+ // With overlapping intervals, the intention seems to be to return the first
+ // interval which contains the address.
+ EXPECT_THAT(Map.FindEntryThatContains(25), EntryIs(0));
+
+ // However, this does not always succeed.
+ // TODO: This should probably return the range (0, 40) as well.
+ EXPECT_THAT(Map.FindEntryThatContains(35), nullptr);
+}
diff --git a/unittests/Core/RangeTest.cpp b/unittests/Core/RangeTest.cpp
new file mode 100644
index 000000000000..337c2fa11515
--- /dev/null
+++ b/unittests/Core/RangeTest.cpp
@@ -0,0 +1,330 @@
+//===-- RangeTest.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/RangeMap.h"
+
+#include <cstdint>
+#include <type_traits>
+
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+TEST(RangeTest, SizeTypes) {
+ Range<lldb::addr_t, uint32_t> r;
+ static_assert(std::is_same<lldb::addr_t, decltype(r.GetRangeBase())>::value,
+ "RangeBase type is not equal to the given one.");
+ static_assert(std::is_same<lldb::addr_t, decltype(r.GetRangeEnd())>::value,
+ "RangeEnd type is not equal to the given one.");
+ static_assert(std::is_same<uint32_t, decltype(r.GetByteSize())>::value,
+ "Size type is not equal to the given one.");
+}
+
+typedef Range<lldb::addr_t, uint32_t> RangeT;
+
+TEST(RangeTest, DefaultConstructor) {
+ RangeT r;
+ EXPECT_FALSE(r.IsValid());
+ EXPECT_EQ(0U, r.GetByteSize());
+ EXPECT_EQ(0U, r.GetRangeBase());
+ EXPECT_EQ(0U, r.GetRangeEnd());
+}
+
+TEST(RangeTest, Constructor) {
+ RangeT r(3, 5);
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(5U, r.GetByteSize());
+ EXPECT_EQ(3U, r.GetRangeBase());
+ EXPECT_EQ(8U, r.GetRangeEnd());
+}
+
+TEST(RangeTest, Copy) {
+ RangeT orig(3, 5);
+ RangeT r = orig;
+ EXPECT_TRUE(r.IsValid());
+ EXPECT_EQ(5U, r.GetByteSize());
+ EXPECT_EQ(3U, r.GetRangeBase());
+ EXPECT_EQ(8U, r.GetRangeEnd());
+}
+
+TEST(RangeTest, Clear) {
+ RangeT r(3, 5);
+ r.Clear();
+ EXPECT_TRUE(r == RangeT());
+}
+
+TEST(RangeTest, ClearWithStarAddress) {
+ RangeT r(3, 5);
+ r.Clear(4);
+ EXPECT_TRUE(r == RangeT(4, 0));
+}
+
+TEST(RangeTest, SetRangeBase) {
+ RangeT r(3, 5);
+ r.SetRangeBase(6);
+ EXPECT_EQ(6U, r.GetRangeBase());
+ EXPECT_EQ(11U, r.GetRangeEnd());
+ EXPECT_EQ(5U, r.GetByteSize());
+}
+
+TEST(RangeTest, Slide) {
+ RangeT r(3, 5);
+ r.Slide(1);
+ EXPECT_EQ(4U, r.GetRangeBase());
+ EXPECT_EQ(9U, r.GetRangeEnd());
+ EXPECT_EQ(5U, r.GetByteSize());
+
+ r.Slide(2);
+ EXPECT_EQ(6U, r.GetRangeBase());
+ EXPECT_EQ(11U, r.GetRangeEnd());
+ EXPECT_EQ(5U, r.GetByteSize());
+}
+
+TEST(RangeTest, SlideZero) {
+ RangeT r(3, 5);
+ r.Slide(0);
+ EXPECT_EQ(3U, r.GetRangeBase());
+ EXPECT_EQ(8U, r.GetRangeEnd());
+ EXPECT_EQ(5U, r.GetByteSize());
+}
+
+TEST(RangeTest, ContainsAddr) {
+ RangeT r(3, 5);
+ EXPECT_FALSE(r.Contains(0));
+ EXPECT_FALSE(r.Contains(1));
+ EXPECT_FALSE(r.Contains(2));
+ EXPECT_TRUE(r.Contains(3));
+ EXPECT_TRUE(r.Contains(4));
+ EXPECT_TRUE(r.Contains(5));
+ EXPECT_TRUE(r.Contains(6));
+ EXPECT_TRUE(r.Contains(7));
+ EXPECT_FALSE(r.Contains(8));
+ EXPECT_FALSE(r.Contains(9));
+ EXPECT_FALSE(r.Contains(10));
+}
+
+TEST(RangeTest, ContainsAddrInvalid) {
+ RangeT r;
+ EXPECT_FALSE(r.Contains(0));
+ EXPECT_FALSE(r.Contains(1));
+ EXPECT_FALSE(r.Contains(2));
+ EXPECT_FALSE(r.Contains(3));
+ EXPECT_FALSE(r.Contains(4));
+}
+
+TEST(RangeTest, ContainsEndInclusive) {
+ RangeT r(3, 5);
+ EXPECT_FALSE(r.ContainsEndInclusive(0));
+ EXPECT_FALSE(r.ContainsEndInclusive(1));
+ EXPECT_FALSE(r.ContainsEndInclusive(2));
+ EXPECT_TRUE(r.ContainsEndInclusive(3));
+ EXPECT_TRUE(r.ContainsEndInclusive(4));
+ EXPECT_TRUE(r.ContainsEndInclusive(5));
+ EXPECT_TRUE(r.ContainsEndInclusive(6));
+ EXPECT_TRUE(r.ContainsEndInclusive(7));
+ EXPECT_TRUE(r.ContainsEndInclusive(8));
+ EXPECT_FALSE(r.ContainsEndInclusive(9));
+ EXPECT_FALSE(r.ContainsEndInclusive(10));
+}
+
+TEST(RangeTest, ContainsEndInclusiveInvalid) {
+ RangeT r;
+ // FIXME: This is probably not intended.
+ EXPECT_TRUE(r.ContainsEndInclusive(0));
+
+ EXPECT_FALSE(r.ContainsEndInclusive(1));
+ EXPECT_FALSE(r.ContainsEndInclusive(2));
+}
+
+TEST(RangeTest, ContainsRange) {
+ RangeT r(3, 5);
+
+ // Range always contains itself.
+ EXPECT_TRUE(r.Contains(r));
+ // Invalid range.
+ EXPECT_FALSE(r.Contains(RangeT()));
+ // Range starts and ends before.
+ EXPECT_FALSE(r.Contains(RangeT(0, 3)));
+ // Range starts before but contains beginning.
+ EXPECT_FALSE(r.Contains(RangeT(0, 4)));
+ // Range starts before but contains beginning and more.
+ EXPECT_FALSE(r.Contains(RangeT(0, 5)));
+ // Range starts before and contains the other.
+ EXPECT_FALSE(r.Contains(RangeT(0, 9)));
+ // Range is fully inside.
+ EXPECT_TRUE(r.Contains(RangeT(4, 3)));
+ // Range has same start, but not as large.
+ EXPECT_TRUE(r.Contains(RangeT(3, 4)));
+ // Range has same end, but starts earlier.
+ EXPECT_TRUE(r.Contains(RangeT(4, 4)));
+ // Range starts inside, but stops after the end of r.
+ EXPECT_FALSE(r.Contains(RangeT(4, 5)));
+ // Range starts directly after r.
+ EXPECT_FALSE(r.Contains(RangeT(8, 2)));
+ // Range starts directly after r.
+ EXPECT_FALSE(r.Contains(RangeT(9, 2)));
+
+ // Invalid range with different start.
+ // FIXME: The first two probably not intended.
+ EXPECT_TRUE(r.Contains(RangeT(3, 0)));
+ EXPECT_TRUE(r.Contains(RangeT(4, 0)));
+ EXPECT_FALSE(r.Contains(RangeT(8, 0)));
+}
+
+TEST(RangeTest, ContainsRangeStartingFromZero) {
+ RangeT r(0, 3);
+ EXPECT_TRUE(r.Contains(r));
+
+ // FIXME: This is probably not intended.
+ EXPECT_TRUE(r.Contains(RangeT()));
+}
+
+TEST(RangeTest, Union) {
+ RangeT r(3, 5);
+
+ // Ranges that we can't merge because it's not adjoin/intersecting.
+ EXPECT_FALSE(r.Union(RangeT(9, 1)));
+ // Check that we didn't modify our range.
+ EXPECT_EQ(r, RangeT(3, 5));
+
+ // Another range we can't merge, but before r.
+ EXPECT_FALSE(r.Union(RangeT(1, 1)));
+ EXPECT_EQ(r, RangeT(3, 5));
+
+ // Merge an adjoin range after.
+ EXPECT_TRUE(r.Union(RangeT(8, 2)));
+ EXPECT_EQ(r, RangeT(3, 7));
+
+ // Merge an adjoin range before.
+ EXPECT_TRUE(r.Union(RangeT(1, 2)));
+ EXPECT_EQ(r, RangeT(1, 9));
+
+ // Merge an intersecting range after.
+ EXPECT_TRUE(r.Union(RangeT(8, 3)));
+ EXPECT_EQ(r, RangeT(1, 10));
+
+ // Merge an intersecting range before.
+ EXPECT_TRUE(r.Union(RangeT(0, 1)));
+ EXPECT_EQ(r, RangeT(0, 11));
+
+ // Merge a few ranges inside that shouldn't do anything.
+ EXPECT_TRUE(r.Union(RangeT(0, 3)));
+ EXPECT_EQ(r, RangeT(0, 11));
+ EXPECT_TRUE(r.Union(RangeT(5, 1)));
+ EXPECT_EQ(r, RangeT(0, 11));
+ EXPECT_TRUE(r.Union(RangeT(9, 2)));
+ EXPECT_EQ(r, RangeT(0, 11));
+}
+
+TEST(RangeTest, DoesAdjoinOrIntersect) {
+ RangeT r(3, 4);
+
+ EXPECT_FALSE(r.DoesAdjoinOrIntersect(RangeT(1, 1)));
+ EXPECT_TRUE(r.DoesAdjoinOrIntersect(RangeT(1, 2)));
+ EXPECT_TRUE(r.DoesAdjoinOrIntersect(RangeT(2, 2)));
+ EXPECT_TRUE(r.DoesAdjoinOrIntersect(RangeT(4, 2)));
+ EXPECT_TRUE(r.DoesAdjoinOrIntersect(RangeT(6, 2)));
+ EXPECT_TRUE(r.DoesAdjoinOrIntersect(RangeT(7, 2)));
+ EXPECT_FALSE(r.DoesAdjoinOrIntersect(RangeT(8, 2)));
+}
+
+TEST(RangeTest, DoesIntersect) {
+ RangeT r(3, 4);
+
+ EXPECT_FALSE(r.DoesIntersect(RangeT(1, 1)));
+ EXPECT_FALSE(r.DoesIntersect(RangeT(1, 2)));
+ EXPECT_TRUE(r.DoesIntersect(RangeT(2, 2)));
+ EXPECT_TRUE(r.DoesIntersect(RangeT(4, 2)));
+ EXPECT_TRUE(r.DoesIntersect(RangeT(6, 2)));
+ EXPECT_FALSE(r.DoesIntersect(RangeT(7, 2)));
+ EXPECT_FALSE(r.DoesIntersect(RangeT(8, 2)));
+}
+
+TEST(RangeTest, LessThan) {
+ RangeT r(10, 20);
+
+ // Equal range.
+ EXPECT_FALSE(r < RangeT(10, 20));
+ EXPECT_FALSE(RangeT(10, 20) < r);
+
+ auto expect_ordered_less_than = [](RangeT r1, RangeT r2) {
+ EXPECT_TRUE(r1 < r2);
+ EXPECT_FALSE(r2 < r1);
+ };
+
+ // Same start, but bigger size.
+ expect_ordered_less_than(r, RangeT(10, 21));
+
+ // Start before and ends before.
+ expect_ordered_less_than(RangeT(9, 20), r);
+
+ // Start before and equal size.
+ expect_ordered_less_than(RangeT(9, 21), r);
+
+ // Start before and bigger size.
+ expect_ordered_less_than(RangeT(9, 22), r);
+
+ // Start after and ends before.
+ expect_ordered_less_than(r, RangeT(11, 18));
+
+ // Start after and equal size.
+ expect_ordered_less_than(r, RangeT(11, 19));
+
+ // Start after and bigger size.
+ expect_ordered_less_than(r, RangeT(11, 20));
+}
+
+TEST(RangeTest, Equal) {
+ RangeT r(10, 20);
+
+ // Equal range.
+ EXPECT_TRUE(r == RangeT(10, 20));
+
+ // Same start, different size.
+ EXPECT_FALSE(r == RangeT(10, 21));
+
+ // Different start, same size.
+ EXPECT_FALSE(r == RangeT(9, 20));
+
+ // Different start, different size.
+ EXPECT_FALSE(r == RangeT(9, 21));
+ EXPECT_FALSE(r == RangeT(11, 19));
+}
+
+TEST(RangeTest, NotEqual) {
+ RangeT r(10, 20);
+
+ EXPECT_FALSE(r != RangeT(10, 20));
+
+ EXPECT_TRUE(r != RangeT(10, 21));
+ EXPECT_TRUE(r != RangeT(9, 20));
+ EXPECT_TRUE(r != RangeT(9, 21));
+}
+
+// Comparison tests for invalid ranges (size == 0).
+
+TEST(RangeTest, LessThanInvalid) {
+ EXPECT_TRUE(RangeT() < RangeT(1, 0));
+ EXPECT_TRUE(RangeT() < RangeT(2, 0));
+ EXPECT_TRUE(RangeT(1, 0) < RangeT(2, 0));
+}
+
+TEST(RangeTest, EqualInvalid) {
+ RangeT r;
+ EXPECT_TRUE(r == RangeT());
+ // Another invalid range, but with a different start.
+ EXPECT_FALSE(r == RangeT(3, 0));
+}
+
+TEST(RangeTest, NotEqualInvalid) {
+ RangeT r;
+ EXPECT_FALSE(r != RangeT());
+ EXPECT_FALSE(r == RangeT(3, 0));
+}
diff --git a/unittests/Core/RichManglingContextTest.cpp b/unittests/Core/RichManglingContextTest.cpp
new file mode 100644
index 000000000000..3bb0aaecbed3
--- /dev/null
+++ b/unittests/Core/RichManglingContextTest.cpp
@@ -0,0 +1,140 @@
+//===-- RichManglingContextTest.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/RichManglingContext.h"
+
+#include "lldb/Utility/ConstString.h"
+
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+TEST(RichManglingContextTest, Basic) {
+ RichManglingContext RMC;
+ ConstString mangled("_ZN3foo3barEv");
+ EXPECT_TRUE(RMC.FromItaniumName(mangled));
+
+ EXPECT_TRUE(RMC.IsFunction());
+ EXPECT_FALSE(RMC.IsCtorOrDtor());
+
+ RMC.ParseFunctionDeclContextName();
+ EXPECT_EQ("foo", RMC.GetBufferRef());
+
+ RMC.ParseFunctionBaseName();
+ EXPECT_EQ("bar", RMC.GetBufferRef());
+
+ RMC.ParseFullName();
+ EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
+}
+
+TEST(RichManglingContextTest, FromCxxMethodName) {
+ RichManglingContext ItaniumRMC;
+ ConstString mangled("_ZN3foo3barEv");
+ EXPECT_TRUE(ItaniumRMC.FromItaniumName(mangled));
+
+ RichManglingContext CxxMethodRMC;
+ ConstString demangled("foo::bar()");
+ EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(demangled));
+
+ EXPECT_TRUE(ItaniumRMC.IsFunction() == CxxMethodRMC.IsFunction());
+ EXPECT_TRUE(ItaniumRMC.IsCtorOrDtor() == CxxMethodRMC.IsCtorOrDtor());
+
+ ItaniumRMC.ParseFunctionDeclContextName();
+ CxxMethodRMC.ParseFunctionDeclContextName();
+ EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
+
+ ItaniumRMC.ParseFunctionBaseName();
+ CxxMethodRMC.ParseFunctionBaseName();
+ EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
+
+ ItaniumRMC.ParseFullName();
+ CxxMethodRMC.ParseFullName();
+ EXPECT_TRUE(ItaniumRMC.GetBufferRef() == CxxMethodRMC.GetBufferRef());
+
+ // Construct with a random name.
+ {
+ RichManglingContext CxxMethodRMC;
+ EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(ConstString("X")));
+
+ // We expect it is not a function.
+ EXPECT_FALSE(CxxMethodRMC.IsFunction());
+ }
+
+ // Construct with a function without a context.
+ {
+ RichManglingContext CxxMethodRMC;
+ EXPECT_TRUE(CxxMethodRMC.FromCxxMethodName(
+ ConstString("void * operator new(unsigned __int64)")));
+
+ // We expect it is a function.
+ EXPECT_TRUE(CxxMethodRMC.IsFunction());
+
+ // We expect its context is empty.
+ CxxMethodRMC.ParseFunctionDeclContextName();
+ EXPECT_TRUE(CxxMethodRMC.GetBufferRef().empty());
+ }
+}
+
+TEST(RichManglingContextTest, SwitchProvider) {
+ RichManglingContext RMC;
+ llvm::StringRef mangled = "_ZN3foo3barEv";
+ llvm::StringRef demangled = "foo::bar()";
+
+ EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
+ RMC.ParseFullName();
+ EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
+
+ EXPECT_TRUE(RMC.FromCxxMethodName(ConstString(demangled)));
+ RMC.ParseFullName();
+ EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
+
+ EXPECT_TRUE(RMC.FromItaniumName(ConstString(mangled)));
+ RMC.ParseFullName();
+ EXPECT_EQ("foo::bar()", RMC.GetBufferRef());
+}
+
+TEST(RichManglingContextTest, IPDRealloc) {
+ // The demangled name should fit into the Itanium default buffer.
+ const char *ShortMangled = "_ZN3foo3barEv";
+
+ // The demangled name for this will certainly not fit into the default buffer.
+ const char *LongMangled =
+ "_ZNK3shk6detail17CallbackPublisherIZNS_5ThrowERKNSt15__exception_"
+ "ptr13exception_ptrEEUlOT_E_E9SubscribeINS0_9ConcatMapINS0_"
+ "18CallbackSubscriberIZNS_6GetAllIiNS1_IZZNS_9ConcatMapIZNS_6ConcatIJNS1_"
+ "IZZNS_3MapIZZNS_7IfEmptyIS9_EEDaS7_ENKUlS6_E_clINS1_IZZNS_4TakeIiEESI_"
+ "S7_ENKUlS6_E_clINS1_IZZNS_6FilterIZNS_9ElementAtEmEUlS7_E_EESI_S7_"
+ "ENKUlS6_E_clINS1_IZZNSL_ImEESI_S7_ENKUlS6_E_clINS1_IZNS_4FromINS0_"
+ "22InfiniteRangeContainerIiEEEESI_S7_EUlS7_E_EEEESI_S6_EUlS7_E_EEEESI_S6_"
+ "EUlS7_E_EEEESI_S6_EUlS7_E_EEEESI_S6_EUlS7_E_EESI_S7_ENKUlS6_E_clIS14_"
+ "EESI_S6_EUlS7_E_EERNS1_IZZNSH_IS9_EESI_S7_ENKSK_IS14_EESI_S6_EUlS7_E0_"
+ "EEEEESI_DpOT_EUlS7_E_EESI_S7_ENKUlS6_E_clINS1_IZNS_5StartIJZNS_"
+ "4JustIJS19_S1C_EEESI_S1F_EUlvE_ZNS1K_IJS19_S1C_EEESI_S1F_EUlvE0_EEESI_"
+ "S1F_EUlS7_E_EEEESI_S6_EUlS7_E_EEEESt6vectorIS6_SaIS6_EERKT0_NS_"
+ "12ElementCountEbEUlS7_E_ZNSD_IiS1Q_EES1T_S1W_S1X_bEUlOS3_E_ZNSD_IiS1Q_"
+ "EES1T_S1W_S1X_bEUlvE_EES1G_S1O_E25ConcatMapValuesSubscriberEEEDaS7_";
+
+ RichManglingContext RMC;
+
+ // Demangle the short one.
+ EXPECT_TRUE(RMC.FromItaniumName(ConstString(ShortMangled)));
+ RMC.ParseFullName();
+ const char *ShortDemangled = RMC.GetBufferRef().data();
+
+ // Demangle the long one.
+ EXPECT_TRUE(RMC.FromItaniumName(ConstString(LongMangled)));
+ RMC.ParseFullName();
+ const char *LongDemangled = RMC.GetBufferRef().data();
+
+ // Make sure a new buffer was allocated or the default buffer was extended.
+ bool AllocatedNewBuffer = (ShortDemangled != LongDemangled);
+ bool ExtendedExistingBuffer = (strlen(LongDemangled) > 2048);
+ EXPECT_TRUE(AllocatedNewBuffer || ExtendedExistingBuffer);
+}
diff --git a/unittests/Core/StateTest.cpp b/unittests/Core/StateTest.cpp
deleted file mode 100644
index 76cdaac82055..000000000000
--- a/unittests/Core/StateTest.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-//===-- StateTest.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/State.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "gtest/gtest.h"
-
-using namespace lldb;
-using namespace lldb_private;
-
-TEST(StateTest, Formatv) {
- EXPECT_EQ("exited", llvm::formatv("{0}", eStateExited).str());
- EXPECT_EQ("stopped", llvm::formatv("{0}", eStateStopped).str());
- EXPECT_EQ("unknown", llvm::formatv("{0}", StateType(-1)).str());
-}
diff --git a/unittests/Disassembler/CMakeLists.txt b/unittests/Disassembler/CMakeLists.txt
new file mode 100644
index 000000000000..3159f9d8cc13
--- /dev/null
+++ b/unittests/Disassembler/CMakeLists.txt
@@ -0,0 +1,13 @@
+if("ARM" IN_LIST LLVM_TARGETS_TO_BUILD)
+ add_lldb_unittest(DisassemblerTests
+ TestArmv7Disassembly.cpp
+ LINK_LIBS
+ lldbCore
+ lldbSymbol
+ lldbTarget
+ lldbPluginDisassemblerLLVM
+ lldbPluginProcessUtility
+ LINK_COMPONENTS
+ Support
+ ${LLVM_TARGETS_TO_BUILD})
+endif()
diff --git a/unittests/Disassembler/TestArmv7Disassembly.cpp b/unittests/Disassembler/TestArmv7Disassembly.cpp
new file mode 100644
index 000000000000..600d79330849
--- /dev/null
+++ b/unittests/Disassembler/TestArmv7Disassembly.cpp
@@ -0,0 +1,93 @@
+//===-- TestArmv7Disassembly.cpp ------------------------------------*- C++
+//-*-===//
+
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Target/ExecutionContext.h"
+
+#include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
+#include "llvm/Support/TargetSelect.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+class TestArmv7Disassembly : public testing::Test {
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ // virtual void SetUp() override { }
+ // virtual void TearDown() override { }
+
+protected:
+};
+
+void TestArmv7Disassembly::SetUpTestCase() {
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllDisassemblers();
+ DisassemblerLLVMC::Initialize();
+}
+
+void TestArmv7Disassembly::TearDownTestCase() {
+ DisassemblerLLVMC::Terminate();
+}
+
+TEST_F(TestArmv7Disassembly, TestCortexFPDisass) {
+ ArchSpec arch("armv7em--");
+
+ const unsigned num_of_instructions = 3;
+ uint8_t data[] = {
+ 0x00, 0xee, 0x10, 0x2a, // 0xee002a10 : vmov s0, r2
+ 0xb8, 0xee, 0xc0, 0x0b, // 0xeeb80bc0 : vcvt.f64.s32 d0, s0
+ 0xb6, 0xee, 0x00, 0x0a, // 0xeeb60a00 : vmov.f32 s0, #5.000000e-01
+ };
+
+ // these can be disassembled by hand with llvm-mc, e.g.
+ //
+ // 0x00, 0xee, 0x10, 0x2a, // 0xee002a10 : vmov s0, r2
+ //
+ // echo 0x00 0xee 0x10 0x2a | llvm-mc -arch thumb -disassemble -mattr=+fp-armv8
+ // vmov s0, r2
+
+ DisassemblerSP disass_sp;
+ Address start_addr(0x100);
+ disass_sp = Disassembler::DisassembleBytes(arch, nullptr, nullptr, start_addr,
+ &data, sizeof (data), num_of_instructions, false);
+
+ // If we failed to get a disassembler, we can assume it is because
+ // the llvm we linked against was not built with the ARM target,
+ // and we should skip these tests without marking anything as failing.
+
+ if (disass_sp) {
+ const InstructionList inst_list (disass_sp->GetInstructionList());
+ EXPECT_EQ (num_of_instructions, inst_list.GetSize());
+
+ InstructionSP inst_sp;
+ const char *mnemonic;
+ ExecutionContext exe_ctx (nullptr, nullptr, nullptr);
+ inst_sp = inst_list.GetInstructionAtIndex (0);
+ mnemonic = inst_sp->GetMnemonic(&exe_ctx);
+ ASSERT_STREQ ("vmov", mnemonic);
+
+ inst_sp = inst_list.GetInstructionAtIndex (1);
+ mnemonic = inst_sp->GetMnemonic(&exe_ctx);
+ ASSERT_STREQ ("vcvt.f64.s32", mnemonic);
+
+ inst_sp = inst_list.GetInstructionAtIndex (2);
+ mnemonic = inst_sp->GetMnemonic(&exe_ctx);
+ ASSERT_STREQ ("vmov.f32", mnemonic);
+ }
+}
diff --git a/unittests/Editline/EditlineTest.cpp b/unittests/Editline/EditlineTest.cpp
index 963d9043e994..ffa95560d3e3 100644
--- a/unittests/Editline/EditlineTest.cpp
+++ b/unittests/Editline/EditlineTest.cpp
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
#include "lldb/Host/Editline.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Utility/Status.h"
@@ -246,6 +247,8 @@ private:
public:
void SetUp() {
+ FileSystem::Initialize();
+
// We need a TERM set properly for editline to work as expected.
setenv("TERM", "vt100", 1);
@@ -263,6 +266,8 @@ public:
_el_adapter.CloseInput();
if (_sp_output_thread)
_sp_output_thread->join();
+
+ FileSystem::Terminate();
}
EditlineAdapter &GetEditlineAdapter() { return _el_adapter; }
diff --git a/unittests/Expression/CMakeLists.txt b/unittests/Expression/CMakeLists.txt
index 9b1d32fbdae0..bad090d64197 100644
--- a/unittests/Expression/CMakeLists.txt
+++ b/unittests/Expression/CMakeLists.txt
@@ -1,11 +1,9 @@
add_lldb_unittest(ExpressionTests
ClangParserTest.cpp
- GoParserTest.cpp
LINK_LIBS
lldbCore
lldbPluginExpressionParserClang
- lldbPluginExpressionParserGo
lldbUtility
lldbUtilityHelpers
)
diff --git a/unittests/Expression/ClangParserTest.cpp b/unittests/Expression/ClangParserTest.cpp
index c776e48c9529..69ffb94c45c3 100644
--- a/unittests/Expression/ClangParserTest.cpp
+++ b/unittests/Expression/ClangParserTest.cpp
@@ -9,6 +9,7 @@
#include "Plugins/ExpressionParser/Clang/ClangHost.h"
#include "TestingSupport/TestUtilities.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-defines.h"
@@ -18,8 +19,14 @@ using namespace lldb_private;
namespace {
struct ClangHostTest : public testing::Test {
- static void SetUpTestCase() { HostInfo::Initialize(); }
- static void TearDownTestCase() { HostInfo::Terminate(); }
+ static void SetUpTestCase() {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
+ static void TearDownTestCase() {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
};
} // namespace
@@ -27,7 +34,7 @@ struct ClangHostTest : public testing::Test {
static std::string ComputeClangDir(std::string lldb_shlib_path,
bool verify = false) {
FileSpec clang_dir;
- FileSpec lldb_shlib_spec(lldb_shlib_path, false);
+ FileSpec lldb_shlib_spec(lldb_shlib_path);
ComputeClangDirectory(lldb_shlib_spec, clang_dir, verify);
return clang_dir.GetPath();
}
diff --git a/unittests/Expression/GoParserTest.cpp b/unittests/Expression/GoParserTest.cpp
deleted file mode 100644
index 2af75acda914..000000000000
--- a/unittests/Expression/GoParserTest.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-//===-- GoParserTest.cpp ------------------------------------------*- C++
-//-*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include <sstream>
-
-#include "gtest/gtest.h"
-
-#include "Plugins/ExpressionParser/Go/GoParser.h"
-#include "lldb/Utility/Status.h"
-
-using namespace lldb_private;
-
-namespace {
-struct ASTPrinter {
- ASTPrinter(GoASTNode *n) { (*this)(n); }
-
- void operator()(GoASTNode *n) {
- if (n == nullptr) {
- m_stream << "nil ";
- return;
- }
- m_stream << "(" << n->GetKindName() << " ";
- n->WalkChildren(*this);
- if (auto *nn = llvm::dyn_cast<GoASTAssignStmt>(n))
- m_stream << nn->GetDefine() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTBasicLit>(n))
- m_stream << nn->GetValue().m_value.str() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTBinaryExpr>(n))
- m_stream << GoLexer::LookupToken(nn->GetOp()).str() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTIdent>(n))
- m_stream << nn->GetName().m_value.str() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTBranchStmt>(n))
- m_stream << GoLexer::LookupToken(nn->GetTok()).str() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTCallExpr>(n))
- m_stream << (nn->GetEllipsis() ? "..." : "") << " ";
- if (auto *nn = llvm::dyn_cast<GoASTChanType>(n))
- m_stream << nn->GetDir() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTGenDecl>(n))
- m_stream << GoLexer::LookupToken(nn->GetTok()).str() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTIncDecStmt>(n))
- m_stream << GoLexer::LookupToken(nn->GetTok()).str() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTRangeStmt>(n))
- m_stream << nn->GetDefine() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTSliceExpr>(n))
- m_stream << nn->GetSlice3() << " ";
- if (auto *nn = llvm::dyn_cast<GoASTUnaryExpr>(n))
- m_stream << GoLexer::LookupToken(nn->GetOp()).str() << " ";
- m_stream << ") ";
- }
-
- const std::string str() const { return m_stream.str(); }
- std::stringstream m_stream;
-};
-
-testing::AssertionResult CheckStatement(const char *_s, const char *c_expr,
- const char *sexpr, const char *code) {
- GoParser parser(code);
- std::unique_ptr<GoASTStmt> stmt(parser.Statement());
- if (parser.Failed() || !stmt) {
- Status err;
- parser.GetError(err);
- return testing::AssertionFailure() << "Error parsing " << c_expr << "\n\t"
- << err.AsCString();
- }
- std::string actual_sexpr = ASTPrinter(stmt.get()).str();
- if (actual_sexpr == sexpr)
- return testing::AssertionSuccess();
- return testing::AssertionFailure() << "Parsing: " << c_expr
- << "\nExpected: " << sexpr
- << "\nGot: " << actual_sexpr;
-}
-} // namespace
-
-#define EXPECT_PARSE(s, c) EXPECT_PRED_FORMAT2(CheckStatement, s, c)
-
-TEST(GoParserTest, ParseBasicLiterals) {
- EXPECT_PARSE("(ExprStmt (BasicLit 0 ) ) ", "0");
- EXPECT_PARSE("(ExprStmt (BasicLit 42 ) ) ", "42");
- EXPECT_PARSE("(ExprStmt (BasicLit 0600 ) ) ", "0600");
- EXPECT_PARSE("(ExprStmt (BasicLit 0xBadFace ) ) ", "0xBadFace");
- EXPECT_PARSE(
- "(ExprStmt (BasicLit 170141183460469231731687303715884105727 ) ) ",
- "170141183460469231731687303715884105727");
-
- EXPECT_PARSE("(ExprStmt (BasicLit 0. ) ) ", "0.");
- EXPECT_PARSE("(ExprStmt (BasicLit 72.40 ) ) ", "72.40");
- EXPECT_PARSE("(ExprStmt (BasicLit 072.40 ) ) ", "072.40");
- EXPECT_PARSE("(ExprStmt (BasicLit 2.71828 ) ) ", "2.71828");
- EXPECT_PARSE("(ExprStmt (BasicLit 1.e+0 ) ) ", "1.e+0");
- EXPECT_PARSE("(ExprStmt (BasicLit 6.67428e-11 ) ) ", "6.67428e-11");
- EXPECT_PARSE("(ExprStmt (BasicLit 1E6 ) ) ", "1E6");
- EXPECT_PARSE("(ExprStmt (BasicLit .12345E+6 ) ) ", ".12345E+6");
-
- EXPECT_PARSE("(ExprStmt (BasicLit 0i ) ) ", "0i");
- EXPECT_PARSE("(ExprStmt (BasicLit 011i ) ) ", "011i");
- EXPECT_PARSE("(ExprStmt (BasicLit 0.i ) ) ", "0.i");
- EXPECT_PARSE("(ExprStmt (BasicLit 2.71828i ) ) ", "2.71828i");
- EXPECT_PARSE("(ExprStmt (BasicLit 6.67428e-11i ) ) ", "6.67428e-11i");
- EXPECT_PARSE("(ExprStmt (BasicLit 1E6i ) ) ", "1E6i");
- EXPECT_PARSE("(ExprStmt (BasicLit .12345E+6i ) ) ", ".12345E+6i");
-
- EXPECT_PARSE("(ExprStmt (BasicLit 'a' ) ) ", "'a'");
- EXPECT_PARSE("(ExprStmt (BasicLit '本' ) ) ", "'本'");
- EXPECT_PARSE("(ExprStmt (BasicLit \"abc\" ) ) ", "\"abc\"");
- EXPECT_PARSE("(ExprStmt (BasicLit `abc` ) ) ", "`abc`");
- EXPECT_PARSE("(ExprStmt (BasicLit `ab\nc` ) ) ", "`ab\nc`");
-}
-
-TEST(GoParserTest, ParseOperand) {
- EXPECT_PARSE("(ExprStmt (Ident a ) ) ", "a");
- EXPECT_PARSE("(ExprStmt (Ident _x9 ) ) ", "_x9");
- EXPECT_PARSE("(ExprStmt (Ident ThisVariableIsExported ) ) ",
- "ThisVariableIsExported");
- EXPECT_PARSE("(ExprStmt (Ident αβ ) ) ", "αβ");
-
- EXPECT_PARSE("(ExprStmt (SelectorExpr (Ident math ) (Ident Sin ) ) ) ",
- "math.Sin");
-}
-
-TEST(GoParserTest, ParseCompositeLiterals) {
- EXPECT_PARSE("(ExprStmt (CompositeLit (Ident Point3D ) ) ) ", "Point3D{}");
- EXPECT_PARSE("(ExprStmt (CompositeLit (Ident Line ) (Ident origin ) "
- "(CompositeLit (Ident Point3D ) (KeyValueExpr "
- "(Ident y ) (UnaryExpr (BasicLit 4 ) - ) ) (KeyValueExpr (Ident "
- "z ) (BasicLit 12.3 ) ) ) ) ) ",
- "Line{origin, Point3D{y: -4, z: 12.3}}");
- EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 10 ) (Ident "
- "string ) ) ) ) ",
- "[10]string{}");
- EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 6 ) (Ident int ) "
- ") (BasicLit 1 ) (BasicLit 2 ) "
- "(BasicLit 3 ) (BasicLit 5 ) ) ) ",
- "[6]int {1, 2, 3, 5}");
- EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType nil (Ident int ) ) "
- "(BasicLit 2 ) (BasicLit 3 ) (BasicLit 5 ) "
- "(BasicLit 7 ) (BasicLit 9 ) (BasicLit 2147483647 ) ) ) ",
- "[]int{2, 3, 5, 7, 9, 2147483647}");
- EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (BasicLit 128 ) (Ident bool "
- ") ) (KeyValueExpr (BasicLit 'a' ) "
- "(Ident true ) ) (KeyValueExpr (BasicLit 'e' ) (Ident true ) ) "
- "(KeyValueExpr (BasicLit 'i' ) (Ident "
- "true ) ) (KeyValueExpr (BasicLit 'o' ) (Ident true ) ) "
- "(KeyValueExpr (BasicLit 'u' ) (Ident true ) ) "
- "(KeyValueExpr (BasicLit 'y' ) (Ident true ) ) ) ) ",
- "[128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': "
- "true, 'y': true}");
- EXPECT_PARSE(
- "(ExprStmt (CompositeLit (ArrayType (BasicLit 10 ) (Ident float32 ) ) "
- "(UnaryExpr (BasicLit 1 ) - ) "
- "(KeyValueExpr (BasicLit 4 ) (UnaryExpr (BasicLit 0.1 ) - ) ) (UnaryExpr "
- "(BasicLit 0.1 ) - ) "
- "(KeyValueExpr (BasicLit 9 ) (UnaryExpr (BasicLit 1 ) - ) ) ) ) ",
- "[10]float32{-1, 4: -0.1, -0.1, 9: -1}");
-}
-
-TEST(GoParserTest, ParseEllipsisArray) {
- EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (Ellipsis nil ) (Ident "
- "string ) ) (BasicLit `Sat` ) (BasicLit `Sun` ) ) ) ",
- "[...]string {`Sat`, `Sun`}");
- EXPECT_PARSE("(ExprStmt (CompositeLit (ArrayType (Ellipsis nil ) (Ident "
- "Point ) ) (CompositeLit nil (BasicLit 1.5 "
- ") (UnaryExpr (BasicLit 3.5 ) - ) ) (CompositeLit nil (BasicLit "
- "0 ) (BasicLit 0 ) ) ) ) ",
- "[...]Point{{1.5, -3.5}, {0, 0}}");
-}
-
-TEST(GoParserTest, ParseMap) {
- EXPECT_PARSE("(ExprStmt (CompositeLit (MapType (Ident string ) (Ident "
- "float32 ) ) (KeyValueExpr (BasicLit `C0` ) "
- "(BasicLit 16.35 ) ) (KeyValueExpr (BasicLit `D0` ) (BasicLit "
- "18.35 ) ) ) ) ",
- "map[string]float32{`C0`: 16.35, `D0`: 18.35, }");
-}
-
-TEST(GoParserTest, UnaryExpr) {
- EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) + ) ) ", "+x");
- EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) - ) ) ", "-x");
- EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) ! ) ) ", "!x");
- EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) ^ ) ) ", "^x");
- EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) & ) ) ", "&x");
- EXPECT_PARSE("(ExprStmt (UnaryExpr (Ident x ) <- ) ) ", "<-x");
- EXPECT_PARSE("(ExprStmt (StarExpr (Ident x ) ) ) ", "*x");
-}
-
-TEST(GoParserTest, BinaryExpr) {
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) || ) ) ", "a || b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) && ) ) ", "a && b");
-
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) == ) ) ", "a == b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) != ) ) ", "a != b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) < ) ) ", "a < b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) <= ) ) ", "a <= b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) > ) ) ", "a > b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) >= ) ) ", "a >= b");
-
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) + ) ) ", "a + b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) - ) ) ", "a - b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) | ) ) ", "a | b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) ^ ) ) ", "a ^ b");
-
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) * ) ) ", "a * b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) / ) ) ", "a / b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) % ) ) ", "a % b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) << ) ) ", "a << b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) >> ) ) ", "a >> b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) & ) ) ", "a & b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (Ident b ) &^ ) ) ", "a &^ b");
-
- EXPECT_PARSE("(ExprStmt (BinaryExpr (BasicLit 23 ) (BinaryExpr (BasicLit 3 ) "
- "(IndexExpr (Ident x ) (Ident i ) ) * ) + ) ) ",
- "23 + 3*x[i]");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident a ) (UnaryExpr (UnaryExpr (Ident "
- "a ) + ) + ) + ) ) ",
- "a + + + a");
- EXPECT_PARSE(
- "(ExprStmt (BinaryExpr (UnaryExpr (Ident a ) ^ ) (Ident b ) >> ) ) ",
- "^a >> b");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (CallExpr (Ident f ) ) (CallExpr (Ident "
- "g ) ) || ) ) ",
- "f() || g()");
- EXPECT_PARSE(
- "(ExprStmt (BinaryExpr (BinaryExpr (Ident x ) (BinaryExpr (Ident y ) "
- "(BasicLit 1 ) + ) == ) "
- "(BinaryExpr (UnaryExpr (Ident chanPtr ) <- ) (BasicLit 0 ) > ) && ) ) ",
- "x == y+1 && <-chanPtr > 0");
-}
-
-TEST(GoParserTest, PrimaryExpr) {
- EXPECT_PARSE(
- "(ExprStmt (BinaryExpr (Ident x ) (CallExpr (Ident f ) ) <= ) ) ",
- "x <= f()");
- EXPECT_PARSE("(ExprStmt (BinaryExpr (Ident s ) (BasicLit `.txt` ) + ) ) ",
- "(s + `.txt`)");
- EXPECT_PARSE(
- "(ExprStmt (CallExpr (Ident f ) (BasicLit 3.1415 ) (Ident true ) ) ) ",
- "f(3.1415, true)");
- EXPECT_PARSE(
- "(ExprStmt (CallExpr (Ident f ) (BasicLit 3.1415 ) (Ident a ) ... ) ) ",
- "f(3.1415, a...)");
- EXPECT_PARSE("(ExprStmt (IndexExpr (Ident m ) (BasicLit '1' ) ) ) ",
- "m['1']");
- EXPECT_PARSE("(ExprStmt (SliceExpr (Ident s ) (Ident i ) (BinaryExpr (Ident "
- "j ) (BasicLit 1 ) + ) nil 0 ) ) ",
- "s[i : j + 1]");
- EXPECT_PARSE("(ExprStmt (SelectorExpr (Ident obj ) (Ident color ) ) ) ",
- "obj.color");
- EXPECT_PARSE("(ExprStmt (CallExpr (SelectorExpr (IndexExpr (SelectorExpr "
- "(Ident f ) (Ident p ) ) (Ident i ) ) "
- "(Ident x ) ) ) ) ",
- "f.p[i].x()");
-}
-
-TEST(GoParserTest, Conversions) {
- EXPECT_PARSE(
- "(ExprStmt (StarExpr (CallExpr (Ident Point ) (Ident p ) ) ) ) ",
- "*Point(p)");
- EXPECT_PARSE(
- "(ExprStmt (CallExpr (StarExpr (Ident Point ) ) (Ident p ) ) ) ",
- "(*Point)(p)");
- EXPECT_PARSE("(ExprStmt (UnaryExpr (CallExpr (ChanType (Ident int ) 0 ) "
- "(Ident c ) ) <- ) ) ",
- "<-chan int(c)");
- EXPECT_PARSE("(ExprStmt (TypeAssertExpr (Ident y ) (SelectorExpr (Ident io ) "
- "(Ident Reader ) ) ) ) ",
- "y.(io.Reader)");
-}
diff --git a/unittests/Host/CMakeLists.txt b/unittests/Host/CMakeLists.txt
index f1768537ed86..93394661d36d 100644
--- a/unittests/Host/CMakeLists.txt
+++ b/unittests/Host/CMakeLists.txt
@@ -3,7 +3,7 @@ set (FILES
HostInfoTest.cpp
HostTest.cpp
MainLoopTest.cpp
- PredicateTest.cpp
+ NativeProcessProtocolTest.cpp
SocketAddressTest.cpp
SocketTest.cpp
SymbolsTest.cpp
@@ -23,4 +23,5 @@ add_lldb_unittest(HostTests
lldbCore
lldbHost
lldbUtilityHelpers
+ LLVMTestingSupport
)
diff --git a/unittests/Host/FileSystemTest.cpp b/unittests/Host/FileSystemTest.cpp
index d5160b1a0da1..254694037488 100644
--- a/unittests/Host/FileSystemTest.cpp
+++ b/unittests/Host/FileSystemTest.cpp
@@ -7,26 +7,285 @@
//
//===----------------------------------------------------------------------===//
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "lldb/Host/FileSystem.h"
+#include "llvm/Support/Errc.h"
extern const char *TestMainArgv0;
using namespace lldb_private;
+using namespace llvm;
+using llvm::sys::fs::UniqueID;
+
+// Modified from llvm/unittests/Support/VirtualFileSystemTest.cpp
+namespace {
+struct DummyFile : public vfs::File {
+ vfs::Status S;
+ explicit DummyFile(vfs::Status S) : S(S) {}
+ llvm::ErrorOr<vfs::Status> status() override { return S; }
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>
+ getBuffer(const Twine &Name, int64_t FileSize, bool RequiresNullTerminator,
+ bool IsVolatile) override {
+ llvm_unreachable("unimplemented");
+ }
+ std::error_code close() override { return std::error_code(); }
+};
+
+class DummyFileSystem : public vfs::FileSystem {
+ int FSID; // used to produce UniqueIDs
+ int FileID; // used to produce UniqueIDs
+ std::string cwd;
+ std::map<std::string, vfs::Status> FilesAndDirs;
+
+ static int getNextFSID() {
+ static int Count = 0;
+ return Count++;
+ }
+
+public:
+ DummyFileSystem() : FSID(getNextFSID()), FileID(0) {}
+
+ ErrorOr<vfs::Status> status(const Twine &Path) override {
+ std::map<std::string, vfs::Status>::iterator I =
+ FilesAndDirs.find(Path.str());
+ if (I == FilesAndDirs.end())
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+ return I->second;
+ }
+ ErrorOr<std::unique_ptr<vfs::File>>
+ openFileForRead(const Twine &Path) override {
+ auto S = status(Path);
+ if (S)
+ return std::unique_ptr<vfs::File>(new DummyFile{*S});
+ return S.getError();
+ }
+ llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override {
+ return cwd;
+ }
+ std::error_code setCurrentWorkingDirectory(const Twine &Path) override {
+ cwd = Path.str();
+ return std::error_code();
+ }
+ // Map any symlink to "/symlink".
+ std::error_code getRealPath(const Twine &Path,
+ SmallVectorImpl<char> &Output) const override {
+ auto I = FilesAndDirs.find(Path.str());
+ if (I == FilesAndDirs.end())
+ return make_error_code(llvm::errc::no_such_file_or_directory);
+ if (I->second.isSymlink()) {
+ Output.clear();
+ Twine("/symlink").toVector(Output);
+ return std::error_code();
+ }
+ Output.clear();
+ Path.toVector(Output);
+ return std::error_code();
+ }
+
+ struct DirIterImpl : public llvm::vfs::detail::DirIterImpl {
+ std::map<std::string, vfs::Status> &FilesAndDirs;
+ std::map<std::string, vfs::Status>::iterator I;
+ std::string Path;
+ bool isInPath(StringRef S) {
+ if (Path.size() < S.size() && S.find(Path) == 0) {
+ auto LastSep = S.find_last_of('/');
+ if (LastSep == Path.size() || LastSep == Path.size() - 1)
+ return true;
+ }
+ return false;
+ }
+ DirIterImpl(std::map<std::string, vfs::Status> &FilesAndDirs,
+ const Twine &_Path)
+ : FilesAndDirs(FilesAndDirs), I(FilesAndDirs.begin()),
+ Path(_Path.str()) {
+ for (; I != FilesAndDirs.end(); ++I) {
+ if (isInPath(I->first)) {
+ CurrentEntry =
+ vfs::directory_entry(I->second.getName(), I->second.getType());
+ break;
+ }
+ }
+ }
+ std::error_code increment() override {
+ ++I;
+ for (; I != FilesAndDirs.end(); ++I) {
+ if (isInPath(I->first)) {
+ CurrentEntry =
+ vfs::directory_entry(I->second.getName(), I->second.getType());
+ break;
+ }
+ }
+ if (I == FilesAndDirs.end())
+ CurrentEntry = vfs::directory_entry();
+ return std::error_code();
+ }
+ };
+
+ vfs::directory_iterator dir_begin(const Twine &Dir,
+ std::error_code &EC) override {
+ return vfs::directory_iterator(
+ std::make_shared<DirIterImpl>(FilesAndDirs, Dir));
+ }
+
+ void addEntry(StringRef Path, const vfs::Status &Status) {
+ FilesAndDirs[Path] = Status;
+ }
+
+ void addRegularFile(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
+ vfs::Status S(Path, UniqueID(FSID, FileID++),
+ std::chrono::system_clock::now(), 0, 0, 1024,
+ sys::fs::file_type::regular_file, Perms);
+ addEntry(Path, S);
+ }
+
+ void addDirectory(StringRef Path, sys::fs::perms Perms = sys::fs::all_all) {
+ vfs::Status S(Path, UniqueID(FSID, FileID++),
+ std::chrono::system_clock::now(), 0, 0, 0,
+ sys::fs::file_type::directory_file, Perms);
+ addEntry(Path, S);
+ }
+
+ void addSymlink(StringRef Path) {
+ vfs::Status S(Path, UniqueID(FSID, FileID++),
+ std::chrono::system_clock::now(), 0, 0, 0,
+ sys::fs::file_type::symlink_file, sys::fs::all_all);
+ addEntry(Path, S);
+ }
+};
+} // namespace
TEST(FileSystemTest, FileAndDirectoryComponents) {
using namespace std::chrono;
+ FileSystem fs;
- const bool resolve = true;
#ifdef _WIN32
- FileSpec fs1("C:\\FILE\\THAT\\DOES\\NOT\\EXIST.TXT", !resolve);
+ FileSpec fs1("C:\\FILE\\THAT\\DOES\\NOT\\EXIST.TXT");
#else
- FileSpec fs1("/file/that/does/not/exist.txt", !resolve);
+ FileSpec fs1("/file/that/does/not/exist.txt");
#endif
- FileSpec fs2(TestMainArgv0, resolve);
+ FileSpec fs2(TestMainArgv0);
+
+ fs.Resolve(fs2);
- EXPECT_EQ(system_clock::time_point(), FileSystem::GetModificationTime(fs1));
+ EXPECT_EQ(system_clock::time_point(), fs.GetModificationTime(fs1));
EXPECT_LT(system_clock::time_point() + hours(24 * 365 * 20),
- FileSystem::GetModificationTime(fs2));
+ fs.GetModificationTime(fs2));
+}
+
+static IntrusiveRefCntPtr<DummyFileSystem> GetSimpleDummyFS() {
+ IntrusiveRefCntPtr<DummyFileSystem> D(new DummyFileSystem());
+ D->addRegularFile("/foo");
+ D->addDirectory("/bar");
+ D->addSymlink("/baz");
+ D->addRegularFile("/qux", ~sys::fs::perms::all_read);
+ D->setCurrentWorkingDirectory("/");
+ return D;
+}
+
+TEST(FileSystemTest, Exists) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ EXPECT_TRUE(fs.Exists("/foo"));
+ EXPECT_TRUE(fs.Exists(FileSpec("/foo", FileSpec::Style::posix)));
+}
+
+TEST(FileSystemTest, Readable) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ EXPECT_TRUE(fs.Readable("/foo"));
+ EXPECT_TRUE(fs.Readable(FileSpec("/foo", FileSpec::Style::posix)));
+
+ EXPECT_FALSE(fs.Readable("/qux"));
+ EXPECT_FALSE(fs.Readable(FileSpec("/qux", FileSpec::Style::posix)));
+}
+
+TEST(FileSystemTest, GetByteSize) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ EXPECT_EQ((uint64_t)1024, fs.GetByteSize("/foo"));
+ EXPECT_EQ((uint64_t)1024,
+ fs.GetByteSize(FileSpec("/foo", FileSpec::Style::posix)));
+}
+
+TEST(FileSystemTest, GetPermissions) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ EXPECT_EQ(sys::fs::all_all, fs.GetPermissions("/foo"));
+ EXPECT_EQ(sys::fs::all_all,
+ fs.GetPermissions(FileSpec("/foo", FileSpec::Style::posix)));
+}
+
+TEST(FileSystemTest, MakeAbsolute) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ {
+ StringRef foo_relative = "foo";
+ SmallString<16> foo(foo_relative);
+ auto EC = fs.MakeAbsolute(foo);
+ EXPECT_FALSE(EC);
+ EXPECT_TRUE(foo.equals("/foo"));
+ }
+
+ {
+ FileSpec file_spec("foo");
+ auto EC = fs.MakeAbsolute(file_spec);
+ EXPECT_FALSE(EC);
+ EXPECT_EQ(FileSpec("/foo"), file_spec);
+ }
+}
+
+TEST(FileSystemTest, Resolve) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ {
+ StringRef foo_relative = "foo";
+ SmallString<16> foo(foo_relative);
+ fs.Resolve(foo);
+ EXPECT_TRUE(foo.equals("/foo"));
+ }
+
+ {
+ FileSpec file_spec("foo");
+ fs.Resolve(file_spec);
+ EXPECT_EQ(FileSpec("/foo"), file_spec);
+ }
+
+ {
+ StringRef foo_relative = "bogus";
+ SmallString<16> foo(foo_relative);
+ fs.Resolve(foo);
+ EXPECT_TRUE(foo.equals("bogus"));
+ }
+
+ {
+ FileSpec file_spec("bogus");
+ fs.Resolve(file_spec);
+ EXPECT_EQ(FileSpec("bogus"), file_spec);
+ }
+}
+
+FileSystem::EnumerateDirectoryResult
+VFSCallback(void *baton, llvm::sys::fs::file_type file_type,
+ llvm::StringRef path) {
+ auto visited = static_cast<std::vector<std::string> *>(baton);
+ visited->push_back(path.str());
+ return FileSystem::eEnumerateDirectoryResultNext;
+}
+
+TEST(FileSystemTest, EnumerateDirectory) {
+ FileSystem fs(GetSimpleDummyFS());
+
+ std::vector<std::string> visited;
+
+ constexpr bool find_directories = true;
+ constexpr bool find_files = true;
+ constexpr bool find_other = true;
+
+ fs.EnumerateDirectory("/", find_directories, find_files, find_other,
+ VFSCallback, &visited);
+
+ EXPECT_THAT(visited,
+ testing::UnorderedElementsAre("/foo", "/bar", "/baz", "/qux"));
}
diff --git a/unittests/Host/HostInfoTest.cpp b/unittests/Host/HostInfoTest.cpp
index 3870673d0f47..d2d1fdc256a9 100644
--- a/unittests/Host/HostInfoTest.cpp
+++ b/unittests/Host/HostInfoTest.cpp
@@ -8,20 +8,27 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/HostInfo.h"
-#include "lldb/lldb-defines.h"
#include "TestingSupport/TestUtilities.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/lldb-defines.h"
#include "gtest/gtest.h"
using namespace lldb_private;
using namespace llvm;
namespace {
-class HostInfoTest: public ::testing::Test {
- public:
- void SetUp() override { HostInfo::Initialize(); }
- void TearDown() override { HostInfo::Terminate(); }
+class HostInfoTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
+ void TearDown() override {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
};
-}
+} // namespace
TEST_F(HostInfoTest, GetAugmentedArchSpec) {
// Fully specified triple should not be changed.
@@ -43,4 +50,4 @@ TEST_F(HostInfoTest, GetAugmentedArchSpec) {
// Test LLDB_ARCH_DEFAULT
EXPECT_EQ(HostInfo::GetAugmentedArchSpec(LLDB_ARCH_DEFAULT).GetTriple(),
HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple());
-} \ No newline at end of file
+}
diff --git a/unittests/Host/NativeProcessProtocolTest.cpp b/unittests/Host/NativeProcessProtocolTest.cpp
new file mode 100644
index 000000000000..8a9271af771e
--- /dev/null
+++ b/unittests/Host/NativeProcessProtocolTest.cpp
@@ -0,0 +1,225 @@
+//===-- NativeProcessProtocolTest.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/common/NativeProcessProtocol.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+
+using namespace lldb_private;
+using namespace lldb;
+using namespace testing;
+
+namespace {
+class MockDelegate : public NativeProcessProtocol::NativeDelegate {
+public:
+ MOCK_METHOD1(InitializeDelegate, void(NativeProcessProtocol *Process));
+ MOCK_METHOD2(ProcessStateChanged,
+ void(NativeProcessProtocol *Process, StateType State));
+ MOCK_METHOD1(DidExec, void(NativeProcessProtocol *Process));
+};
+
+// NB: This class doesn't use the override keyword to avoid
+// -Winconsistent-missing-override warnings from the compiler. The
+// inconsistency comes from the overriding definitions in the MOCK_*** macros.
+class MockProcess : public NativeProcessProtocol {
+public:
+ MockProcess(NativeDelegate &Delegate, const ArchSpec &Arch,
+ lldb::pid_t Pid = 1)
+ : NativeProcessProtocol(Pid, -1, Delegate), Arch(Arch) {}
+
+ MOCK_METHOD1(Resume, Status(const ResumeActionList &ResumeActions));
+ MOCK_METHOD0(Halt, Status());
+ MOCK_METHOD0(Detach, Status());
+ MOCK_METHOD1(Signal, Status(int Signo));
+ MOCK_METHOD0(Kill, Status());
+ MOCK_METHOD3(AllocateMemory,
+ Status(size_t Size, uint32_t Permissions, addr_t &Addr));
+ MOCK_METHOD1(DeallocateMemory, Status(addr_t Addr));
+ MOCK_METHOD0(GetSharedLibraryInfoAddress, addr_t());
+ MOCK_METHOD0(UpdateThreads, size_t());
+ MOCK_CONST_METHOD0(GetAuxvData,
+ llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>());
+ MOCK_METHOD2(GetLoadedModuleFileSpec,
+ Status(const char *ModulePath, FileSpec &Spec));
+ MOCK_METHOD2(GetFileLoadAddress,
+ Status(const llvm::StringRef &FileName, addr_t &Addr));
+
+ const ArchSpec &GetArchitecture() const /*override*/ { return Arch; }
+ Status SetBreakpoint(lldb::addr_t Addr, uint32_t Size,
+ bool Hardware) /*override*/ {
+ if (Hardware)
+ return SetHardwareBreakpoint(Addr, Size);
+ else
+ return SetSoftwareBreakpoint(Addr, Size);
+ }
+
+ // Redirect base class Read/Write Memory methods to functions whose signatures
+ // are more mock-friendly.
+ Status ReadMemory(addr_t Addr, void *Buf, size_t Size,
+ size_t &BytesRead) /*override*/;
+ Status WriteMemory(addr_t Addr, const void *Buf, size_t Size,
+ size_t &BytesWritten) /*override*/;
+
+ MOCK_METHOD2(ReadMemory,
+ llvm::Expected<std::vector<uint8_t>>(addr_t Addr, size_t Size));
+ MOCK_METHOD2(WriteMemory,
+ llvm::Expected<size_t>(addr_t Addr,
+ llvm::ArrayRef<uint8_t> Data));
+
+ using NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode;
+ llvm::Expected<std::vector<uint8_t>> ReadMemoryWithoutTrap(addr_t Addr,
+ size_t Size);
+
+private:
+ ArchSpec Arch;
+};
+
+class FakeMemory {
+public:
+ FakeMemory(llvm::ArrayRef<uint8_t> Data) : Data(Data) {}
+ llvm::Expected<std::vector<uint8_t>> Read(addr_t Addr, size_t Size);
+ llvm::Expected<size_t> Write(addr_t Addr, llvm::ArrayRef<uint8_t> Chunk);
+
+private:
+ std::vector<uint8_t> Data;
+};
+} // namespace
+
+Status MockProcess::ReadMemory(addr_t Addr, void *Buf, size_t Size,
+ size_t &BytesRead) {
+ auto ExpectedMemory = ReadMemory(Addr, Size);
+ if (!ExpectedMemory) {
+ BytesRead = 0;
+ return Status(ExpectedMemory.takeError());
+ }
+ BytesRead = ExpectedMemory->size();
+ assert(BytesRead <= Size);
+ std::memcpy(Buf, ExpectedMemory->data(), BytesRead);
+ return Status();
+}
+
+Status MockProcess::WriteMemory(addr_t Addr, const void *Buf, size_t Size,
+ size_t &BytesWritten) {
+ auto ExpectedBytes = WriteMemory(
+ Addr, llvm::makeArrayRef(static_cast<const uint8_t *>(Buf), Size));
+ if (!ExpectedBytes) {
+ BytesWritten = 0;
+ return Status(ExpectedBytes.takeError());
+ }
+ BytesWritten = *ExpectedBytes;
+ return Status();
+}
+
+llvm::Expected<std::vector<uint8_t>>
+MockProcess::ReadMemoryWithoutTrap(addr_t Addr, size_t Size) {
+ std::vector<uint8_t> Data(Size, 0);
+ size_t BytesRead;
+ Status ST = NativeProcessProtocol::ReadMemoryWithoutTrap(
+ Addr, Data.data(), Data.size(), BytesRead);
+ if (ST.Fail())
+ return ST.ToError();
+ Data.resize(BytesRead);
+ return std::move(Data);
+}
+
+llvm::Expected<std::vector<uint8_t>> FakeMemory::Read(addr_t Addr,
+ size_t Size) {
+ if (Addr >= Data.size())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Address out of range.");
+ Size = std::min(Size, Data.size() - (size_t)Addr);
+ auto Begin = std::next(Data.begin(), Addr);
+ return std::vector<uint8_t>(Begin, std::next(Begin, Size));
+}
+
+llvm::Expected<size_t> FakeMemory::Write(addr_t Addr,
+ llvm::ArrayRef<uint8_t> Chunk) {
+ if (Addr >= Data.size())
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "Address out of range.");
+ size_t Size = std::min(Chunk.size(), Data.size() - (size_t)Addr);
+ std::copy_n(Chunk.begin(), Size, &Data[Addr]);
+ return Size;
+}
+
+TEST(NativeProcessProtocolTest, SetBreakpoint) {
+ NiceMock<MockDelegate> DummyDelegate;
+ MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux"));
+ auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));
+ InSequence S;
+ EXPECT_CALL(Process, ReadMemory(0x47, 1))
+ .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb})));
+ EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1)));
+ EXPECT_CALL(Process, ReadMemory(0x47, 1)).WillOnce(Return(ByMove(Trap)));
+ EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),
+ llvm::Succeeded());
+}
+
+TEST(NativeProcessProtocolTest, SetBreakpointFailRead) {
+ NiceMock<MockDelegate> DummyDelegate;
+ MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux"));
+ EXPECT_CALL(Process, ReadMemory(0x47, 1))
+ .WillOnce(Return(ByMove(
+ llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo"))));
+ EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),
+ llvm::Failed());
+}
+
+TEST(NativeProcessProtocolTest, SetBreakpointFailWrite) {
+ NiceMock<MockDelegate> DummyDelegate;
+ MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux"));
+ auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));
+ InSequence S;
+ EXPECT_CALL(Process, ReadMemory(0x47, 1))
+ .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb})));
+ EXPECT_CALL(Process, WriteMemory(0x47, Trap))
+ .WillOnce(Return(ByMove(
+ llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo"))));
+ EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),
+ llvm::Failed());
+}
+
+TEST(NativeProcessProtocolTest, SetBreakpointFailVerify) {
+ NiceMock<MockDelegate> DummyDelegate;
+ MockProcess Process(DummyDelegate, ArchSpec("x86_64-pc-linux"));
+ auto Trap = cantFail(Process.GetSoftwareBreakpointTrapOpcode(1));
+ InSequence S;
+ EXPECT_CALL(Process, ReadMemory(0x47, 1))
+ .WillOnce(Return(ByMove(std::vector<uint8_t>{0xbb})));
+ EXPECT_CALL(Process, WriteMemory(0x47, Trap)).WillOnce(Return(ByMove(1)));
+ EXPECT_CALL(Process, ReadMemory(0x47, 1))
+ .WillOnce(Return(ByMove(
+ llvm::createStringError(llvm::inconvertibleErrorCode(), "Foo"))));
+ EXPECT_THAT_ERROR(Process.SetBreakpoint(0x47, 0, false).ToError(),
+ llvm::Failed());
+}
+
+TEST(NativeProcessProtocolTest, ReadMemoryWithoutTrap) {
+ NiceMock<MockDelegate> DummyDelegate;
+ MockProcess Process(DummyDelegate, ArchSpec("aarch64-pc-linux"));
+ FakeMemory M{{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}};
+ EXPECT_CALL(Process, ReadMemory(_, _))
+ .WillRepeatedly(Invoke(&M, &FakeMemory::Read));
+ EXPECT_CALL(Process, WriteMemory(_, _))
+ .WillRepeatedly(Invoke(&M, &FakeMemory::Write));
+
+ EXPECT_THAT_ERROR(Process.SetBreakpoint(0x4, 0, false).ToError(),
+ llvm::Succeeded());
+ EXPECT_THAT_EXPECTED(
+ Process.ReadMemoryWithoutTrap(0, 10),
+ llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(0, 6),
+ llvm::HasValue(std::vector<uint8_t>{0, 1, 2, 3, 4, 5}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 4),
+ llvm::HasValue(std::vector<uint8_t>{6, 7, 8, 9}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(6, 2),
+ llvm::HasValue(std::vector<uint8_t>{6, 7}));
+ EXPECT_THAT_EXPECTED(Process.ReadMemoryWithoutTrap(4, 2),
+ llvm::HasValue(std::vector<uint8_t>{4, 5}));
+}
diff --git a/unittests/Host/SocketTest.cpp b/unittests/Host/SocketTest.cpp
index 59f59fc0ada7..e7e713861441 100644
--- a/unittests/Host/SocketTest.cpp
+++ b/unittests/Host/SocketTest.cpp
@@ -17,6 +17,8 @@
#include "lldb/Host/Socket.h"
#include "lldb/Host/common/TCPSocket.h"
#include "lldb/Host/common/UDPSocket.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
#ifndef LLDB_DISABLE_POSIX
#include "lldb/Host/posix/DomainSocket.h"
@@ -41,7 +43,6 @@ public:
protected:
static void AcceptThread(Socket *listen_socket,
- const char *listen_remote_address,
bool child_processes_inherit, Socket **accept_socket,
Status *error) {
*error = listen_socket->Accept(*accept_socket);
@@ -49,7 +50,7 @@ protected:
template <typename SocketType>
void CreateConnectedSockets(
- const char *listen_remote_address,
+ llvm::StringRef listen_remote_address,
const std::function<std::string(const SocketType &)> &get_connect_addr,
std::unique_ptr<SocketType> *a_up, std::unique_ptr<SocketType> *b_up) {
bool child_processes_inherit = false;
@@ -64,8 +65,8 @@ protected:
Status accept_error;
Socket *accept_socket;
std::thread accept_thread(AcceptThread, listen_socket_up.get(),
- listen_remote_address, child_processes_inherit,
- &accept_socket, &accept_error);
+ child_processes_inherit, &accept_socket,
+ &accept_error);
std::string connect_remote_address = get_connect_addr(*listen_socket_up);
std::unique_ptr<SocketType> connect_socket_up(
@@ -158,15 +159,15 @@ TEST_F(SocketTest, DecodeHostAndPort) {
#ifndef LLDB_DISABLE_POSIX
TEST_F(SocketTest, DomainListenConnectAccept) {
- char *file_name_str = tempnam(nullptr, nullptr);
- EXPECT_NE(nullptr, file_name_str);
- const std::string file_name(file_name_str);
- free(file_name_str);
+ llvm::SmallString<64> Path;
+ std::error_code EC = llvm::sys::fs::createUniqueDirectory("DomainListenConnectAccept", Path);
+ ASSERT_FALSE(EC);
+ llvm::sys::path::append(Path, "test");
std::unique_ptr<DomainSocket> socket_a_up;
std::unique_ptr<DomainSocket> socket_b_up;
CreateConnectedSockets<DomainSocket>(
- file_name.c_str(), [=](const DomainSocket &) { return file_name; },
+ Path, [=](const DomainSocket &) { return Path.str().str(); },
&socket_a_up, &socket_b_up);
}
#endif
diff --git a/unittests/Host/SymbolsTest.cpp b/unittests/Host/SymbolsTest.cpp
index 253ce39e31b5..e525f3d36801 100644
--- a/unittests/Host/SymbolsTest.cpp
+++ b/unittests/Host/SymbolsTest.cpp
@@ -9,25 +9,41 @@
#include "gtest/gtest.h"
-#include "lldb/Host/Symbols.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/Symbols.h"
using namespace lldb_private;
-TEST(SymbolsTest,
- LocateExecutableSymbolFileForUnknownExecutableAndUnknownSymbolFile) {
+namespace {
+class SymbolsTest : public ::testing::Test {
+public:
+ void SetUp() override {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
+ void TearDown() override {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
+};
+} // namespace
+
+TEST_F(
+ SymbolsTest,
+ TerminateLocateExecutableSymbolFileForUnknownExecutableAndUnknownSymbolFile) {
ModuleSpec module_spec;
FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec);
EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
}
-TEST(SymbolsTest,
- LocateExecutableSymbolFileForUnknownExecutableAndMissingSymbolFile) {
+TEST_F(SymbolsTest,
+ LocateExecutableSymbolFileForUnknownExecutableAndMissingSymbolFile) {
ModuleSpec module_spec;
// using a GUID here because the symbol file shouldn't actually exist on disk
module_spec.GetSymbolFileSpec().SetFile(
- "4A524676-B24B-4F4E-968A-551D465EBAF1.so", false,
- FileSpec::Style::native);
+ "4A524676-B24B-4F4E-968A-551D465EBAF1.so", FileSpec::Style::native);
FileSpec symbol_file_spec = Symbols::LocateExecutableSymbolFile(module_spec);
EXPECT_TRUE(symbol_file_spec.GetFilename().IsEmpty());
}
diff --git a/unittests/Host/linux/HostTest.cpp b/unittests/Host/linux/HostTest.cpp
index 7ea702d8b18a..d539dbca6eae 100644
--- a/unittests/Host/linux/HostTest.cpp
+++ b/unittests/Host/linux/HostTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Host/Host.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "gtest/gtest.h"
@@ -17,8 +18,14 @@ using namespace lldb_private;
namespace {
class HostTest : public testing::Test {
public:
- static void SetUpTestCase() { HostInfo::Initialize(); }
- static void TearDownTestCase() { HostInfo::Terminate(); }
+ static void SetUpTestCase() {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
+ static void TearDownTestCase() {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
};
} // namespace
diff --git a/unittests/Interpreter/TestCompletion.cpp b/unittests/Interpreter/TestCompletion.cpp
index 196cca8ce7bd..6cd4f682455d 100644
--- a/unittests/Interpreter/TestCompletion.cpp
+++ b/unittests/Interpreter/TestCompletion.cpp
@@ -7,9 +7,11 @@
//
//===----------------------------------------------------------------------===//
+#include "lldb/Host/FileSystem.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Utility/StringList.h"
#include "lldb/Utility/TildeExpressionResolver.h"
+
#include "gmock/gmock.h"
#include "gtest/gtest.h"
@@ -41,32 +43,43 @@ class CompletionTest : public testing::Test {
protected:
/// Unique temporary directory in which all created filesystem entities must
/// be placed. It is removed at the end of the test suite.
- static SmallString<128> BaseDir;
+ SmallString<128> BaseDir;
+ /// The working directory that we got when starting the test. Every test
+ /// should chdir into this directory first because some tests maybe chdir
+ /// into another one during their run.
static SmallString<128> OriginalWorkingDir;
- static SmallString<128> DirFoo;
- static SmallString<128> DirFooA;
- static SmallString<128> DirFooB;
- static SmallString<128> DirFooC;
- static SmallString<128> DirBar;
- static SmallString<128> DirBaz;
- static SmallString<128> DirTestFolder;
- static SmallString<128> DirNested;
-
- static SmallString<128> FileAA;
- static SmallString<128> FileAB;
- static SmallString<128> FileAC;
- static SmallString<128> FileFoo;
- static SmallString<128> FileBar;
- static SmallString<128> FileBaz;
+ SmallString<128> DirFoo;
+ SmallString<128> DirFooA;
+ SmallString<128> DirFooB;
+ SmallString<128> DirFooC;
+ SmallString<128> DirBar;
+ SmallString<128> DirBaz;
+ SmallString<128> DirTestFolder;
+ SmallString<128> DirNested;
+
+ SmallString<128> FileAA;
+ SmallString<128> FileAB;
+ SmallString<128> FileAC;
+ SmallString<128> FileFoo;
+ SmallString<128> FileBar;
+ SmallString<128> FileBaz;
+
+ void SetUp() override {
+ FileSystem::Initialize();
+
+ // chdir back into the original working dir this test binary started with.
+ // A previous test may have have changed the working dir.
+ ASSERT_NO_ERROR(fs::set_current_path(OriginalWorkingDir));
+
+ // Get the name of the current test. To prevent that by chance two tests
+ // get the same temporary directory if createUniqueDirectory fails.
+ auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+ ASSERT_TRUE(test_info != nullptr);
+ std::string name = test_info->name();
+ ASSERT_NO_ERROR(fs::createUniqueDirectory("FsCompletion-" + name, BaseDir));
- void SetUp() override { llvm::sys::fs::set_current_path(OriginalWorkingDir); }
-
- static void SetUpTestCase() {
- llvm::sys::fs::current_path(OriginalWorkingDir);
-
- ASSERT_NO_ERROR(fs::createUniqueDirectory("FsCompletion", BaseDir));
const char *DirNames[] = {"foo", "fooa", "foob", "fooc",
"bar", "baz", "test_folder", "foo/nested"};
const char *FileNames[] = {"aa1234.tmp", "ab1234.tmp", "ac1234.tmp",
@@ -92,8 +105,13 @@ protected:
}
}
- static void TearDownTestCase() {
+ static void SetUpTestCase() {
+ ASSERT_NO_ERROR(fs::current_path(OriginalWorkingDir));
+ }
+
+ void TearDown() override {
ASSERT_NO_ERROR(fs::remove_directories(BaseDir));
+ FileSystem::Terminate();
}
static bool HasEquivalentFile(const Twine &Path, const StringList &Paths) {
@@ -128,25 +146,8 @@ protected:
}
};
-SmallString<128> CompletionTest::BaseDir;
SmallString<128> CompletionTest::OriginalWorkingDir;
-
-SmallString<128> CompletionTest::DirFoo;
-SmallString<128> CompletionTest::DirFooA;
-SmallString<128> CompletionTest::DirFooB;
-SmallString<128> CompletionTest::DirFooC;
-SmallString<128> CompletionTest::DirBar;
-SmallString<128> CompletionTest::DirBaz;
-SmallString<128> CompletionTest::DirTestFolder;
-SmallString<128> CompletionTest::DirNested;
-
-SmallString<128> CompletionTest::FileAA;
-SmallString<128> CompletionTest::FileAB;
-SmallString<128> CompletionTest::FileAC;
-SmallString<128> CompletionTest::FileFoo;
-SmallString<128> CompletionTest::FileBar;
-SmallString<128> CompletionTest::FileBaz;
-}
+} // namespace
static std::vector<std::string> toVector(const StringList &SL) {
std::vector<std::string> Result;
@@ -169,11 +170,17 @@ TEST_F(CompletionTest, DirCompletionAbsolute) {
// When a directory is specified that doesn't end in a slash, it searches
// for that directory, not items under it.
- size_t Count =
- CommandCompletions::DiskDirectories(BaseDir, Results, Resolver);
+ // Sanity check that the path we complete on exists and isn't too long.
+ size_t Count = CommandCompletions::DiskDirectories(Twine(BaseDir) + "/fooa",
+ Results, Resolver);
ASSERT_EQ(1u, Count);
ASSERT_EQ(Count, Results.GetSize());
- EXPECT_TRUE(HasEquivalentFile(BaseDir, Results));
+ EXPECT_TRUE(HasEquivalentFile(DirFooA, Results));
+
+ Count = CommandCompletions::DiskDirectories(Twine(BaseDir) + "/.", Results,
+ Resolver);
+ ASSERT_EQ(0u, Count);
+ ASSERT_EQ(Count, Results.GetSize());
// When the same directory ends with a slash, it finds all children.
Count = CommandCompletions::DiskDirectories(Prefixes[0], Results, Resolver);
diff --git a/unittests/Language/CMakeLists.txt b/unittests/Language/CMakeLists.txt
index d5e17c1f2a19..3a6e5de785e5 100644
--- a/unittests/Language/CMakeLists.txt
+++ b/unittests/Language/CMakeLists.txt
@@ -1 +1,2 @@
add_subdirectory(CPlusPlus)
+add_subdirectory(Highlighting)
diff --git a/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp b/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
index 7a81b878f633..148359903c17 100644
--- a/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
+++ b/unittests/Language/CPlusPlus/CPlusPlusLanguageTest.cpp
@@ -138,7 +138,14 @@ TEST(CPlusPlusLanguage, ExtractContextAndIdentifier) {
{"std::vector<Class, std::allocator<Class>>"
"::_M_emplace_back_aux<Class const&>",
"std::vector<Class, std::allocator<Class>>",
- "_M_emplace_back_aux<Class const&>"}};
+ "_M_emplace_back_aux<Class const&>"},
+ {"`anonymous namespace'::foo", "`anonymous namespace'", "foo"},
+ {"`operator<<A>'::`2'::B<0>::operator>",
+ "`operator<<A>'::`2'::B<0>",
+ "operator>"},
+ {"`anonymous namespace'::S::<<::__l2::Foo",
+ "`anonymous namespace'::S::<<::__l2",
+ "Foo"}};
llvm::StringRef context, basename;
for (const auto &test : test_cases) {
@@ -183,4 +190,6 @@ TEST(CPlusPlusLanguage, FindAlternateFunctionManglings) {
EXPECT_THAT(FindAlternate("_ZN1A1fEa"), Contains("_ZN1A1fEc"));
EXPECT_THAT(FindAlternate("_ZN1A1fEx"), Contains("_ZN1A1fEl"));
EXPECT_THAT(FindAlternate("_ZN1A1fEy"), Contains("_ZN1A1fEm"));
+ EXPECT_THAT(FindAlternate("_ZN1A1fEai"), Contains("_ZN1A1fEci"));
+ EXPECT_THAT(FindAlternate("_bogus"), IsEmpty());
}
diff --git a/unittests/Language/Highlighting/CMakeLists.txt b/unittests/Language/Highlighting/CMakeLists.txt
new file mode 100644
index 000000000000..576f8dff10f0
--- /dev/null
+++ b/unittests/Language/Highlighting/CMakeLists.txt
@@ -0,0 +1,8 @@
+add_lldb_unittest(HighlighterTests
+ HighlighterTest.cpp
+
+ LINK_LIBS
+ lldbPluginCPlusPlusLanguage
+ lldbPluginObjCLanguage
+ lldbPluginObjCPlusPlusLanguage
+ )
diff --git a/unittests/Language/Highlighting/HighlighterTest.cpp b/unittests/Language/Highlighting/HighlighterTest.cpp
new file mode 100644
index 000000000000..3681d357259c
--- /dev/null
+++ b/unittests/Language/Highlighting/HighlighterTest.cpp
@@ -0,0 +1,293 @@
+//===-- HighlighterTest.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "lldb/Core/Highlighter.h"
+
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h"
+#include "Plugins/Language/ObjC/ObjCLanguage.h"
+#include "Plugins/Language/ObjCPlusPlus/ObjCPlusPlusLanguage.h"
+
+using namespace lldb_private;
+
+namespace {
+class HighlighterTest : public testing::Test {
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+};
+} // namespace
+
+void HighlighterTest::SetUpTestCase() {
+ // The HighlighterManager uses the language plugins under the hood, so we
+ // have to initialize them here for our test process.
+ CPlusPlusLanguage::Initialize();
+ ObjCLanguage::Initialize();
+ ObjCPlusPlusLanguage::Initialize();
+}
+
+void HighlighterTest::TearDownTestCase() {
+ CPlusPlusLanguage::Terminate();
+ ObjCLanguage::Terminate();
+ ObjCPlusPlusLanguage::Terminate();
+}
+
+static std::string getName(lldb::LanguageType type) {
+ HighlighterManager m;
+ return m.getHighlighterFor(type, "").GetName().str();
+}
+
+static std::string getName(llvm::StringRef path) {
+ HighlighterManager m;
+ return m.getHighlighterFor(lldb::eLanguageTypeUnknown, path).GetName().str();
+}
+
+TEST_F(HighlighterTest, HighlighterSelectionType) {
+ EXPECT_EQ(getName(lldb::eLanguageTypeC_plus_plus), "clang");
+ EXPECT_EQ(getName(lldb::eLanguageTypeC_plus_plus_03), "clang");
+ EXPECT_EQ(getName(lldb::eLanguageTypeC_plus_plus_11), "clang");
+ EXPECT_EQ(getName(lldb::eLanguageTypeC_plus_plus_14), "clang");
+ EXPECT_EQ(getName(lldb::eLanguageTypeObjC), "clang");
+ EXPECT_EQ(getName(lldb::eLanguageTypeObjC_plus_plus), "clang");
+
+ EXPECT_EQ(getName(lldb::eLanguageTypeUnknown), "none");
+ EXPECT_EQ(getName(lldb::eLanguageTypeJulia), "none");
+ EXPECT_EQ(getName(lldb::eLanguageTypeHaskell), "none");
+}
+
+TEST_F(HighlighterTest, HighlighterSelectionPath) {
+ EXPECT_EQ(getName("myfile.cc"), "clang");
+ EXPECT_EQ(getName("moo.cpp"), "clang");
+ EXPECT_EQ(getName("mar.cxx"), "clang");
+ EXPECT_EQ(getName("foo.C"), "clang");
+ EXPECT_EQ(getName("bar.CC"), "clang");
+ EXPECT_EQ(getName("a/dir.CC"), "clang");
+ EXPECT_EQ(getName("/a/dir.hpp"), "clang");
+ EXPECT_EQ(getName("header.h"), "clang");
+
+ EXPECT_EQ(getName(""), "none");
+ EXPECT_EQ(getName("/dev/null"), "none");
+ EXPECT_EQ(getName("Factory.java"), "none");
+ EXPECT_EQ(getName("poll.py"), "none");
+ EXPECT_EQ(getName("reducer.hs"), "none");
+}
+
+TEST_F(HighlighterTest, FallbackHighlighter) {
+ HighlighterManager mgr;
+ const Highlighter &h =
+ mgr.getHighlighterFor(lldb::eLanguageTypePascal83, "foo.pas");
+
+ HighlightStyle style;
+ style.identifier.Set("[", "]");
+ style.semicolons.Set("<", ">");
+
+ const char *code = "program Hello;";
+ std::string output = h.Highlight(style, code, llvm::Optional<size_t>());
+
+ EXPECT_STREQ(output.c_str(), code);
+}
+
+static std::string
+highlightDefault(llvm::StringRef code, HighlightStyle style,
+ llvm::Optional<size_t> cursor = llvm::Optional<size_t>()) {
+ HighlighterManager mgr;
+ return mgr.getDefaultHighlighter().Highlight(style, code, cursor);
+}
+
+TEST_F(HighlighterTest, DefaultHighlighter) {
+ const char *code = "int my_main() { return 22; } \n";
+
+ HighlightStyle style;
+ EXPECT_EQ(code, highlightDefault(code, style));
+}
+
+TEST_F(HighlighterTest, DefaultHighlighterWithCursor) {
+ HighlightStyle style;
+ style.selected.Set("<c>", "</c>");
+ EXPECT_EQ("<c>a</c> bc", highlightDefault("a bc", style, 0));
+ EXPECT_EQ("a<c> </c>bc", highlightDefault("a bc", style, 1));
+ EXPECT_EQ("a <c>b</c>c", highlightDefault("a bc", style, 2));
+ EXPECT_EQ("a b<c>c</c>", highlightDefault("a bc", style, 3));
+}
+
+TEST_F(HighlighterTest, DefaultHighlighterWithCursorOutOfBounds) {
+ HighlightStyle style;
+ style.selected.Set("<c>", "</c>");
+ EXPECT_EQ("a bc", highlightDefault("a bc", style, 4));
+}
+//------------------------------------------------------------------------------
+// Tests highlighting with the Clang highlighter.
+//------------------------------------------------------------------------------
+
+static std::string
+highlightC(llvm::StringRef code, HighlightStyle style,
+ llvm::Optional<size_t> cursor = llvm::Optional<size_t>()) {
+ HighlighterManager mgr;
+ const Highlighter &h = mgr.getHighlighterFor(lldb::eLanguageTypeC, "main.c");
+ return h.Highlight(style, code, cursor);
+}
+
+TEST_F(HighlighterTest, ClangEmptyInput) {
+ HighlightStyle s;
+ EXPECT_EQ("", highlightC("", s));
+}
+
+TEST_F(HighlighterTest, ClangScalarLiterals) {
+ HighlightStyle s;
+ s.scalar_literal.Set("<scalar>", "</scalar>");
+
+ EXPECT_EQ(" int i = <scalar>22</scalar>;", highlightC(" int i = 22;", s));
+}
+
+TEST_F(HighlighterTest, ClangStringLiterals) {
+ HighlightStyle s;
+ s.string_literal.Set("<str>", "</str>");
+
+ EXPECT_EQ("const char *f = 22 + <str>\"foo\"</str>;",
+ highlightC("const char *f = 22 + \"foo\";", s));
+}
+
+TEST_F(HighlighterTest, ClangUnterminatedString) {
+ HighlightStyle s;
+ s.string_literal.Set("<str>", "</str>");
+
+ EXPECT_EQ(" f = \"", highlightC(" f = \"", s));
+}
+
+TEST_F(HighlighterTest, Keywords) {
+ HighlightStyle s;
+ s.keyword.Set("<k>", "</k>");
+
+ EXPECT_EQ(" <k>return</k> 1; ", highlightC(" return 1; ", s));
+}
+
+TEST_F(HighlighterTest, Colons) {
+ HighlightStyle s;
+ s.colon.Set("<c>", "</c>");
+
+ EXPECT_EQ("foo<c>:</c><c>:</c>bar<c>:</c>", highlightC("foo::bar:", s));
+}
+
+TEST_F(HighlighterTest, ClangBraces) {
+ HighlightStyle s;
+ s.braces.Set("<b>", "</b>");
+
+ EXPECT_EQ("a<b>{</b><b>}</b>", highlightC("a{}", s));
+}
+
+TEST_F(HighlighterTest, ClangSquareBrackets) {
+ HighlightStyle s;
+ s.square_brackets.Set("<sb>", "</sb>");
+
+ EXPECT_EQ("a<sb>[</sb><sb>]</sb>", highlightC("a[]", s));
+}
+
+TEST_F(HighlighterTest, ClangCommas) {
+ HighlightStyle s;
+ s.comma.Set("<comma>", "</comma>");
+
+ EXPECT_EQ(" bool f = foo()<comma>,</comma> 1;",
+ highlightC(" bool f = foo(), 1;", s));
+}
+
+TEST_F(HighlighterTest, ClangPPDirectives) {
+ HighlightStyle s;
+ s.pp_directive.Set("<pp>", "</pp>");
+
+ EXPECT_EQ("<pp>#</pp><pp>include</pp><pp> </pp><pp>\"foo\"</pp><pp> </pp>//c",
+ highlightC("#include \"foo\" //c", s));
+}
+
+TEST_F(HighlighterTest, ClangComments) {
+ HighlightStyle s;
+ s.comment.Set("<cc>", "</cc>");
+
+ EXPECT_EQ(" <cc>/*com */</cc> <cc>// com /*n*/</cc>",
+ highlightC(" /*com */ // com /*n*/", s));
+}
+
+TEST_F(HighlighterTest, ClangOperators) {
+ HighlightStyle s;
+ s.operators.Set("[", "]");
+
+ EXPECT_EQ(" 1[+]2[/]a[*]f[&]x[|][~]l", highlightC(" 1+2/a*f&x|~l", s));
+}
+
+TEST_F(HighlighterTest, ClangIdentifiers) {
+ HighlightStyle s;
+ s.identifier.Set("<id>", "</id>");
+
+ EXPECT_EQ(" <id>foo</id> <id>c</id> = <id>bar</id>(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s));
+}
+
+TEST_F(HighlighterTest, ClangCursorPos) {
+ HighlightStyle s;
+ s.selected.Set("<c>", "</c>");
+
+ EXPECT_EQ("<c> </c>foo c = bar(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 0));
+ EXPECT_EQ(" <c>foo</c> c = bar(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 1));
+ EXPECT_EQ(" <c>foo</c> c = bar(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 2));
+ EXPECT_EQ(" <c>foo</c> c = bar(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 3));
+ EXPECT_EQ(" foo<c> </c>c = bar(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 4));
+ EXPECT_EQ(" foo <c>c</c> = bar(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 5));
+}
+
+TEST_F(HighlighterTest, ClangCursorPosEndOfLine) {
+ HighlightStyle s;
+ s.selected.Set("<c>", "</c>");
+
+ EXPECT_EQ("f", highlightC("f", s, 1));
+}
+
+TEST_F(HighlighterTest, ClangCursorOutOfBounds) {
+ HighlightStyle s;
+ s.selected.Set("<c>", "</c>");
+ EXPECT_EQ("f", highlightC("f", s, 2));
+ EXPECT_EQ("f", highlightC("f", s, 3));
+ EXPECT_EQ("f", highlightC("f", s, 4));
+}
+
+TEST_F(HighlighterTest, ClangCursorPosBeforeOtherToken) {
+ HighlightStyle s;
+ s.selected.Set("<c>", "</c>");
+ s.identifier.Set("<id>", "</id>");
+
+ EXPECT_EQ("<c> </c><id>foo</id> <id>c</id> = <id>bar</id>(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 0));
+}
+
+TEST_F(HighlighterTest, ClangCursorPosAfterOtherToken) {
+ HighlightStyle s;
+ s.selected.Set("<c>", "</c>");
+ s.identifier.Set("<id>", "</id>");
+
+ EXPECT_EQ(" <id>foo</id><c> </c><id>c</id> = <id>bar</id>(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 4));
+}
+
+TEST_F(HighlighterTest, ClangCursorPosInOtherToken) {
+ HighlightStyle s;
+ s.selected.Set("<c>", "</c>");
+ s.identifier.Set("<id>", "</id>");
+
+ EXPECT_EQ(" <id><c>foo</c></id> <id>c</id> = <id>bar</id>(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 1));
+ EXPECT_EQ(" <id><c>foo</c></id> <id>c</id> = <id>bar</id>(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 2));
+ EXPECT_EQ(" <id><c>foo</c></id> <id>c</id> = <id>bar</id>(); return 1;",
+ highlightC(" foo c = bar(); return 1;", s, 3));
+}
diff --git a/unittests/ObjectFile/ELF/CMakeLists.txt b/unittests/ObjectFile/ELF/CMakeLists.txt
index cfdacdcbbb88..d16dc2d58eb0 100644
--- a/unittests/ObjectFile/ELF/CMakeLists.txt
+++ b/unittests/ObjectFile/ELF/CMakeLists.txt
@@ -13,6 +13,7 @@ add_definitions(-DYAML2OBJ="$<TARGET_FILE:yaml2obj>")
set(test_inputs
early-section-headers.so
+ debug-info-relocations.pcm.yaml
sections-resolve-consistently.yaml
)
add_unittest_inputs(ObjectFileELFTests "${test_inputs}")
diff --git a/unittests/ObjectFile/ELF/Inputs/debug-info-relocations.pcm.yaml b/unittests/ObjectFile/ELF/Inputs/debug-info-relocations.pcm.yaml
new file mode 100644
index 000000000000..10bf9c2d177d
--- /dev/null
+++ b/unittests/ObjectFile/ELF/Inputs/debug-info-relocations.pcm.yaml
@@ -0,0 +1,183 @@
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_AARCH64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000004
+ Content: E0031B32C0035FD6
+ - Name: .debug_str
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 636C616E672076657273696F6E20362E302E312028746167732F52454C454153455F3630312F66696E616C2900726564756365642E68002F746D702F617364666173646673646661006600696E7400
+ - Name: .debug_abbrev
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 011101250E1305030E10171B0EB44219110112060000022E00110112064018030E3A0B3B0B271949133F190000032400030E3E0B0B0B000000
+ - Name: .debug_info
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 470000000400000000000801000000000C0000000000000000000000000000000000000000000800000002000000000000000008000000016F000000000102430000000300000000050400
+ - Name: .rela.debug_info
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .debug_info
+ Relocations:
+ - Offset: 0x0000000000000006
+ Symbol: .debug_abbrev
+ Type: R_AARCH64_ABS32
+ - Offset: 0x000000000000000C
+ Symbol: .debug_str
+ Type: R_AARCH64_ABS32
+ - Offset: 0x0000000000000012
+ Symbol: .debug_str
+ Type: R_AARCH64_ABS32
+ Addend: 45
+ - Offset: 0x0000000000000016
+ Symbol: .debug_line
+ Type: R_AARCH64_ABS32
+ - Offset: 0x000000000000001A
+ Symbol: .debug_str
+ Type: R_AARCH64_ABS32
+ Addend: 55
+ - Offset: 0x000000000000001E
+ Symbol: .text
+ Type: R_AARCH64_ABS64
+ - Offset: 0x000000000000002B
+ Symbol: .text
+ Type: R_AARCH64_ABS64
+ - Offset: 0x0000000000000039
+ Symbol: .debug_str
+ Type: R_AARCH64_ABS32
+ Addend: 73
+ - Offset: 0x0000000000000044
+ Symbol: .debug_str
+ Type: R_AARCH64_ABS32
+ Addend: 75
+ - Name: .debug_ranges
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .debug_macinfo
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+ - Name: .debug_pubnames
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 140000000200000000004B0000002A000000660000000000
+ - Name: .rela.debug_pubnames
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .debug_pubnames
+ Relocations:
+ - Offset: 0x0000000000000006
+ Symbol: .debug_info
+ Type: R_AARCH64_ABS32
+ - Name: .debug_pubtypes
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 160000000200000000004B00000043000000696E740000000000
+ - Name: .rela.debug_pubtypes
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .debug_pubtypes
+ Relocations:
+ - Offset: 0x0000000000000006
+ Symbol: .debug_info
+ Type: R_AARCH64_ABS32
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0000000000000001
+ Content: 00636C616E672076657273696F6E20362E302E312028746167732F52454C454153455F3630312F66696E616C2900
+ - Name: .note.GNU-stack
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: ''
+ - Name: .debug_frame
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000008
+ Content: 14000000FFFFFFFF04000800017C1E0C1F00000000000000140000000000000000000000000000000800000000000000
+ - Name: .rela.debug_frame
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .debug_frame
+ Relocations:
+ - Offset: 0x000000000000001C
+ Symbol: .debug_frame
+ Type: R_AARCH64_ABS32
+ - Offset: 0x0000000000000020
+ Symbol: .text
+ Type: R_AARCH64_ABS64
+ - Name: .debug_line
+ Type: SHT_PROGBITS
+ AddressAlign: 0x0000000000000001
+ Content: 3C000000040021000000010101FB0E0D00010101010000000100000100726564756365642E68000000000000090200000000000000001305030A4B0204000101
+ - Name: .rela.debug_line
+ Type: SHT_RELA
+ Link: .symtab
+ AddressAlign: 0x0000000000000008
+ Info: .debug_line
+ Relocations:
+ - Offset: 0x000000000000002E
+ Symbol: .text
+ Type: R_AARCH64_ABS64
+Symbols:
+ Local:
+ - Name: reduced.h
+ Type: STT_FILE
+ - Name: '$d.1'
+ Section: .debug_str
+ - Name: '$d.2'
+ Section: .debug_abbrev
+ - Name: '$d.3'
+ Section: .debug_info
+ - Name: '$d.4'
+ Section: .debug_macinfo
+ - Name: '$d.5'
+ Section: .debug_pubnames
+ - Name: '$d.6'
+ Section: .debug_pubtypes
+ - Name: '$d.7'
+ Section: .comment
+ - Name: '$d.8'
+ Section: .debug_frame
+ - Name: '$d.9'
+ Section: .debug_line
+ - Name: '$x.0'
+ Section: .text
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ - Name: .debug_str
+ Type: STT_SECTION
+ Section: .debug_str
+ - Name: .debug_abbrev
+ Type: STT_SECTION
+ Section: .debug_abbrev
+ - Name: .debug_info
+ Type: STT_SECTION
+ Section: .debug_info
+ - Name: .debug_frame
+ Type: STT_SECTION
+ Section: .debug_frame
+ - Name: .debug_line
+ Type: STT_SECTION
+ Section: .debug_line
+ Global:
+ - Name: f
+ Type: STT_FUNC
+ Section: .text
+ Size: 0x0000000000000008
+DynamicSymbols:
+...
diff --git a/unittests/ObjectFile/ELF/TestObjectFileELF.cpp b/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
index cf8d7042cb01..9d3b84514ce9 100644
--- a/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
+++ b/unittests/ObjectFile/ELF/TestObjectFileELF.cpp
@@ -14,7 +14,9 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Compression.h"
#include "llvm/Support/FileUtilities.h"
@@ -29,6 +31,7 @@ using namespace lldb;
class ObjectFileELFTest : public testing::Test {
public:
void SetUp() override {
+ FileSystem::Initialize();
HostInfo::Initialize();
ObjectFileELF::Initialize();
SymbolVendorELF::Initialize();
@@ -38,6 +41,7 @@ public:
SymbolVendorELF::Terminate();
ObjectFileELF::Terminate();
HostInfo::Terminate();
+ FileSystem::Terminate();
}
protected:
@@ -71,8 +75,8 @@ TEST_F(ObjectFileELFTest, SectionsResolveConsistently) {
ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size));
ASSERT_GT(size, 0u);
- ModuleSpec spec{FileSpec(obj, false)};
- spec.GetSymbolFileSpec().SetFile(obj, false, FileSpec::Style::native);
+ ModuleSpec spec{FileSpec(obj)};
+ spec.GetSymbolFileSpec().SetFile(obj, FileSpec::Style::native);
auto module_sp = std::make_shared<Module>(spec);
SectionList *list = module_sp->GetSectionList();
ASSERT_NE(nullptr, list);
@@ -131,10 +135,78 @@ Sections:
TEST_F(ObjectFileELFTest, GetModuleSpecifications_EarlySectionHeaders) {
std::string SO = GetInputFilePath("early-section-headers.so");
ModuleSpecList Specs;
- ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO, false), 0, 0, Specs));
+ ASSERT_EQ(1u, ObjectFile::GetModuleSpecifications(FileSpec(SO), 0, 0, Specs));
ModuleSpec Spec;
ASSERT_TRUE(Specs.GetModuleSpecAtIndex(0, Spec)) ;
UUID Uuid;
Uuid.SetFromStringRef("1b8a73ac238390e32a7ff4ac8ebe4d6a41ecf5c9", 20);
EXPECT_EQ(Spec.GetUUID(), Uuid);
}
+
+static void CHECK_ABS32(uint8_t *bytes, uint32_t offset, uint32_t addend) {
+ uint32_t res;
+ memcpy(&res, reinterpret_cast<uint32_t *>(bytes + offset), sizeof(uint32_t));
+ ASSERT_EQ(addend, res);
+}
+
+static void CHECK_ABS64(uint8_t *bytes, uint64_t offset, uint64_t addend) {
+ uint64_t res;
+ memcpy(&res, reinterpret_cast<uint64_t *>(bytes + offset), sizeof(uint64_t));
+ ASSERT_EQ(addend, res);
+}
+
+TEST_F(ObjectFileELFTest, TestAARCH64Relocations) {
+ std::string yaml = GetInputFilePath("debug-info-relocations.pcm.yaml");
+ llvm::SmallString<128> obj;
+ ASSERT_NO_ERROR(llvm::sys::fs::createTemporaryFile(
+ "debug-info-relocations-%%%%%%", "obj", obj));
+
+ llvm::FileRemover remover(obj);
+ llvm::StringRef args[] = {YAML2OBJ, yaml};
+ llvm::StringRef obj_ref = obj;
+ const llvm::Optional<llvm::StringRef> redirects[] = {llvm::None, obj_ref,
+ llvm::None};
+ ASSERT_EQ(0,
+ llvm::sys::ExecuteAndWait(YAML2OBJ, args, llvm::None, redirects));
+ uint64_t size;
+ ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size));
+ ASSERT_GT(size, 0u);
+
+ ModuleSpec spec{FileSpec(obj)};
+ spec.GetSymbolFileSpec().SetFile(obj, FileSpec::Style::native);
+ auto module_sp = std::make_shared<Module>(spec);
+
+ auto objfile = static_cast<ObjectFileELF *>(module_sp->GetObjectFile());
+ SectionList *section_list = objfile->GetSectionList();
+ ASSERT_NE(nullptr, section_list);
+
+ auto debug_info_sp =
+ section_list->FindSectionByName(ConstString(".debug_info"));
+ ASSERT_NE(nullptr, debug_info_sp);
+ objfile->RelocateSection(debug_info_sp.get());
+
+ DataExtractor data;
+ // length of 0x10 is not needed but length 0x0 crashes
+ objfile->GetData(0x00, 0x10, data);
+ DataBufferSP &data_buffer_sp = data.GetSharedDataBuffer();
+ uint8_t *bytes = data_buffer_sp->GetBytes();
+
+ addr_t debug_info_offset = debug_info_sp->GetFileOffset();
+ bytes += debug_info_offset;
+
+ // Sanity check - The first byte from the yaml file is 0x47
+ ASSERT_EQ(0x47, *bytes);
+
+ // .rela.debug_info contains 9 relocations:
+ // 7 R_AARCH64_ABS32 - 2 R_AARCH64_ABS64
+ // None have a value. Four have addends.
+ CHECK_ABS32(bytes, 0x6, 0);
+ CHECK_ABS32(bytes, 0xC, 0);
+ CHECK_ABS32(bytes, 0x12, 45);
+ CHECK_ABS32(bytes, 0x16, 0);
+ CHECK_ABS32(bytes, 0x1A, 55);
+ CHECK_ABS64(bytes, 0x1E, 0);
+ CHECK_ABS64(bytes, 0x2B, 0);
+ CHECK_ABS32(bytes, 0x39, 73);
+ CHECK_ABS32(bytes, 0x44, 75);
+}
diff --git a/unittests/Platform/PlatformDarwinTest.cpp b/unittests/Platform/PlatformDarwinTest.cpp
index 18cd1b76997e..a388f413ff5e 100644
--- a/unittests/Platform/PlatformDarwinTest.cpp
+++ b/unittests/Platform/PlatformDarwinTest.cpp
@@ -18,6 +18,13 @@
using namespace lldb;
using namespace lldb_private;
+struct PlatformDarwinTester : public PlatformDarwin {
+ static bool SDKSupportsModules(SDKType desired_type,
+ const lldb_private::FileSpec &sdk_path) {
+ return PlatformDarwin::SDKSupportsModules(desired_type, sdk_path);
+ }
+};
+
TEST(PlatformDarwinTest, TestParseVersionBuildDir) {
llvm::VersionTuple V;
llvm::StringRef D;
@@ -44,4 +51,22 @@ TEST(PlatformDarwinTest, TestParseVersionBuildDir) {
std::tie(V, D) = PlatformDarwin::ParseVersionBuildDir("3.4.5");
EXPECT_EQ(llvm::VersionTuple(3, 4, 5), V);
+
+ std::string base = "/Applications/Xcode.app/Contents/Developer/Platforms/";
+ EXPECT_TRUE(PlatformDarwinTester::SDKSupportsModules(
+ PlatformDarwin::SDKType::iPhoneSimulator,
+ FileSpec(
+ base +
+ "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator12.0.sdk")));
+ EXPECT_FALSE(PlatformDarwinTester::SDKSupportsModules(
+ PlatformDarwin::SDKType::iPhoneSimulator,
+ FileSpec(
+ base +
+ "iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.2.sdk")));
+ EXPECT_TRUE(PlatformDarwinTester::SDKSupportsModules(
+ PlatformDarwin::SDKType::MacOSX,
+ FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk")));
+ EXPECT_FALSE(PlatformDarwinTester::SDKSupportsModules(
+ PlatformDarwin::SDKType::MacOSX,
+ FileSpec(base + "MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk")));
}
diff --git a/unittests/Process/Linux/ProcessorTraceTest.cpp b/unittests/Process/Linux/ProcessorTraceTest.cpp
index 67381b6ddca3..4ddfa2b59be7 100644
--- a/unittests/Process/Linux/ProcessorTraceTest.cpp
+++ b/unittests/Process/Linux/ProcessorTraceTest.cpp
@@ -11,9 +11,7 @@
#include "ProcessorTrace.h"
#include "llvm/ADT/ArrayRef.h"
-// C Includes
-// C++ Includes
using namespace lldb_private;
using namespace process_linux;
diff --git a/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp b/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
index 8ab0afdb9bea..187f1b2db9a3 100644
--- a/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
+++ b/unittests/Process/gdb-remote/GDBRemoteClientBaseTest.cpp
@@ -48,7 +48,8 @@ struct TestClient : public GDBRemoteClientBase {
class GDBRemoteClientBaseTest : public GDBRemoteTest {
public:
void SetUp() override {
- ASSERT_THAT_ERROR(Connect(client, server), llvm::Succeeded());
+ ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server),
+ llvm::Succeeded());
ASSERT_EQ(TestClient::eBroadcastBitRunPacketSent,
listener_sp->StartListeningForEvents(
&client, TestClient::eBroadcastBitRunPacketSent));
diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index 41ca091c8f10..bf31f958b969 100644
--- a/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -63,7 +63,8 @@ std::string one_register_hex = "41424344";
class GDBRemoteCommunicationClientTest : public GDBRemoteTest {
public:
void SetUp() override {
- ASSERT_THAT_ERROR(Connect(client, server), llvm::Succeeded());
+ ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server),
+ llvm::Succeeded());
}
protected:
@@ -169,14 +170,14 @@ TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo) {
llvm::Triple triple("i386-pc-linux");
FileSpec file_specs[] = {
- FileSpec("/foo/bar.so", false, FileSpec::Style::posix),
- FileSpec("/foo/baz.so", false, FileSpec::Style::posix),
+ FileSpec("/foo/bar.so", FileSpec::Style::posix),
+ FileSpec("/foo/baz.so", FileSpec::Style::posix),
// This is a bit dodgy but we currently depend on GetModulesInfo not
// performing denormalization. It can go away once the users
// (DynamicLoaderPOSIXDYLD, at least) correctly set the path syntax for
// the FileSpecs they create.
- FileSpec("/foo/baw.so", false, FileSpec::Style::windows),
+ FileSpec("/foo/baw.so", FileSpec::Style::windows),
};
std::future<llvm::Optional<std::vector<ModuleSpec>>> async_result =
std::async(std::launch::async,
@@ -203,7 +204,7 @@ TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo) {
TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo_UUID20) {
llvm::Triple triple("i386-pc-linux");
- FileSpec file_spec("/foo/bar.so", false, FileSpec::Style::posix);
+ FileSpec file_spec("/foo/bar.so", FileSpec::Style::posix);
std::future<llvm::Optional<std::vector<ModuleSpec>>> async_result =
std::async(std::launch::async,
[&] { return client.GetModulesInfo(file_spec, triple); });
@@ -227,7 +228,7 @@ TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo_UUID20) {
TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfoInvalidResponse) {
llvm::Triple triple("i386-pc-linux");
- FileSpec file_spec("/foo/bar.so", false, FileSpec::Style::posix);
+ FileSpec file_spec("/foo/bar.so", FileSpec::Style::posix);
const char *invalid_responses[] = {
// no UUID
diff --git a/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp b/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
index 5ae8e700757c..fd3e93797d26 100644
--- a/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
+++ b/unittests/Process/gdb-remote/GDBRemoteCommunicationTest.cpp
@@ -30,7 +30,8 @@ public:
class GDBRemoteCommunicationTest : public GDBRemoteTest {
public:
void SetUp() override {
- ASSERT_THAT_ERROR(Connect(client, server), llvm::Succeeded());
+ ASSERT_THAT_ERROR(GDBRemoteCommunication::ConnectLocally(client, server),
+ llvm::Succeeded());
}
protected:
diff --git a/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp b/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
index 2acf72744d20..9a9d8a3be471 100644
--- a/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
+++ b/unittests/Process/gdb-remote/GDBRemoteTestUtils.cpp
@@ -9,10 +9,10 @@
#include "GDBRemoteTestUtils.h"
-#include "lldb/Host/common/TCPSocket.h"
-#include "lldb/Host/posix/ConnectionFileDescriptorPosix.h"
-
-#include <future>
+#if defined(_MSC_VER)
+#include "lldb/Host/windows/windows.h"
+#include <WinSock2.h>
+#endif
namespace lldb_private {
namespace process_gdb_remote {
@@ -30,34 +30,5 @@ void GDBRemoteTest::TearDownTestCase() {
#endif
}
-llvm::Error GDBRemoteTest::Connect(GDBRemoteCommunication &client,
- GDBRemoteCommunication &server) {
- bool child_processes_inherit = false;
- TCPSocket listen_socket(true, child_processes_inherit);
- if (llvm::Error error = listen_socket.Listen("127.0.0.1:0", 5).ToError())
- return error;
-
- Socket *accept_socket;
- std::future<Status> accept_status = std::async(
- std::launch::async, [&] { return listen_socket.Accept(accept_socket); });
-
- llvm::SmallString<32> remote_addr;
- llvm::raw_svector_ostream(remote_addr)
- << "connect://localhost:" << listen_socket.GetLocalPortNumber();
-
- std::unique_ptr<ConnectionFileDescriptor> conn_up(
- new ConnectionFileDescriptor());
- if (conn_up->Connect(remote_addr, nullptr) != lldb::eConnectionStatusSuccess)
- return llvm::make_error<llvm::StringError>("Unable to connect",
- llvm::inconvertibleErrorCode());
-
- client.SetConnection(conn_up.release());
- if (llvm::Error error = accept_status.get().ToError())
- return error;
-
- server.SetConnection(new ConnectionFileDescriptor(accept_socket));
- return llvm::Error::success();
-}
-
} // namespace process_gdb_remote
} // namespace lldb_private
diff --git a/unittests/Process/gdb-remote/GDBRemoteTestUtils.h b/unittests/Process/gdb-remote/GDBRemoteTestUtils.h
index cc17422049bc..90f95932c642 100644
--- a/unittests/Process/gdb-remote/GDBRemoteTestUtils.h
+++ b/unittests/Process/gdb-remote/GDBRemoteTestUtils.h
@@ -20,10 +20,6 @@ class GDBRemoteTest : public testing::Test {
public:
static void SetUpTestCase();
static void TearDownTestCase();
-
-protected:
- llvm::Error Connect(GDBRemoteCommunication &client,
- GDBRemoteCommunication &server);
};
struct MockServer : public GDBRemoteCommunicationServer {
diff --git a/unittests/Process/minidump/CMakeLists.txt b/unittests/Process/minidump/CMakeLists.txt
index a4ebb074b957..84071099bb77 100644
--- a/unittests/Process/minidump/CMakeLists.txt
+++ b/unittests/Process/minidump/CMakeLists.txt
@@ -13,18 +13,24 @@ add_lldb_unittest(LLDBMinidumpTests
)
set(test_inputs
+ bad_duplicate_streams.dmp
+ bad_overlapping_streams.dmp
+ fizzbuzz_no_heap.dmp
+ fizzbuzz_wow64.dmp
linux-i386.dmp
linux-x86_64.dmp
linux-x86_64_not_crashed.dmp
- fizzbuzz_no_heap.dmp
- fizzbuzz_wow64.dmp
- bad_duplicate_streams.dmp
- bad_overlapping_streams.dmp
- thread-list-padded.dmp
- thread-list-not-padded.dmp
- module-list-padded.dmp
- module-list-not-padded.dmp
+ memory-list-not-padded.dmp
memory-list-padded.dmp
- memory-list-not-padded.dmp)
+ module-list-not-padded.dmp
+ module-list-padded.dmp
+ modules-dup-min-addr.dmp
+ modules-order.dmp
+ regions-linux-map.dmp
+ regions-memlist.dmp
+ regions-memlist64.dmp
+ thread-list-not-padded.dmp
+ thread-list-padded.dmp
+ )
add_unittest_inputs(LLDBMinidumpTests "${test_inputs}")
diff --git a/unittests/Process/minidump/Inputs/dump-content.dmp b/unittests/Process/minidump/Inputs/dump-content.dmp
new file mode 100644
index 000000000000..18eb59ffb7e6
--- /dev/null
+++ b/unittests/Process/minidump/Inputs/dump-content.dmp
Binary files differ
diff --git a/unittests/Process/minidump/Inputs/modules-dup-min-addr.dmp b/unittests/Process/minidump/Inputs/modules-dup-min-addr.dmp
new file mode 100644
index 000000000000..a7a1c4afe85a
--- /dev/null
+++ b/unittests/Process/minidump/Inputs/modules-dup-min-addr.dmp
Binary files differ
diff --git a/unittests/Process/minidump/Inputs/modules-order.dmp b/unittests/Process/minidump/Inputs/modules-order.dmp
new file mode 100644
index 000000000000..cab926b21297
--- /dev/null
+++ b/unittests/Process/minidump/Inputs/modules-order.dmp
Binary files differ
diff --git a/unittests/Process/minidump/Inputs/regions-linux-map.dmp b/unittests/Process/minidump/Inputs/regions-linux-map.dmp
new file mode 100644
index 000000000000..3f1dd53d98fa
--- /dev/null
+++ b/unittests/Process/minidump/Inputs/regions-linux-map.dmp
Binary files differ
diff --git a/unittests/Process/minidump/Inputs/regions-memlist.dmp b/unittests/Process/minidump/Inputs/regions-memlist.dmp
new file mode 100644
index 000000000000..18a7862adba8
--- /dev/null
+++ b/unittests/Process/minidump/Inputs/regions-memlist.dmp
Binary files differ
diff --git a/unittests/Process/minidump/Inputs/regions-memlist64.dmp b/unittests/Process/minidump/Inputs/regions-memlist64.dmp
new file mode 100644
index 000000000000..1bb8db8464d1
--- /dev/null
+++ b/unittests/Process/minidump/Inputs/regions-memlist64.dmp
Binary files differ
diff --git a/unittests/Process/minidump/MinidumpParserTest.cpp b/unittests/Process/minidump/MinidumpParserTest.cpp
index cf4873fbc4fc..92ea20f72860 100644
--- a/unittests/Process/minidump/MinidumpParserTest.cpp
+++ b/unittests/Process/minidump/MinidumpParserTest.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-// Project includes
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "Plugins/Process/minidump/MinidumpParser.h"
@@ -16,9 +15,9 @@
#include "Plugins/Process/minidump/RegisterContextMinidump_x86_64.h"
#include "TestingSupport/TestUtilities.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/FileSpec.h"
#include "llvm/ADT/ArrayRef.h"
@@ -38,9 +37,13 @@ using namespace minidump;
class MinidumpParserTest : public testing::Test {
public:
+ void SetUp() override { FileSystem::Initialize(); }
+
+ void TearDown() override { FileSystem::Terminate(); }
+
void SetUpData(const char *minidump_filename) {
std::string filename = GetInputFilePath(minidump_filename);
- auto BufferPtr = DataBufferLLVM::CreateSliceFromPath(filename, -1, 0);
+ auto BufferPtr = FileSystem::Instance().CreateDataBuffer(filename, -1, 0);
ASSERT_NE(BufferPtr, nullptr);
llvm::Optional<MinidumpParser> optional_parser =
MinidumpParser::Create(BufferPtr);
@@ -54,7 +57,7 @@ public:
void InvalidMinidump(const char *minidump_filename, uint64_t load_size) {
std::string filename = GetInputFilePath(minidump_filename);
auto BufferPtr =
- DataBufferLLVM::CreateSliceFromPath(filename, load_size, 0);
+ FileSystem::Instance().CreateDataBuffer(filename, load_size, 0);
ASSERT_NE(BufferPtr, nullptr);
llvm::Optional<MinidumpParser> optional_parser =
@@ -89,7 +92,7 @@ TEST_F(MinidumpParserTest, GetThreadListNotPadded) {
// after the thread count.
SetUpData("thread-list-not-padded.dmp");
llvm::ArrayRef<MinidumpThread> thread_list;
-
+
thread_list = parser->GetThreads();
ASSERT_EQ(2UL, thread_list.size());
EXPECT_EQ(0x11223344UL, thread_list[0].thread_id);
@@ -297,29 +300,120 @@ TEST_F(MinidumpParserTest, FindMemoryRangeWithFullMemoryMinidump) {
EXPECT_FALSE(parser->FindMemoryRange(0x7ffe0000 + 4096).hasValue());
}
-void check_region_info(std::unique_ptr<MinidumpParser> &parser,
- const uint64_t addr, MemoryRegionInfo::OptionalBool read,
- MemoryRegionInfo::OptionalBool write,
- MemoryRegionInfo::OptionalBool exec) {
+void check_region(std::unique_ptr<MinidumpParser> &parser,
+ lldb::addr_t addr, lldb::addr_t start, lldb::addr_t end,
+ MemoryRegionInfo::OptionalBool read,
+ MemoryRegionInfo::OptionalBool write,
+ MemoryRegionInfo::OptionalBool exec,
+ MemoryRegionInfo::OptionalBool mapped,
+ ConstString name = ConstString()) {
auto range_info = parser->GetMemoryRegionInfo(addr);
- ASSERT_TRUE(range_info.hasValue());
- EXPECT_EQ(read, range_info->GetReadable());
- EXPECT_EQ(write, range_info->GetWritable());
- EXPECT_EQ(exec, range_info->GetExecutable());
+ EXPECT_EQ(start, range_info.GetRange().GetRangeBase());
+ EXPECT_EQ(end, range_info.GetRange().GetRangeEnd());
+ EXPECT_EQ(read, range_info.GetReadable());
+ EXPECT_EQ(write, range_info.GetWritable());
+ EXPECT_EQ(exec, range_info.GetExecutable());
+ EXPECT_EQ(mapped, range_info.GetMapped());
+ EXPECT_EQ(name, range_info.GetName());
}
+// Same as above function where addr == start
+void check_region(std::unique_ptr<MinidumpParser> &parser,
+ lldb::addr_t start, lldb::addr_t end,
+ MemoryRegionInfo::OptionalBool read,
+ MemoryRegionInfo::OptionalBool write,
+ MemoryRegionInfo::OptionalBool exec,
+ MemoryRegionInfo::OptionalBool mapped,
+ ConstString name = ConstString()) {
+ check_region(parser, start, start, end, read, write, exec, mapped, name);
+}
+
+
+constexpr auto yes = MemoryRegionInfo::eYes;
+constexpr auto no = MemoryRegionInfo::eNo;
+constexpr auto unknown = MemoryRegionInfo::eDontKnow;
+
TEST_F(MinidumpParserTest, GetMemoryRegionInfo) {
SetUpData("fizzbuzz_wow64.dmp");
- const auto yes = MemoryRegionInfo::eYes;
- const auto no = MemoryRegionInfo::eNo;
+ check_region(parser, 0x00000000, 0x00010000, no, no, no, no);
+ check_region(parser, 0x00010000, 0x00020000, yes, yes, no, yes);
+ check_region(parser, 0x00020000, 0x00030000, yes, yes, no, yes);
+ check_region(parser, 0x00030000, 0x00031000, yes, yes, no, yes);
+ check_region(parser, 0x00031000, 0x00040000, no, no, no, no);
+ check_region(parser, 0x00040000, 0x00041000, yes, no, no, yes);
+
+ // Check addresses contained inside ranges
+ check_region(parser, 0x00000001, 0x00000000, 0x00010000, no, no, no, no);
+ check_region(parser, 0x0000ffff, 0x00000000, 0x00010000, no, no, no, no);
+ check_region(parser, 0x00010001, 0x00010000, 0x00020000, yes, yes, no, yes);
+ check_region(parser, 0x0001ffff, 0x00010000, 0x00020000, yes, yes, no, yes);
+
+ // Test that an address after the last entry maps to rest of the memory space
+ check_region(parser, 0x7fff0000, 0x7fff0000, UINT64_MAX, no, no, no, no);
+}
- check_region_info(parser, 0x00000, no, no, no);
- check_region_info(parser, 0x10000, yes, yes, no);
- check_region_info(parser, 0x20000, yes, yes, no);
- check_region_info(parser, 0x30000, yes, yes, no);
- check_region_info(parser, 0x31000, no, no, no);
- check_region_info(parser, 0x40000, yes, no, no);
+TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemoryList) {
+ SetUpData("regions-memlist.dmp");
+ // Test we can get memory regions from the MINIDUMP_MEMORY_LIST stream when
+ // we don't have a MemoryInfoListStream.
+
+ // Test addres before the first entry comes back with nothing mapped up
+ // to first valid region info
+ check_region(parser, 0x00000000, 0x00001000, no, no, no, no);
+ check_region(parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes);
+ check_region(parser, 0x00001010, 0x00002000, no, no, no, no);
+ check_region(parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes);
+ check_region(parser, 0x00002020, UINT64_MAX, no, no, no, no);
+}
+
+TEST_F(MinidumpParserTest, GetMemoryRegionInfoFromMemory64List) {
+ SetUpData("regions-memlist64.dmp");
+ // Test we can get memory regions from the MINIDUMP_MEMORY64_LIST stream when
+ // we don't have a MemoryInfoListStream.
+
+ // Test addres before the first entry comes back with nothing mapped up
+ // to first valid region info
+ check_region(parser, 0x00000000, 0x00001000, no, no, no, no);
+ check_region(parser, 0x00001000, 0x00001010, yes, unknown, unknown, yes);
+ check_region(parser, 0x00001010, 0x00002000, no, no, no, no);
+ check_region(parser, 0x00002000, 0x00002020, yes, unknown, unknown, yes);
+ check_region(parser, 0x00002020, UINT64_MAX, no, no, no, no);
+}
+
+TEST_F(MinidumpParserTest, GetMemoryRegionInfoLinuxMaps) {
+ SetUpData("regions-linux-map.dmp");
+ // Test we can get memory regions from the linux /proc/<pid>/maps stream when
+ // we don't have a MemoryInfoListStream.
+
+ // Test addres before the first entry comes back with nothing mapped up
+ // to first valid region info
+ ConstString a("/system/bin/app_process");
+ ConstString b("/system/bin/linker");
+ ConstString c("/system/lib/liblog.so");
+ ConstString d("/system/lib/libc.so");
+ ConstString n;
+ check_region(parser, 0x00000000, 0x400d9000, no , no , no , no , n);
+ check_region(parser, 0x400d9000, 0x400db000, yes, no , yes, yes, a);
+ check_region(parser, 0x400db000, 0x400dc000, yes, no , no , yes, a);
+ check_region(parser, 0x400dc000, 0x400dd000, yes, yes, no , yes, n);
+ check_region(parser, 0x400dd000, 0x400ec000, yes, no , yes, yes, b);
+ check_region(parser, 0x400ec000, 0x400ed000, yes, no , no , yes, n);
+ check_region(parser, 0x400ed000, 0x400ee000, yes, no , no , yes, b);
+ check_region(parser, 0x400ee000, 0x400ef000, yes, yes, no , yes, b);
+ check_region(parser, 0x400ef000, 0x400fb000, yes, yes, no , yes, n);
+ check_region(parser, 0x400fb000, 0x400fc000, yes, no , yes, yes, c);
+ check_region(parser, 0x400fc000, 0x400fd000, yes, yes, yes, yes, c);
+ check_region(parser, 0x400fd000, 0x400ff000, yes, no , yes, yes, c);
+ check_region(parser, 0x400ff000, 0x40100000, yes, no , no , yes, c);
+ check_region(parser, 0x40100000, 0x40101000, yes, yes, no , yes, c);
+ check_region(parser, 0x40101000, 0x40122000, yes, no , yes, yes, d);
+ check_region(parser, 0x40122000, 0x40123000, yes, yes, yes, yes, d);
+ check_region(parser, 0x40123000, 0x40167000, yes, no , yes, yes, d);
+ check_region(parser, 0x40167000, 0x40169000, yes, no , no , yes, d);
+ check_region(parser, 0x40169000, 0x4016b000, yes, yes, no , yes, d);
+ check_region(parser, 0x4016b000, 0x40176000, yes, yes, no , yes, n);
+ check_region(parser, 0x40176000, UINT64_MAX, no , no , no , no , n);
}
// Windows Minidump tests
@@ -530,3 +624,42 @@ TEST_F(MinidumpParserTest, ConvertMinidumpContext_x86_32_wow64) {
}
}
}
+
+TEST_F(MinidumpParserTest, MinidumpDuplicateModuleMinAddress) {
+ SetUpData("modules-dup-min-addr.dmp");
+ // Test that if we have two modules in the module list:
+ // /tmp/a with range [0x2000-0x3000)
+ // /tmp/a with range [0x1000-0x2000)
+ // That we end up with one module in the filtered list with the
+ // range [0x1000-0x2000). MinidumpParser::GetFilteredModuleList() is
+ // trying to ensure that if we have the same module mentioned more than
+ // one time, we pick the one with the lowest base_of_image.
+ std::vector<const MinidumpModule *> filtered_modules =
+ parser->GetFilteredModuleList();
+ EXPECT_EQ(1u, filtered_modules.size());
+ EXPECT_EQ(0x0000000000001000u, filtered_modules[0]->base_of_image);
+}
+
+TEST_F(MinidumpParserTest, MinidumpModuleOrder) {
+ SetUpData("modules-order.dmp");
+ // Test that if we have two modules in the module list:
+ // /tmp/a with range [0x2000-0x3000)
+ // /tmp/b with range [0x1000-0x2000)
+ // That we end up with two modules in the filtered list with the same ranges
+ // and in the same order. Previous versions of the
+ // MinidumpParser::GetFilteredModuleList() function would sort all images
+ // by address and modify the order of the modules.
+ std::vector<const MinidumpModule *> filtered_modules =
+ parser->GetFilteredModuleList();
+ llvm::Optional<std::string> name;
+ EXPECT_EQ(2u, filtered_modules.size());
+ EXPECT_EQ(0x0000000000002000u, filtered_modules[0]->base_of_image);
+ name = parser->GetMinidumpString(filtered_modules[0]->module_name_rva);
+ ASSERT_TRUE((bool)name);
+ EXPECT_EQ(std::string("/tmp/a"), *name);
+ EXPECT_EQ(0x0000000000001000u, filtered_modules[1]->base_of_image);
+ name = parser->GetMinidumpString(filtered_modules[1]->module_name_rva);
+ ASSERT_TRUE((bool)name);
+ EXPECT_EQ(std::string("/tmp/b"), *name);
+}
+
diff --git a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
index 1376f268aa79..5726670b15fd 100644
--- a/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
+++ b/unittests/ScriptInterpreter/Python/PythonDataObjectsTests.cpp
@@ -167,7 +167,7 @@ TEST_F(PythonDataObjectsTest, TestDictionaryResolutionWithDot) {
}
TEST_F(PythonDataObjectsTest, TestPythonInteger) {
-// Test that integers behave correctly when wrapped by a PythonInteger.
+ // Test that integers behave correctly when wrapped by a PythonInteger.
#if PY_MAJOR_VERSION < 3
// Verify that `PythonInt` works correctly when given a PyInt object.
@@ -557,7 +557,9 @@ TEST_F(PythonDataObjectsTest, TestPythonCallableInvoke) {
}
TEST_F(PythonDataObjectsTest, TestPythonFile) {
- File file(FileSystem::DEV_NULL, File::eOpenOptionRead);
+ File file;
+ FileSystem::Instance().Open(file, FileSpec(FileSystem::DEV_NULL),
+ File::eOpenOptionRead);
PythonFile py_file(file, "r");
EXPECT_TRUE(PythonFile::Check(py_file.get()));
}
diff --git a/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index 608f3ee45e5e..7bc8f64b4853 100644
--- a/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -7,10 +7,11 @@
//
//===----------------------------------------------------------------------===//
-#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
#include "gtest/gtest.h"
#include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
+#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "PythonTestSuite.h"
@@ -18,6 +19,7 @@
using namespace lldb_private;
void PythonTestSuite::SetUp() {
+ FileSystem::Initialize();
HostInfoBase::Initialize();
// ScriptInterpreterPython::Initialize() depends on HostInfo being
// initializedso it can compute the python directory etc.
@@ -36,4 +38,6 @@ void PythonTestSuite::TearDown() {
PyGILState_Release(m_gil_state);
ScriptInterpreterPython::Terminate();
+ HostInfoBase::Terminate();
+ FileSystem::Terminate();
}
diff --git a/unittests/Symbol/TestClangASTContext.cpp b/unittests/Symbol/TestClangASTContext.cpp
index c9737fab4727..ad2cb2c9e54e 100644
--- a/unittests/Symbol/TestClangASTContext.cpp
+++ b/unittests/Symbol/TestClangASTContext.cpp
@@ -13,11 +13,11 @@
#include "clang/AST/DeclCXX.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangUtil.h"
#include "lldb/Symbol/Declaration.h"
-#include "lldb/Symbol/GoASTContext.h"
using namespace clang;
using namespace lldb;
@@ -25,9 +25,15 @@ using namespace lldb_private;
class TestClangASTContext : public testing::Test {
public:
- static void SetUpTestCase() { HostInfo::Initialize(); }
+ static void SetUpTestCase() {
+ FileSystem::Initialize();
+ HostInfo::Initialize();
+ }
- static void TearDownTestCase() { HostInfo::Terminate(); }
+ static void TearDownTestCase() {
+ HostInfo::Terminate();
+ FileSystem::Terminate();
+ }
virtual void SetUp() override {
std::string triple = HostInfo::GetTargetTriple();
@@ -232,11 +238,6 @@ TEST_F(TestClangASTContext, TestIsClangType) {
// Default constructed type should fail
EXPECT_FALSE(ClangUtil::IsClangType(CompilerType()));
-
- // Go type should fail
- GoASTContext go_ast;
- CompilerType go_type(&go_ast, bool_ctype);
- EXPECT_FALSE(ClangUtil::IsClangType(go_type));
}
TEST_F(TestClangASTContext, TestRemoveFastQualifiers) {
@@ -337,15 +338,19 @@ TEST_F(TestClangASTContext, TestRecordHasFields) {
EXPECT_NE(nullptr, non_empty_base_field_decl);
EXPECT_TRUE(ClangASTContext::RecordHasFields(non_empty_base_decl));
+ std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> bases;
+
// Test that a record with no direct fields, but fields in a base returns true
CompilerType empty_derived = m_ast->CreateRecordType(
nullptr, lldb::eAccessPublic, "EmptyDerived", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
ClangASTContext::StartTagDeclarationDefinition(empty_derived);
- CXXBaseSpecifier *non_empty_base_spec = m_ast->CreateBaseClassSpecifier(
- non_empty_base.GetOpaqueQualType(), lldb::eAccessPublic, false, false);
- bool result = m_ast->SetBaseClassesForClassType(
- empty_derived.GetOpaqueQualType(), &non_empty_base_spec, 1);
+ std::unique_ptr<clang::CXXBaseSpecifier> non_empty_base_spec =
+ m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
+ lldb::eAccessPublic, false, false);
+ bases.push_back(std::move(non_empty_base_spec));
+ bool result = m_ast->TransferBaseClasses(empty_derived.GetOpaqueQualType(),
+ std::move(bases));
ClangASTContext::CompleteTagDeclarationDefinition(empty_derived);
EXPECT_TRUE(result);
CXXRecordDecl *empty_derived_non_empty_base_cxx_decl =
@@ -353,7 +358,7 @@ TEST_F(TestClangASTContext, TestRecordHasFields) {
RecordDecl *empty_derived_non_empty_base_decl =
ClangASTContext::GetAsRecordDecl(empty_derived);
EXPECT_EQ(1u, ClangASTContext::GetNumBaseClasses(
- empty_derived_non_empty_base_cxx_decl, false));
+ empty_derived_non_empty_base_cxx_decl, false));
EXPECT_TRUE(
ClangASTContext::RecordHasFields(empty_derived_non_empty_base_decl));
@@ -363,10 +368,12 @@ TEST_F(TestClangASTContext, TestRecordHasFields) {
nullptr, lldb::eAccessPublic, "EmptyDerived2", clang::TTK_Struct,
lldb::eLanguageTypeC_plus_plus, nullptr);
ClangASTContext::StartTagDeclarationDefinition(empty_derived2);
- CXXBaseSpecifier *non_empty_vbase_spec = m_ast->CreateBaseClassSpecifier(
- non_empty_base.GetOpaqueQualType(), lldb::eAccessPublic, true, false);
- result = m_ast->SetBaseClassesForClassType(empty_derived2.GetOpaqueQualType(),
- &non_empty_vbase_spec, 1);
+ std::unique_ptr<CXXBaseSpecifier> non_empty_vbase_spec =
+ m_ast->CreateBaseClassSpecifier(non_empty_base.GetOpaqueQualType(),
+ lldb::eAccessPublic, true, false);
+ bases.push_back(std::move(non_empty_vbase_spec));
+ result = m_ast->TransferBaseClasses(empty_derived2.GetOpaqueQualType(),
+ std::move(bases));
ClangASTContext::CompleteTagDeclarationDefinition(empty_derived2);
EXPECT_TRUE(result);
CXXRecordDecl *empty_derived_non_empty_vbase_cxx_decl =
@@ -374,12 +381,9 @@ TEST_F(TestClangASTContext, TestRecordHasFields) {
RecordDecl *empty_derived_non_empty_vbase_decl =
ClangASTContext::GetAsRecordDecl(empty_derived2);
EXPECT_EQ(1u, ClangASTContext::GetNumBaseClasses(
- empty_derived_non_empty_vbase_cxx_decl, false));
+ empty_derived_non_empty_vbase_cxx_decl, false));
EXPECT_TRUE(
ClangASTContext::RecordHasFields(empty_derived_non_empty_vbase_decl));
-
- delete non_empty_base_spec;
- delete non_empty_vbase_spec;
}
TEST_F(TestClangASTContext, TemplateArguments) {
@@ -417,7 +421,7 @@ TEST_F(TestClangASTContext, TemplateArguments) {
clang::AutoTypeKeyword::Auto, false));
CompilerType int_type(m_ast->getASTContext(), m_ast->getASTContext()->IntTy);
- for(CompilerType t: { type, typedef_type, auto_type }) {
+ for (CompilerType t : {type, typedef_type, auto_type}) {
SCOPED_TRACE(t.GetTypeName().AsCString());
EXPECT_EQ(m_ast->GetTemplateArgumentKind(t.GetOpaqueQualType(), 0),
diff --git a/unittests/Symbol/TestDWARFCallFrameInfo.cpp b/unittests/Symbol/TestDWARFCallFrameInfo.cpp
index c8d560f03ded..1c127789fd47 100644
--- a/unittests/Symbol/TestDWARFCallFrameInfo.cpp
+++ b/unittests/Symbol/TestDWARFCallFrameInfo.cpp
@@ -8,20 +8,24 @@
//
//===----------------------------------------------------------------------===//
+#include "gtest/gtest.h"
+
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
#include "Plugins/Process/Utility/RegisterContext_x86.h"
+#include "TestingSupport/TestUtilities.h"
+
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/Section.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Utility/StreamString.h"
-#include "TestingSupport/TestUtilities.h"
+
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
using namespace lldb_private;
using namespace lldb;
@@ -29,6 +33,7 @@ using namespace lldb;
class DWARFCallFrameInfoTest : public testing::Test {
public:
void SetUp() override {
+ FileSystem::Initialize();
HostInfo::Initialize();
ObjectFileELF::Initialize();
}
@@ -36,6 +41,7 @@ public:
void TearDown() override {
ObjectFileELF::Terminate();
HostInfo::Terminate();
+ FileSystem::Terminate();
}
protected:
@@ -107,7 +113,7 @@ void DWARFCallFrameInfoTest::TestBasic(DWARFCallFrameInfo::Type type,
ASSERT_NO_ERROR(llvm::sys::fs::file_size(obj, size));
ASSERT_GT(size, 0u);
- auto module_sp = std::make_shared<Module>(ModuleSpec(FileSpec(obj, false)));
+ auto module_sp = std::make_shared<Module>(ModuleSpec(FileSpec(obj)));
SectionList *list = module_sp->GetSectionList();
ASSERT_NE(nullptr, list);
diff --git a/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp b/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
index 743b91a28791..fc540ff06831 100644
--- a/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
+++ b/unittests/SymbolFile/DWARF/SymbolFileDWARFTests.cpp
@@ -22,6 +22,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -38,13 +39,14 @@ public:
// Initialize and TearDown the plugin every time, so we get a brand new
// AST every time so that modifications to the AST from each test don't
// leak into the next test.
- HostInfo::Initialize();
- ObjectFilePECOFF::Initialize();
- SymbolFileDWARF::Initialize();
- ClangASTContext::Initialize();
- SymbolFilePDB::Initialize();
+FileSystem::Initialize();
+HostInfo::Initialize();
+ObjectFilePECOFF::Initialize();
+SymbolFileDWARF::Initialize();
+ClangASTContext::Initialize();
+SymbolFilePDB::Initialize();
- m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
+m_dwarf_test_exe = GetInputFilePath("test-dwarf.exe");
}
void TearDown() override {
@@ -53,6 +55,7 @@ public:
SymbolFileDWARF::Terminate();
ObjectFilePECOFF::Terminate();
HostInfo::Terminate();
+ FileSystem::Terminate();
}
protected:
@@ -61,7 +64,7 @@ protected:
TEST_F(SymbolFileDWARFTests, TestAbilitiesForDWARF) {
// Test that when we have Dwarf debug info, SymbolFileDWARF is used.
- FileSpec fspec(m_dwarf_test_exe, false);
+ FileSpec fspec(m_dwarf_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
diff --git a/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h b/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h
index d0a93d8f39e8..9d3995558233 100644
--- a/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h
+++ b/unittests/SymbolFile/PDB/Inputs/test-pdb-nested.h
@@ -3,4 +3,4 @@
inline int baz(int n) { return n + 1; }
-#endif \ No newline at end of file
+#endif
diff --git a/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp b/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
index 89d69c12963e..1b4f2c49721f 100644
--- a/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
+++ b/unittests/SymbolFile/PDB/Inputs/test-pdb-types.cpp
@@ -34,7 +34,7 @@ class NSClass {
float f;
double d;
};
-}
+} // namespace NS
class Class {
public:
@@ -48,6 +48,10 @@ int test_func(int a, int b) { return a + b; }
typedef Class ClassTypedef;
typedef NS::NSClass NSClassTypedef;
+typedef int (*FuncPointerTypedef)();
+typedef int (*VariadicFuncPointerTypedef)(char, ...);
+FuncPointerTypedef GlobalFunc;
+VariadicFuncPointerTypedef GlobalVariadicFunc;
int GlobalArray[10];
static const int sizeof_NSClass = sizeof(NS::NSClass);
@@ -57,6 +61,9 @@ static const int sizeof_Enum = sizeof(Enum);
static const int sizeof_ShortEnum = sizeof(ShortEnum);
static const int sizeof_ClassTypedef = sizeof(ClassTypedef);
static const int sizeof_NSClassTypedef = sizeof(NSClassTypedef);
+static const int sizeof_FuncPointerTypedef = sizeof(FuncPointerTypedef);
+static const int sizeof_VariadicFuncPointerTypedef =
+ sizeof(VariadicFuncPointerTypedef);
static const int sizeof_GlobalArray = sizeof(GlobalArray);
int main(int argc, char **argv) {
diff --git a/unittests/SymbolFile/PDB/Inputs/test-pdb-types.exe b/unittests/SymbolFile/PDB/Inputs/test-pdb-types.exe
index 21a4bd2b4ef5..a6a0560eb666 100644
--- a/unittests/SymbolFile/PDB/Inputs/test-pdb-types.exe
+++ b/unittests/SymbolFile/PDB/Inputs/test-pdb-types.exe
Binary files differ
diff --git a/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb b/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
index acf241bcb5d6..1a249e3635ce 100644
--- a/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
+++ b/unittests/SymbolFile/PDB/Inputs/test-pdb-types.pdb
Binary files differ
diff --git a/unittests/SymbolFile/PDB/Inputs/test-pdb.h b/unittests/SymbolFile/PDB/Inputs/test-pdb.h
index 077d9d6b1fac..c935de334d73 100644
--- a/unittests/SymbolFile/PDB/Inputs/test-pdb.h
+++ b/unittests/SymbolFile/PDB/Inputs/test-pdb.h
@@ -7,4 +7,4 @@ int bar(int n);
inline int foo(int n) { return baz(n) + 1; }
-#endif \ No newline at end of file
+#endif
diff --git a/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp b/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
index 1e867b172ee3..33b520e792e0 100644
--- a/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
+++ b/unittests/SymbolFile/PDB/SymbolFilePDBTests.cpp
@@ -22,6 +22,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompileUnit.h"
@@ -49,6 +50,7 @@ public:
::CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
+ FileSystem::Initialize();
HostInfo::Initialize();
ObjectFilePECOFF::Initialize();
SymbolFileDWARF::Initialize();
@@ -65,6 +67,7 @@ public:
SymbolFileDWARF::Terminate();
ObjectFilePECOFF::Terminate();
HostInfo::Terminate();
+ FileSystem::Terminate();
#if defined(_MSC_VER)
::CoUninitialize();
@@ -144,7 +147,7 @@ protected:
TEST_F(SymbolFilePDBTests, TestAbilitiesForPDB) {
// Test that when we have PDB debug info, SymbolFilePDB is used.
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -162,7 +165,7 @@ TEST_F(SymbolFilePDBTests, TestResolveSymbolContextBasename) {
// Test that attempting to call ResolveSymbolContext with only a basename
// finds all full paths
// with the same basename
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -170,7 +173,7 @@ TEST_F(SymbolFilePDBTests, TestResolveSymbolContextBasename) {
EXPECT_NE(nullptr, plugin);
SymbolFile *symfile = plugin->GetSymbolFile();
- FileSpec header_spec("test-pdb.cpp", false);
+ FileSpec header_spec("test-pdb.cpp");
SymbolContextList sc_list;
uint32_t result_count = symfile->ResolveSymbolContext(
header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
@@ -182,7 +185,7 @@ TEST_F(SymbolFilePDBTests, TestResolveSymbolContextFullPath) {
// Test that attempting to call ResolveSymbolContext with a full path only
// finds the one source
// file that matches the full path.
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -191,8 +194,7 @@ TEST_F(SymbolFilePDBTests, TestResolveSymbolContextFullPath) {
SymbolFile *symfile = plugin->GetSymbolFile();
FileSpec header_spec(
- R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec",
- false);
+ R"spec(D:\src\llvm\tools\lldb\unittests\SymbolFile\PDB\Inputs\test-pdb.cpp)spec");
SymbolContextList sc_list;
uint32_t result_count = symfile->ResolveSymbolContext(
header_spec, 0, false, lldb::eSymbolContextCompUnit, sc_list);
@@ -200,14 +202,13 @@ TEST_F(SymbolFilePDBTests, TestResolveSymbolContextFullPath) {
EXPECT_TRUE(ContainsCompileUnit(sc_list, header_spec));
}
-TEST_F(SymbolFilePDBTests,
- TestLookupOfHeaderFileWithInlines) {
+TEST_F(SymbolFilePDBTests, TestLookupOfHeaderFileWithInlines) {
// Test that when looking up a header file via ResolveSymbolContext (i.e. a
// file that was not by itself
// compiled, but only contributes to the combined code of other source files),
// a SymbolContext is returned
// for each compiland which has line contributions from the requested header.
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -215,10 +216,10 @@ TEST_F(SymbolFilePDBTests,
EXPECT_NE(nullptr, plugin);
SymbolFile *symfile = plugin->GetSymbolFile();
- FileSpec header_specs[] = {FileSpec("test-pdb.h", false),
- FileSpec("test-pdb-nested.h", false)};
- FileSpec main_cpp_spec("test-pdb.cpp", false);
- FileSpec alt_cpp_spec("test-pdb-alt.cpp", false);
+ FileSpec header_specs[] = {FileSpec("test-pdb.h"),
+ FileSpec("test-pdb-nested.h")};
+ FileSpec main_cpp_spec("test-pdb.cpp");
+ FileSpec alt_cpp_spec("test-pdb-alt.cpp");
for (const auto &hspec : header_specs) {
SymbolContextList sc_list;
uint32_t result_count = symfile->ResolveSymbolContext(
@@ -235,7 +236,7 @@ TEST_F(SymbolFilePDBTests, TestLookupOfHeaderFileWithNoInlines) {
// compiled, but only contributes to the combined code of other source files),
// that if check_inlines
// is false, no SymbolContexts are returned.
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -243,8 +244,8 @@ TEST_F(SymbolFilePDBTests, TestLookupOfHeaderFileWithNoInlines) {
EXPECT_NE(nullptr, plugin);
SymbolFile *symfile = plugin->GetSymbolFile();
- FileSpec header_specs[] = {FileSpec("test-pdb.h", false),
- FileSpec("test-pdb-nested.h", false)};
+ FileSpec header_specs[] = {FileSpec("test-pdb.h"),
+ FileSpec("test-pdb-nested.h")};
for (const auto &hspec : header_specs) {
SymbolContextList sc_list;
uint32_t result_count = symfile->ResolveSymbolContext(
@@ -257,21 +258,22 @@ TEST_F(SymbolFilePDBTests, TestLineTablesMatchAll) {
// Test that when calling ResolveSymbolContext with a line number of 0, all
// line entries from
// the specified files are returned.
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
SymbolVendor *plugin = module->GetSymbolVendor();
SymbolFile *symfile = plugin->GetSymbolFile();
- FileSpec source_file("test-pdb.cpp", false);
- FileSpec header1("test-pdb.h", false);
- FileSpec header2("test-pdb-nested.h", false);
+ FileSpec source_file("test-pdb.cpp");
+ FileSpec header1("test-pdb.h");
+ FileSpec header2("test-pdb-nested.h");
uint32_t cus = symfile->GetNumCompileUnits();
EXPECT_EQ(2u, cus);
SymbolContextList sc_list;
- uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
+ lldb::SymbolContextItem scope =
+ lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
uint32_t count =
symfile->ResolveSymbolContext(source_file, 0, true, scope, sc_list);
@@ -306,21 +308,22 @@ TEST_F(SymbolFilePDBTests, TestLineTablesMatchSpecific) {
// Test that when calling ResolveSymbolContext with a specific line number,
// only line entries
// which match the requested line are returned.
- FileSpec fspec(m_pdb_test_exe.c_str(), false);
+ FileSpec fspec(m_pdb_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
SymbolVendor *plugin = module->GetSymbolVendor();
SymbolFile *symfile = plugin->GetSymbolFile();
- FileSpec source_file("test-pdb.cpp", false);
- FileSpec header1("test-pdb.h", false);
- FileSpec header2("test-pdb-nested.h", false);
+ FileSpec source_file("test-pdb.cpp");
+ FileSpec header1("test-pdb.h");
+ FileSpec header2("test-pdb-nested.h");
uint32_t cus = symfile->GetNumCompileUnits();
EXPECT_EQ(2u, cus);
SymbolContextList sc_list;
- uint32_t scope = lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
+ lldb::SymbolContextItem scope =
+ lldb::eSymbolContextCompUnit | lldb::eSymbolContextLineEntry;
// First test with line 7, and verify that only line 7 entries are added.
uint32_t count =
@@ -355,7 +358,7 @@ TEST_F(SymbolFilePDBTests, TestLineTablesMatchSpecific) {
}
TEST_F(SymbolFilePDBTests, TestSimpleClassTypes) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -363,10 +366,9 @@ TEST_F(SymbolFilePDBTests, TestSimpleClassTypes) {
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
TypeMap results;
- EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class"), nullptr, false, 0,
+ EXPECT_EQ(1u, symfile->FindTypes(ConstString("Class"), nullptr, false, 0,
searched_files, results));
EXPECT_EQ(1u, results.GetSize());
lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
@@ -378,7 +380,7 @@ TEST_F(SymbolFilePDBTests, TestSimpleClassTypes) {
}
TEST_F(SymbolFilePDBTests, TestNestedClassTypes) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -386,22 +388,49 @@ TEST_F(SymbolFilePDBTests, TestNestedClassTypes) {
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
TypeMap results;
- EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("Class::NestedClass"),
- nullptr, false, 0, searched_files, results));
+
+ auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ symfile->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ EXPECT_NE(nullptr, clang_ast_ctx);
+
+ EXPECT_EQ(1u, symfile->FindTypes(ConstString("Class"), nullptr, false, 0,
+ searched_files, results));
EXPECT_EQ(1u, results.GetSize());
+
+ auto Class = results.GetTypeAtIndex(0);
+ EXPECT_TRUE(Class);
+ EXPECT_TRUE(Class->IsValidType());
+
+ auto ClassCompilerType = Class->GetFullCompilerType();
+ EXPECT_TRUE(ClassCompilerType.IsValid());
+
+ auto ClassDeclCtx = clang_ast_ctx->GetDeclContextForType(ClassCompilerType);
+ EXPECT_NE(nullptr, ClassDeclCtx);
+
+ // There are two symbols for nested classes: one belonging to enclosing class
+ // and one is global. We process correctly this case and create the same
+ // compiler type for both, but `FindTypes` may return more than one type
+ // (with the same compiler type) because the symbols have different IDs.
+ auto ClassCompilerDeclCtx = CompilerDeclContext(clang_ast_ctx, ClassDeclCtx);
+ EXPECT_LE(1u, symfile->FindTypes(ConstString("NestedClass"),
+ &ClassCompilerDeclCtx, false, 0,
+ searched_files, results));
+ EXPECT_LE(1u, results.GetSize());
+
lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
- EXPECT_EQ(ConstString("Class::NestedClass"), udt_type->GetName());
+ EXPECT_EQ(ConstString("NestedClass"), udt_type->GetName());
+
CompilerType compiler_type = udt_type->GetForwardCompilerType();
EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+
EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NestedClass"),
udt_type->GetByteSize());
}
TEST_F(SymbolFilePDBTests, TestClassInNamespace) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -409,22 +438,41 @@ TEST_F(SymbolFilePDBTests, TestClassInNamespace) {
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
TypeMap results;
- EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString("NS::NSClass"), nullptr,
- false, 0, searched_files, results));
+
+ auto clang_ast_ctx = llvm::dyn_cast_or_null<ClangASTContext>(
+ symfile->GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus));
+ EXPECT_NE(nullptr, clang_ast_ctx);
+
+ auto ast_ctx = clang_ast_ctx->getASTContext();
+ EXPECT_NE(nullptr, ast_ctx);
+
+ auto tu = ast_ctx->getTranslationUnitDecl();
+ EXPECT_NE(nullptr, tu);
+
+ symfile->ParseDeclsForContext(CompilerDeclContext(
+ clang_ast_ctx, static_cast<clang::DeclContext *>(tu)));
+
+ auto ns_namespace = symfile->FindNamespace(ConstString("NS"), nullptr);
+ EXPECT_TRUE(ns_namespace.IsValid());
+
+ EXPECT_EQ(1u, symfile->FindTypes(ConstString("NSClass"), &ns_namespace, false,
+ 0, searched_files, results));
EXPECT_EQ(1u, results.GetSize());
+
lldb::TypeSP udt_type = results.GetTypeAtIndex(0);
- EXPECT_EQ(ConstString("NS::NSClass"), udt_type->GetName());
+ EXPECT_EQ(ConstString("NSClass"), udt_type->GetName());
+
CompilerType compiler_type = udt_type->GetForwardCompilerType();
EXPECT_TRUE(ClangASTContext::IsClassType(compiler_type.GetOpaqueQualType()));
+
EXPECT_EQ(GetGlobalConstantInteger(session, "sizeof_NSClass"),
udt_type->GetByteSize());
}
TEST_F(SymbolFilePDBTests, TestEnumTypes) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -432,12 +480,11 @@ TEST_F(SymbolFilePDBTests, TestEnumTypes) {
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
const char *EnumsToCheck[] = {"Enum", "ShortEnum"};
for (auto Enum : EnumsToCheck) {
TypeMap results;
- EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Enum), nullptr, false, 0,
+ EXPECT_EQ(1u, symfile->FindTypes(ConstString(Enum), nullptr, false, 0,
searched_files, results));
EXPECT_EQ(1u, results.GetSize());
lldb::TypeSP enum_type = results.GetTypeAtIndex(0);
@@ -471,7 +518,7 @@ TEST_F(SymbolFilePDBTests, TestFunctionTypes) {
}
TEST_F(SymbolFilePDBTests, TestTypedefs) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -479,15 +526,16 @@ TEST_F(SymbolFilePDBTests, TestTypedefs) {
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
llvm::pdb::IPDBSession &session = symfile->GetPDBSession();
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
TypeMap results;
- const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef"};
+ const char *TypedefsToCheck[] = {"ClassTypedef", "NSClassTypedef",
+ "FuncPointerTypedef",
+ "VariadicFuncPointerTypedef"};
for (auto Typedef : TypedefsToCheck) {
TypeMap results;
- EXPECT_EQ(1u, symfile->FindTypes(sc, ConstString(Typedef), nullptr, false,
- 0, searched_files, results));
+ EXPECT_EQ(1u, symfile->FindTypes(ConstString(Typedef), nullptr, false, 0,
+ searched_files, results));
EXPECT_EQ(1u, results.GetSize());
lldb::TypeSP typedef_type = results.GetTypeAtIndex(0);
EXPECT_EQ(ConstString(Typedef), typedef_type->GetName());
@@ -505,7 +553,7 @@ TEST_F(SymbolFilePDBTests, TestTypedefs) {
}
TEST_F(SymbolFilePDBTests, TestRegexNameMatch) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
@@ -513,7 +561,7 @@ TEST_F(SymbolFilePDBTests, TestRegexNameMatch) {
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
TypeMap results;
-
+
symfile->FindTypesByRegex(RegularExpression(".*"), 0, results);
EXPECT_GT(results.GetSize(), 1u);
@@ -524,19 +572,18 @@ TEST_F(SymbolFilePDBTests, TestRegexNameMatch) {
}
TEST_F(SymbolFilePDBTests, TestMaxMatches) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
SymbolVendor *plugin = module->GetSymbolVendor();
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
TypeMap results;
const ConstString name("ClassTypedef");
- uint32_t num_results = symfile->FindTypes(sc, name, nullptr,
- false, 0, searched_files, results);
+ uint32_t num_results =
+ symfile->FindTypes(name, nullptr, false, 0, searched_files, results);
// Try to limit ourselves from 1 to 10 results, otherwise we could be doing
// this thousands of times.
// The idea is just to make sure that for a variety of values, the number of
@@ -544,26 +591,42 @@ TEST_F(SymbolFilePDBTests, TestMaxMatches) {
// comes out to the number we are expecting.
uint32_t iterations = std::min(num_results, 10u);
for (uint32_t i = 1; i <= iterations; ++i) {
- uint32_t num_limited_results = symfile->FindTypes(
- sc, name, nullptr, false, i, searched_files, results);
+ uint32_t num_limited_results =
+ symfile->FindTypes(name, nullptr, false, i, searched_files, results);
EXPECT_EQ(i, num_limited_results);
EXPECT_EQ(num_limited_results, results.GetSize());
}
}
TEST_F(SymbolFilePDBTests, TestNullName) {
- FileSpec fspec(m_types_test_exe.c_str(), false);
+ FileSpec fspec(m_types_test_exe);
ArchSpec aspec("i686-pc-windows");
lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
SymbolVendor *plugin = module->GetSymbolVendor();
SymbolFilePDB *symfile =
static_cast<SymbolFilePDB *>(plugin->GetSymbolFile());
- SymbolContext sc;
llvm::DenseSet<SymbolFile *> searched_files;
TypeMap results;
- uint32_t num_results = symfile->FindTypes(sc, ConstString(), nullptr, false,
- 0, searched_files, results);
+ uint32_t num_results = symfile->FindTypes(ConstString(), nullptr, false, 0,
+ searched_files, results);
EXPECT_EQ(0u, num_results);
EXPECT_EQ(0u, results.GetSize());
}
+
+TEST_F(SymbolFilePDBTests, TestFindSymbolsWithNameAndType) {
+ FileSpec fspec(m_pdb_test_exe.c_str());
+ ArchSpec aspec("i686-pc-windows");
+ lldb::ModuleSP module = std::make_shared<Module>(fspec, aspec);
+
+ SymbolContextList sc_list;
+ EXPECT_EQ(1u,
+ module->FindSymbolsWithNameAndType(ConstString("?foo@@YAHH@Z"),
+ lldb::eSymbolTypeAny, sc_list));
+ EXPECT_EQ(1u, sc_list.GetSize());
+
+ SymbolContext sc;
+ EXPECT_TRUE(sc_list.GetContextAtIndex(0, sc));
+ EXPECT_STREQ("int foo(int)",
+ sc.GetFunctionName(Mangled::ePreferDemangled).AsCString());
+}
diff --git a/unittests/Target/ModuleCacheTest.cpp b/unittests/Target/ModuleCacheTest.cpp
index 0b9e02df7817..9678bb078cef 100644
--- a/unittests/Target/ModuleCacheTest.cpp
+++ b/unittests/Target/ModuleCacheTest.cpp
@@ -5,12 +5,13 @@
#include "llvm/Support/Path.h"
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "TestingSupport/TestUtilities.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ModuleCache.h"
-#include "TestingSupport/TestUtilities.h"
using namespace lldb_private;
using namespace lldb;
@@ -44,7 +45,7 @@ static const uint32_t uuid_bytes = 20;
static const size_t module_size = 5602;
static FileSpec GetDummyRemotePath() {
- FileSpec fs("/", false, FileSpec::Style::posix);
+ FileSpec fs("/", FileSpec::Style::posix);
fs.AppendPathComponent(dummy_remote_dir);
fs.AppendPathComponent(module_name);
return fs;
@@ -65,6 +66,7 @@ static FileSpec GetSysrootView(FileSpec spec, const char *hostname) {
}
void ModuleCacheTest::SetUpTestCase() {
+ FileSystem::Initialize();
HostInfo::Initialize();
ObjectFileELF::Initialize();
@@ -75,17 +77,19 @@ void ModuleCacheTest::SetUpTestCase() {
void ModuleCacheTest::TearDownTestCase() {
ObjectFileELF::Terminate();
HostInfo::Terminate();
+ FileSystem::Terminate();
}
static void VerifyDiskState(const FileSpec &cache_dir, const char *hostname) {
FileSpec uuid_view = GetUuidView(cache_dir);
- EXPECT_TRUE(uuid_view.Exists()) << "uuid_view is: " << uuid_view.GetCString();
- EXPECT_EQ(module_size, uuid_view.GetByteSize());
+ EXPECT_TRUE(FileSystem::Instance().Exists(uuid_view))
+ << "uuid_view is: " << uuid_view.GetCString();
+ EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(uuid_view));
FileSpec sysroot_view = GetSysrootView(cache_dir, hostname);
- EXPECT_TRUE(sysroot_view.Exists()) << "sysroot_view is: "
- << sysroot_view.GetCString();
- EXPECT_EQ(module_size, sysroot_view.GetByteSize());
+ EXPECT_TRUE(FileSystem::Instance().Exists(sysroot_view))
+ << "sysroot_view is: " << sysroot_view.GetCString();
+ EXPECT_EQ(module_size, FileSystem::Instance().GetByteSize(sysroot_view));
}
void ModuleCacheTest::TryGetAndPut(const FileSpec &cache_dir,
diff --git a/unittests/Target/PathMappingListTest.cpp b/unittests/Target/PathMappingListTest.cpp
index cb807d0ca20d..42db27fdb504 100644
--- a/unittests/Target/PathMappingListTest.cpp
+++ b/unittests/Target/PathMappingListTest.cpp
@@ -19,8 +19,7 @@ namespace {
struct Matches {
FileSpec original;
FileSpec remapped;
- Matches(const char *o, const char *r)
- : original(o, false), remapped(r, false) {}
+ Matches(const char *o, const char *r) : original(o), remapped(r) {}
};
} // namespace
@@ -38,7 +37,7 @@ static void TestPathMappings(const PathMappingList &map,
std::string orig_normalized = match.original.GetPath();
EXPECT_TRUE(
map.RemapPath(ConstString(match.original.GetPath()), actual_remapped));
- EXPECT_EQ(FileSpec(actual_remapped.GetStringRef(), false), match.remapped);
+ EXPECT_EQ(FileSpec(actual_remapped.GetStringRef()), match.remapped);
FileSpec unmapped_spec;
EXPECT_TRUE(map.ReverseRemapPath(match.remapped, unmapped_spec));
std::string unmapped_path = unmapped_spec.GetPath();
diff --git a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
index f0c9cefeb7b0..735738aee0e2 100644
--- a/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
+++ b/unittests/UnwindAssembly/x86/Testx86AssemblyInspectionEngine.cpp
@@ -133,7 +133,7 @@ std::unique_ptr<x86AssemblyInspectionEngine> Geti386Inspector() {
namespace lldb_private {
static std::ostream &operator<<(std::ostream &OS,
- const UnwindPlan::Row::CFAValue &CFA) {
+ const UnwindPlan::Row::FAValue &CFA) {
StreamString S;
CFA.Dump(S, nullptr, nullptr);
return OS << S.GetData();
@@ -2368,7 +2368,7 @@ TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign8BitDisp_i386) {
ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
sample_range, plan));
- UnwindPlan::Row::CFAValue esp_plus_4, esp_plus_8, ebp_plus_8;
+ UnwindPlan::Row::FAValue esp_plus_4, esp_plus_8, ebp_plus_8;
esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);
esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);
ebp_plus_8.SetIsRegisterPlusOffset(k_ebp, 8);
@@ -2402,7 +2402,7 @@ TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) {
ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
sample_range, plan));
- UnwindPlan::Row::CFAValue rsp_plus_8, rsp_plus_16, rbp_plus_16;
+ UnwindPlan::Row::FAValue rsp_plus_8, rsp_plus_16, rbp_plus_16;
rsp_plus_8.SetIsRegisterPlusOffset(k_rsp, 8);
rsp_plus_16.SetIsRegisterPlusOffset(k_rsp, 16);
rbp_plus_16.SetIsRegisterPlusOffset(k_rbp, 16);
@@ -2416,6 +2416,65 @@ TEST_F(Testx86AssemblyInspectionEngine, TestStackRealign32BitDisp_x86_64) {
plan.GetRowForFunctionOffset(sizeof(data) - 1)->GetCFAValue());
}
+TEST_F(Testx86AssemblyInspectionEngine, TestStackRealignMSVC_i386) {
+ std::unique_ptr<x86AssemblyInspectionEngine> engine = Geti386Inspector();
+
+ uint8_t data[] = {
+ 0x53, // offset 00 -- pushl %ebx
+ 0x8b, 0xdc, // offset 01 -- movl %esp, %ebx
+ 0x83, 0xec, 0x08, // offset 03 -- subl $8, %esp
+ 0x81, 0xe4, 0x00, 0xff, 0xff, 0xff, // offset 06 -- andl $-256, %esp
+ 0x83, 0xc4, 0x04, // offset 12 -- addl $4, %esp
+ 0x55, // offset 15 -- pushl %ebp
+ 0x8b, 0xec, // offset 16 -- movl %esp, %ebp
+ 0x81, 0xec, 0x00, 0x02, 0x00, 0x00, // offset 18 -- subl $512, %esp
+ 0x89, 0x7d, 0xfc, // offset 24 -- movl %edi, -4(%ebp)
+ 0x8b, 0xe5, // offset 27 -- movl %ebp, %esp
+ 0x5d, // offset 29 -- popl %ebp
+ 0x8b, 0xe3, // offset 30 -- movl %ebx, %esp
+ 0x5b, // offset 32 -- popl %ebx
+ 0xc3 // offset 33 -- retl
+ };
+
+ AddressRange sample_range(0x1000, sizeof(data));
+ UnwindPlan plan(eRegisterKindLLDB);
+ ASSERT_TRUE(engine->GetNonCallSiteUnwindPlanFromAssembly(data, sizeof(data),
+ sample_range, plan));
+
+ UnwindPlan::Row::FAValue esp_minus_4, esp_plus_0, esp_plus_4, esp_plus_8,
+ ebx_plus_8, ebp_plus_0;
+ esp_minus_4.SetIsRegisterPlusOffset(k_esp, -4);
+ esp_plus_0.SetIsRegisterPlusOffset(k_esp, 0);
+ esp_plus_4.SetIsRegisterPlusOffset(k_esp, 4);
+ esp_plus_8.SetIsRegisterPlusOffset(k_esp, 8);
+ ebx_plus_8.SetIsRegisterPlusOffset(k_ebx, 8);
+ ebp_plus_0.SetIsRegisterPlusOffset(k_ebp, 0);
+
+ // Test CFA
+ EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(0)->GetCFAValue());
+ EXPECT_EQ(esp_plus_8, plan.GetRowForFunctionOffset(1)->GetCFAValue());
+ for (size_t i = 3; i < 33; ++i)
+ EXPECT_EQ(ebx_plus_8, plan.GetRowForFunctionOffset(i)->GetCFAValue())
+ << "i: " << i;
+ EXPECT_EQ(esp_plus_4, plan.GetRowForFunctionOffset(33)->GetCFAValue());
+
+ // Test AFA
+ EXPECT_EQ(esp_plus_0, plan.GetRowForFunctionOffset(12)->GetAFAValue());
+ EXPECT_EQ(esp_minus_4, plan.GetRowForFunctionOffset(15)->GetAFAValue());
+ EXPECT_EQ(esp_plus_0, plan.GetRowForFunctionOffset(16)->GetAFAValue());
+ for (size_t i = 18; i < 30; ++i)
+ EXPECT_EQ(ebp_plus_0, plan.GetRowForFunctionOffset(i)->GetAFAValue())
+ << "i: " << i;
+ EXPECT_EQ(esp_minus_4, plan.GetRowForFunctionOffset(30)->GetAFAValue());
+
+ // Test saved register
+ UnwindPlan::Row::RegisterLocation reg_loc;
+ EXPECT_TRUE(
+ plan.GetRowForFunctionOffset(27)->GetRegisterInfo(k_edi, reg_loc));
+ EXPECT_TRUE(reg_loc.IsAtAFAPlusOffset());
+ EXPECT_EQ(-4, reg_loc.GetOffset());
+}
+
// Give the disassembler random bytes to test that it doesn't exceed
// the bounds of the array when run under clang's address sanitizer.
TEST_F(Testx86AssemblyInspectionEngine, TestDisassemblyJunkBytes) {
diff --git a/unittests/Utility/ArchSpecTest.cpp b/unittests/Utility/ArchSpecTest.cpp
index d7397cbec531..f226af4b507a 100644
--- a/unittests/Utility/ArchSpecTest.cpp
+++ b/unittests/Utility/ArchSpecTest.cpp
@@ -171,3 +171,65 @@ TEST(ArchSpecTest, MergeFromMachOUnknown) {
A.MergeFrom(B);
ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64);
}
+
+TEST(ArchSpecTest, Compatibility) {
+ {
+ ArchSpec A("x86_64-apple-macosx10.12");
+ ArchSpec B("x86_64-apple-macosx10.12");
+ ASSERT_TRUE(A.IsExactMatch(B));
+ ASSERT_TRUE(A.IsCompatibleMatch(B));
+ }
+ {
+ // The version information is auxiliary to support availablity but
+ // doesn't affect compatibility.
+ ArchSpec A("x86_64-apple-macosx10.11");
+ ArchSpec B("x86_64-apple-macosx10.12");
+ ASSERT_TRUE(A.IsExactMatch(B));
+ ASSERT_TRUE(A.IsCompatibleMatch(B));
+ }
+ {
+ ArchSpec A("x86_64-apple-macosx10.13");
+ ArchSpec B("x86_64h-apple-macosx10.13");
+ ASSERT_FALSE(A.IsExactMatch(B));
+ ASSERT_TRUE(A.IsCompatibleMatch(B));
+ }
+ {
+ ArchSpec A("x86_64-apple-macosx");
+ ArchSpec B("x86_64-apple-ios-simulator");
+ ASSERT_FALSE(A.IsExactMatch(B));
+ ASSERT_FALSE(A.IsCompatibleMatch(B));
+ }
+ {
+ ArchSpec A("x86_64-*-*");
+ ArchSpec B("x86_64-apple-ios-simulator");
+ ASSERT_FALSE(A.IsExactMatch(B));
+ ASSERT_FALSE(A.IsCompatibleMatch(B));
+ }
+ {
+ ArchSpec A("arm64-*-*");
+ ArchSpec B("arm64-apple-ios");
+ ASSERT_FALSE(A.IsExactMatch(B));
+ // FIXME: This looks unintuitive and we should investigate whether
+ // this is the desired behavior.
+ ASSERT_FALSE(A.IsCompatibleMatch(B));
+ }
+ {
+ ArchSpec A("x86_64-*-*");
+ ArchSpec B("x86_64-apple-ios-simulator");
+ ASSERT_FALSE(A.IsExactMatch(B));
+ // FIXME: See above, though the extra environment complicates things.
+ ASSERT_FALSE(A.IsCompatibleMatch(B));
+ }
+ {
+ ArchSpec A("x86_64");
+ ArchSpec B("x86_64-apple-macosx10.14");
+ // FIXME: The exact match also looks unintuitive.
+ ASSERT_TRUE(A.IsExactMatch(B));
+ ASSERT_TRUE(A.IsCompatibleMatch(B));
+ }
+}
+
+TEST(ArchSpecTest, OperatorBool) {
+ EXPECT_FALSE(ArchSpec());
+ EXPECT_TRUE(ArchSpec("x86_64-pc-linux"));
+}
diff --git a/unittests/Core/BroadcasterTest.cpp b/unittests/Utility/BroadcasterTest.cpp
index 1613d0806009..6c9d8771dd8b 100644
--- a/unittests/Core/BroadcasterTest.cpp
+++ b/unittests/Utility/BroadcasterTest.cpp
@@ -9,10 +9,10 @@
#include "gtest/gtest.h"
-#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/Event.h"
-#include "lldb/Core/Listener.h"
-#include "lldb/Host/Predicate.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Event.h"
+#include "lldb/Utility/Listener.h"
+#include "lldb/Utility/Predicate.h"
#include <thread>
@@ -24,7 +24,7 @@ TEST(BroadcasterTest, BroadcastEvent) {
Broadcaster broadcaster(nullptr, "test-broadcaster");
std::chrono::seconds timeout(0);
- // Create a listener, sign it up, make sure it recieves an event.
+ // Create a listener, sign it up, make sure it receives an event.
ListenerSP listener1_sp = Listener::MakeListener("test-listener1");
const uint32_t event_mask1 = 1;
EXPECT_EQ(event_mask1,
diff --git a/unittests/Utility/CMakeLists.txt b/unittests/Utility/CMakeLists.txt
index 4812d41ea753..b3970fe3d7b5 100644
--- a/unittests/Utility/CMakeLists.txt
+++ b/unittests/Utility/CMakeLists.txt
@@ -3,19 +3,30 @@ add_lldb_unittest(UtilityTests
ArgsTest.cpp
OptionsWithRawTest.cpp
ArchSpecTest.cpp
+ BroadcasterTest.cpp
CleanUpTest.cpp
ConstStringTest.cpp
CompletionRequestTest.cpp
+ DataExtractorTest.cpp
EnvironmentTest.cpp
+ EventTest.cpp
FileSpecTest.cpp
FlagsTest.cpp
JSONTest.cpp
+ ListenerTest.cpp
LogTest.cpp
NameMatchesTest.cpp
+ PredicateTest.cpp
+ RegisterValueTest.cpp
+ ReproducerTest.cpp
+ ScalarTest.cpp
+ StateTest.cpp
StatusTest.cpp
StreamTeeTest.cpp
StreamTest.cpp
StringExtractorTest.cpp
+ StringLexerTest.cpp
+ StringListTest.cpp
StructuredDataTest.cpp
TildeExpressionResolverTest.cpp
TimeoutTest.cpp
@@ -28,6 +39,7 @@ add_lldb_unittest(UtilityTests
LINK_LIBS
lldbUtility
lldbUtilityHelpers
+ LLVMTestingSupport
LINK_COMPONENTS
Support
)
diff --git a/unittests/Utility/CompletionRequestTest.cpp b/unittests/Utility/CompletionRequestTest.cpp
index 58dfab0da508..bdf3c4d056fb 100644
--- a/unittests/Utility/CompletionRequestTest.cpp
+++ b/unittests/Utility/CompletionRequestTest.cpp
@@ -20,9 +20,11 @@ TEST(CompletionRequest, Constructor) {
const int match_start = 2345;
const int match_max_return = 12345;
StringList matches;
+ CompletionResult result;
CompletionRequest request(command, cursor_pos, match_start, match_max_return,
- matches);
+ result);
+ result.GetMatches(matches);
EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str());
EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
@@ -41,29 +43,39 @@ TEST(CompletionRequest, DuplicateFiltering) {
const unsigned cursor_pos = 3;
StringList matches;
- CompletionRequest request(command, cursor_pos, 0, 0, matches);
+ CompletionResult result;
+ CompletionRequest request(command, cursor_pos, 0, 0, result);
+ result.GetMatches(matches);
EXPECT_EQ(0U, request.GetNumberOfMatches());
// Add foo twice
request.AddCompletion("foo");
+ result.GetMatches(matches);
+
EXPECT_EQ(1U, request.GetNumberOfMatches());
EXPECT_EQ(1U, matches.GetSize());
EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
request.AddCompletion("foo");
+ result.GetMatches(matches);
+
EXPECT_EQ(1U, request.GetNumberOfMatches());
EXPECT_EQ(1U, matches.GetSize());
EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
// Add bar twice
request.AddCompletion("bar");
+ result.GetMatches(matches);
+
EXPECT_EQ(2U, request.GetNumberOfMatches());
EXPECT_EQ(2U, matches.GetSize());
EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
request.AddCompletion("bar");
+ result.GetMatches(matches);
+
EXPECT_EQ(2U, request.GetNumberOfMatches());
EXPECT_EQ(2U, matches.GetSize());
EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
@@ -71,6 +83,8 @@ TEST(CompletionRequest, DuplicateFiltering) {
// Add foo again.
request.AddCompletion("foo");
+ result.GetMatches(matches);
+
EXPECT_EQ(2U, request.GetNumberOfMatches());
EXPECT_EQ(2U, matches.GetSize());
EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
@@ -78,6 +92,8 @@ TEST(CompletionRequest, DuplicateFiltering) {
// Add something with an existing prefix
request.AddCompletion("foobar");
+ result.GetMatches(matches);
+
EXPECT_EQ(3U, request.GetNumberOfMatches());
EXPECT_EQ(3U, matches.GetSize());
EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
@@ -85,12 +101,89 @@ TEST(CompletionRequest, DuplicateFiltering) {
EXPECT_STREQ("foobar", matches.GetStringAtIndex(2));
}
+TEST(CompletionRequest, DuplicateFilteringWithComments) {
+ std::string command = "a bad c";
+ const unsigned cursor_pos = 3;
+ StringList matches, descriptions;
+
+ CompletionResult result;
+ CompletionRequest request(command, cursor_pos, 0, 0, result);
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
+
+ EXPECT_EQ(0U, request.GetNumberOfMatches());
+
+ // Add foo twice with same comment
+ request.AddCompletion("foo", "comment");
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
+
+ EXPECT_EQ(1U, request.GetNumberOfMatches());
+ EXPECT_EQ(1U, matches.GetSize());
+ EXPECT_EQ(1U, descriptions.GetSize());
+ EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
+ EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
+
+ request.AddCompletion("foo", "comment");
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
+
+ EXPECT_EQ(1U, request.GetNumberOfMatches());
+ EXPECT_EQ(1U, matches.GetSize());
+ EXPECT_EQ(1U, descriptions.GetSize());
+ EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
+ EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
+
+ // Add bar twice with different comments
+ request.AddCompletion("bar", "comment");
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
+
+ EXPECT_EQ(2U, request.GetNumberOfMatches());
+ EXPECT_EQ(2U, matches.GetSize());
+ EXPECT_EQ(2U, descriptions.GetSize());
+ EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
+
+ request.AddCompletion("bar", "another comment");
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
+
+ EXPECT_EQ(3U, request.GetNumberOfMatches());
+ EXPECT_EQ(3U, matches.GetSize());
+ EXPECT_EQ(3U, descriptions.GetSize());
+ EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
+ EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
+ EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", matches.GetStringAtIndex(2));
+ EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2));
+
+ // Add foo again with no comment
+ request.AddCompletion("foo");
+ result.GetMatches(matches);
+ result.GetDescriptions(descriptions);
+
+ EXPECT_EQ(4U, request.GetNumberOfMatches());
+ EXPECT_EQ(4U, matches.GetSize());
+ EXPECT_EQ(4U, descriptions.GetSize());
+ EXPECT_STREQ("foo", matches.GetStringAtIndex(0));
+ EXPECT_STREQ("comment", descriptions.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", matches.GetStringAtIndex(1));
+ EXPECT_STREQ("comment", descriptions.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", matches.GetStringAtIndex(2));
+ EXPECT_STREQ("another comment", descriptions.GetStringAtIndex(2));
+ EXPECT_STREQ("foo", matches.GetStringAtIndex(3));
+ EXPECT_STREQ("", descriptions.GetStringAtIndex(3));
+}
+
TEST(CompletionRequest, TestCompletionOwnership) {
std::string command = "a bad c";
const unsigned cursor_pos = 3;
StringList matches;
- CompletionRequest request(command, cursor_pos, 0, 0, matches);
+ CompletionResult result;
+ CompletionRequest request(command, cursor_pos, 0, 0, result);
std::string Temporary = "bar";
request.AddCompletion(Temporary);
@@ -98,6 +191,7 @@ TEST(CompletionRequest, TestCompletionOwnership) {
// shouldn't influence anything.
Temporary[0] = 'f';
+ result.GetMatches(matches);
EXPECT_EQ(1U, request.GetNumberOfMatches());
EXPECT_STREQ("bar", matches.GetStringAtIndex(0));
}
diff --git a/unittests/Utility/ConstStringTest.cpp b/unittests/Utility/ConstStringTest.cpp
index 454f656760ca..2bae896002bc 100644
--- a/unittests/Utility/ConstStringTest.cpp
+++ b/unittests/Utility/ConstStringTest.cpp
@@ -16,3 +16,77 @@ using namespace lldb_private;
TEST(ConstStringTest, format_provider) {
EXPECT_EQ("foo", llvm::formatv("{0}", ConstString("foo")).str());
}
+
+TEST(ConstStringTest, MangledCounterpart) {
+ ConstString uvw("uvw");
+ ConstString counterpart;
+ EXPECT_FALSE(uvw.GetMangledCounterpart(counterpart));
+ EXPECT_EQ("", counterpart.GetStringRef());
+
+ ConstString xyz;
+ xyz.SetStringWithMangledCounterpart("xyz", uvw);
+ EXPECT_EQ("xyz", xyz.GetStringRef());
+
+ EXPECT_TRUE(xyz.GetMangledCounterpart(counterpart));
+ EXPECT_EQ("uvw", counterpart.GetStringRef());
+
+ EXPECT_TRUE(uvw.GetMangledCounterpart(counterpart));
+ EXPECT_EQ("xyz", counterpart.GetStringRef());
+}
+
+TEST(ConstStringTest, UpdateMangledCounterpart) {
+ { // Add counterpart
+ ConstString some1;
+ some1.SetStringWithMangledCounterpart("some", ConstString(""));
+ }
+ { // Overwrite empty string
+ ConstString some2;
+ some2.SetStringWithMangledCounterpart("some", ConstString("one"));
+ }
+ { // Overwrite with identical value
+ ConstString some2;
+ some2.SetStringWithMangledCounterpart("some", ConstString("one"));
+ }
+ { // Check counterpart is set
+ ConstString counterpart;
+ EXPECT_TRUE(ConstString("some").GetMangledCounterpart(counterpart));
+ EXPECT_EQ("one", counterpart.GetStringRef());
+ }
+}
+
+TEST(ConstStringTest, FromMidOfBufferStringRef) {
+ // StringRef's into bigger buffer: no null termination
+ const char *buffer = "abcdefghi";
+ llvm::StringRef foo_ref(buffer, 3);
+ llvm::StringRef bar_ref(buffer + 3, 3);
+
+ ConstString foo(foo_ref);
+
+ ConstString bar;
+ bar.SetStringWithMangledCounterpart(bar_ref, foo);
+ EXPECT_EQ("def", bar.GetStringRef());
+
+ ConstString counterpart;
+ EXPECT_TRUE(bar.GetMangledCounterpart(counterpart));
+ EXPECT_EQ("abc", counterpart.GetStringRef());
+
+ EXPECT_TRUE(foo.GetMangledCounterpart(counterpart));
+ EXPECT_EQ("def", counterpart.GetStringRef());
+}
+
+TEST(ConstStringTest, NullAndEmptyStates) {
+ ConstString foo("foo");
+ EXPECT_FALSE(!foo);
+ EXPECT_FALSE(foo.IsEmpty());
+ EXPECT_FALSE(foo.IsNull());
+
+ ConstString empty("");
+ EXPECT_TRUE(!empty);
+ EXPECT_TRUE(empty.IsEmpty());
+ EXPECT_FALSE(empty.IsNull());
+
+ ConstString null;
+ EXPECT_TRUE(!null);
+ EXPECT_TRUE(null.IsEmpty());
+ EXPECT_TRUE(null.IsNull());
+}
diff --git a/unittests/Core/DataExtractorTest.cpp b/unittests/Utility/DataExtractorTest.cpp
index 0267f6d14056..0267f6d14056 100644
--- a/unittests/Core/DataExtractorTest.cpp
+++ b/unittests/Utility/DataExtractorTest.cpp
diff --git a/unittests/Core/EventTest.cpp b/unittests/Utility/EventTest.cpp
index 32c6f4b1ce4a..57e934ba8e42 100644
--- a/unittests/Core/EventTest.cpp
+++ b/unittests/Utility/EventTest.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Core/Event.h"
+#include "lldb/Utility/Event.h"
#include "lldb/Utility/StreamString.h"
#include "gtest/gtest.h"
diff --git a/unittests/Utility/FileSpecTest.cpp b/unittests/Utility/FileSpecTest.cpp
index a271229b2e03..eae3a09b140d 100644
--- a/unittests/Utility/FileSpecTest.cpp
+++ b/unittests/Utility/FileSpecTest.cpp
@@ -14,92 +14,91 @@
using namespace lldb_private;
TEST(FileSpecTest, FileAndDirectoryComponents) {
- FileSpec fs_posix("/foo/bar", false, FileSpec::Style::posix);
+ FileSpec fs_posix("/foo/bar", FileSpec::Style::posix);
EXPECT_STREQ("/foo/bar", fs_posix.GetCString());
EXPECT_STREQ("/foo", fs_posix.GetDirectory().GetCString());
EXPECT_STREQ("bar", fs_posix.GetFilename().GetCString());
- FileSpec fs_windows("F:\\bar", false, FileSpec::Style::windows);
+ FileSpec fs_windows("F:\\bar", FileSpec::Style::windows);
EXPECT_STREQ("F:\\bar", fs_windows.GetCString());
// EXPECT_STREQ("F:\\", fs_windows.GetDirectory().GetCString()); // It returns
// "F:/"
EXPECT_STREQ("bar", fs_windows.GetFilename().GetCString());
- FileSpec fs_posix_root("/", false, FileSpec::Style::posix);
+ FileSpec fs_posix_root("/", FileSpec::Style::posix);
EXPECT_STREQ("/", fs_posix_root.GetCString());
EXPECT_EQ(nullptr, fs_posix_root.GetDirectory().GetCString());
EXPECT_STREQ("/", fs_posix_root.GetFilename().GetCString());
- FileSpec fs_net_drive("//net", false, FileSpec::Style::posix);
+ FileSpec fs_net_drive("//net", FileSpec::Style::posix);
EXPECT_STREQ("//net", fs_net_drive.GetCString());
EXPECT_EQ(nullptr, fs_net_drive.GetDirectory().GetCString());
EXPECT_STREQ("//net", fs_net_drive.GetFilename().GetCString());
- FileSpec fs_net_root("//net/", false, FileSpec::Style::posix);
+ FileSpec fs_net_root("//net/", FileSpec::Style::posix);
EXPECT_STREQ("//net/", fs_net_root.GetCString());
EXPECT_STREQ("//net", fs_net_root.GetDirectory().GetCString());
EXPECT_STREQ("/", fs_net_root.GetFilename().GetCString());
- FileSpec fs_windows_drive("F:", false, FileSpec::Style::windows);
+ FileSpec fs_windows_drive("F:", FileSpec::Style::windows);
EXPECT_STREQ("F:", fs_windows_drive.GetCString());
EXPECT_EQ(nullptr, fs_windows_drive.GetDirectory().GetCString());
EXPECT_STREQ("F:", fs_windows_drive.GetFilename().GetCString());
- FileSpec fs_windows_root("F:\\", false, FileSpec::Style::windows);
+ FileSpec fs_windows_root("F:\\", FileSpec::Style::windows);
EXPECT_STREQ("F:\\", fs_windows_root.GetCString());
EXPECT_STREQ("F:", fs_windows_root.GetDirectory().GetCString());
// EXPECT_STREQ("\\", fs_windows_root.GetFilename().GetCString()); // It
// returns "/"
- FileSpec fs_posix_long("/foo/bar/baz", false, FileSpec::Style::posix);
+ FileSpec fs_posix_long("/foo/bar/baz", FileSpec::Style::posix);
EXPECT_STREQ("/foo/bar/baz", fs_posix_long.GetCString());
EXPECT_STREQ("/foo/bar", fs_posix_long.GetDirectory().GetCString());
EXPECT_STREQ("baz", fs_posix_long.GetFilename().GetCString());
- FileSpec fs_windows_long("F:\\bar\\baz", false, FileSpec::Style::windows);
+ FileSpec fs_windows_long("F:\\bar\\baz", FileSpec::Style::windows);
EXPECT_STREQ("F:\\bar\\baz", fs_windows_long.GetCString());
// EXPECT_STREQ("F:\\bar", fs_windows_long.GetDirectory().GetCString()); // It
// returns "F:/bar"
EXPECT_STREQ("baz", fs_windows_long.GetFilename().GetCString());
- FileSpec fs_posix_trailing_slash("/foo/bar/", false, FileSpec::Style::posix);
+ FileSpec fs_posix_trailing_slash("/foo/bar/", FileSpec::Style::posix);
EXPECT_STREQ("/foo/bar", fs_posix_trailing_slash.GetCString());
EXPECT_STREQ("/foo", fs_posix_trailing_slash.GetDirectory().GetCString());
EXPECT_STREQ("bar", fs_posix_trailing_slash.GetFilename().GetCString());
- FileSpec fs_windows_trailing_slash("F:\\bar\\", false,
- FileSpec::Style::windows);
+ FileSpec fs_windows_trailing_slash("F:\\bar\\", FileSpec::Style::windows);
EXPECT_STREQ("F:\\bar", fs_windows_trailing_slash.GetCString());
EXPECT_STREQ("bar", fs_windows_trailing_slash.GetFilename().GetCString());
}
TEST(FileSpecTest, AppendPathComponent) {
- FileSpec fs_posix("/foo", false, FileSpec::Style::posix);
+ FileSpec fs_posix("/foo", FileSpec::Style::posix);
fs_posix.AppendPathComponent("bar");
EXPECT_STREQ("/foo/bar", fs_posix.GetCString());
EXPECT_STREQ("/foo", fs_posix.GetDirectory().GetCString());
EXPECT_STREQ("bar", fs_posix.GetFilename().GetCString());
- FileSpec fs_posix_2("/foo", false, FileSpec::Style::posix);
+ FileSpec fs_posix_2("/foo", FileSpec::Style::posix);
fs_posix_2.AppendPathComponent("//bar/baz");
EXPECT_STREQ("/foo/bar/baz", fs_posix_2.GetCString());
EXPECT_STREQ("/foo/bar", fs_posix_2.GetDirectory().GetCString());
EXPECT_STREQ("baz", fs_posix_2.GetFilename().GetCString());
- FileSpec fs_windows("F:\\bar", false, FileSpec::Style::windows);
+ FileSpec fs_windows("F:\\bar", FileSpec::Style::windows);
fs_windows.AppendPathComponent("baz");
EXPECT_STREQ("F:\\bar\\baz", fs_windows.GetCString());
// EXPECT_STREQ("F:\\bar", fs_windows.GetDirectory().GetCString()); // It
// returns "F:/bar"
EXPECT_STREQ("baz", fs_windows.GetFilename().GetCString());
- FileSpec fs_posix_root("/", false, FileSpec::Style::posix);
+ FileSpec fs_posix_root("/", FileSpec::Style::posix);
fs_posix_root.AppendPathComponent("bar");
EXPECT_STREQ("/bar", fs_posix_root.GetCString());
EXPECT_STREQ("/", fs_posix_root.GetDirectory().GetCString());
EXPECT_STREQ("bar", fs_posix_root.GetFilename().GetCString());
- FileSpec fs_windows_root("F:\\", false, FileSpec::Style::windows);
+ FileSpec fs_windows_root("F:\\", FileSpec::Style::windows);
fs_windows_root.AppendPathComponent("bar");
EXPECT_STREQ("F:\\bar", fs_windows_root.GetCString());
// EXPECT_STREQ("F:\\", fs_windows_root.GetDirectory().GetCString()); // It
@@ -108,7 +107,7 @@ TEST(FileSpecTest, AppendPathComponent) {
}
TEST(FileSpecTest, CopyByAppendingPathComponent) {
- FileSpec fs = FileSpec("/foo", false, FileSpec::Style::posix)
+ FileSpec fs = FileSpec("/foo", FileSpec::Style::posix)
.CopyByAppendingPathComponent("bar");
EXPECT_STREQ("/foo/bar", fs.GetCString());
EXPECT_STREQ("/foo", fs.GetDirectory().GetCString());
@@ -116,30 +115,30 @@ TEST(FileSpecTest, CopyByAppendingPathComponent) {
}
TEST(FileSpecTest, PrependPathComponent) {
- FileSpec fs_posix("foo", false, FileSpec::Style::posix);
+ FileSpec fs_posix("foo", FileSpec::Style::posix);
fs_posix.PrependPathComponent("/bar");
EXPECT_STREQ("/bar/foo", fs_posix.GetCString());
- FileSpec fs_posix_2("foo/bar", false, FileSpec::Style::posix);
+ FileSpec fs_posix_2("foo/bar", FileSpec::Style::posix);
fs_posix_2.PrependPathComponent("/baz");
EXPECT_STREQ("/baz/foo/bar", fs_posix_2.GetCString());
- FileSpec fs_windows("baz", false, FileSpec::Style::windows);
+ FileSpec fs_windows("baz", FileSpec::Style::windows);
fs_windows.PrependPathComponent("F:\\bar");
EXPECT_STREQ("F:\\bar\\baz", fs_windows.GetCString());
- FileSpec fs_posix_root("bar", false, FileSpec::Style::posix);
+ FileSpec fs_posix_root("bar", FileSpec::Style::posix);
fs_posix_root.PrependPathComponent("/");
EXPECT_STREQ("/bar", fs_posix_root.GetCString());
- FileSpec fs_windows_root("bar", false, FileSpec::Style::windows);
+ FileSpec fs_windows_root("bar", FileSpec::Style::windows);
fs_windows_root.PrependPathComponent("F:\\");
EXPECT_STREQ("F:\\bar", fs_windows_root.GetCString());
}
TEST(FileSpecTest, EqualSeparator) {
- FileSpec backward("C:\\foo\\bar", false, FileSpec::Style::windows);
- FileSpec forward("C:/foo/bar", false, FileSpec::Style::windows);
+ FileSpec backward("C:\\foo\\bar", FileSpec::Style::windows);
+ FileSpec forward("C:/foo/bar", FileSpec::Style::windows);
EXPECT_EQ(forward, backward);
}
@@ -155,8 +154,8 @@ TEST(FileSpecTest, EqualDotsWindows) {
};
for (const auto &test : tests) {
- FileSpec one(test.first, false, FileSpec::Style::windows);
- FileSpec two(test.second, false, FileSpec::Style::windows);
+ FileSpec one(test.first, FileSpec::Style::windows);
+ FileSpec two(test.second, FileSpec::Style::windows);
EXPECT_EQ(one, two);
}
}
@@ -171,8 +170,8 @@ TEST(FileSpecTest, EqualDotsPosix) {
};
for (const auto &test : tests) {
- FileSpec one(test.first, false, FileSpec::Style::posix);
- FileSpec two(test.second, false, FileSpec::Style::posix);
+ FileSpec one(test.first, FileSpec::Style::posix);
+ FileSpec two(test.second, FileSpec::Style::posix);
EXPECT_EQ(one, two);
}
}
@@ -185,8 +184,8 @@ TEST(FileSpecTest, EqualDotsPosixRoot) {
};
for (const auto &test : tests) {
- FileSpec one(test.first, false, FileSpec::Style::posix);
- FileSpec two(test.second, false, FileSpec::Style::posix);
+ FileSpec one(test.first, FileSpec::Style::posix);
+ FileSpec two(test.second, FileSpec::Style::posix);
EXPECT_EQ(one, two);
}
}
@@ -222,7 +221,7 @@ TEST(FileSpecTest, GetNormalizedPath) {
for (auto test : posix_tests) {
SCOPED_TRACE(llvm::Twine("test.first = ") + test.first);
EXPECT_EQ(test.second,
- FileSpec(test.first, false, FileSpec::Style::posix).GetPath());
+ FileSpec(test.first, FileSpec::Style::posix).GetPath());
}
std::pair<const char *, const char *> windows_tests[] = {
@@ -254,7 +253,7 @@ TEST(FileSpecTest, GetNormalizedPath) {
};
for (auto test : windows_tests) {
EXPECT_EQ(test.second,
- FileSpec(test.first, false, FileSpec::Style::windows).GetPath())
+ FileSpec(test.first, FileSpec::Style::windows).GetPath())
<< "Original path: " << test.first;
}
}
@@ -267,17 +266,17 @@ TEST(FileSpecTest, FormatFileSpec) {
EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str());
EXPECT_EQ("(empty)", llvm::formatv("{0:F}", F).str());
- F = FileSpec("C:\\foo\\bar.txt", false, win);
+ F = FileSpec("C:\\foo\\bar.txt", win);
EXPECT_EQ("C:\\foo\\bar.txt", llvm::formatv("{0}", F).str());
EXPECT_EQ("C:\\foo\\", llvm::formatv("{0:D}", F).str());
EXPECT_EQ("bar.txt", llvm::formatv("{0:F}", F).str());
- F = FileSpec("foo\\bar.txt", false, win);
+ F = FileSpec("foo\\bar.txt", win);
EXPECT_EQ("foo\\bar.txt", llvm::formatv("{0}", F).str());
EXPECT_EQ("foo\\", llvm::formatv("{0:D}", F).str());
EXPECT_EQ("bar.txt", llvm::formatv("{0:F}", F).str());
- F = FileSpec("foo", false, win);
+ F = FileSpec("foo", win);
EXPECT_EQ("foo", llvm::formatv("{0}", F).str());
EXPECT_EQ("foo", llvm::formatv("{0:F}", F).str());
EXPECT_EQ("(empty)", llvm::formatv("{0:D}", F).str());
@@ -306,7 +305,7 @@ TEST(FileSpecTest, IsRelative) {
"/foo/../.",
};
for (const auto &path: not_relative) {
- FileSpec spec(path, false, FileSpec::Style::posix);
+ FileSpec spec(path, FileSpec::Style::posix);
EXPECT_FALSE(spec.IsRelative());
}
llvm::StringRef is_relative[] = {
@@ -324,13 +323,13 @@ TEST(FileSpecTest, IsRelative) {
"./foo/bar.c"
};
for (const auto &path: is_relative) {
- FileSpec spec(path, false, FileSpec::Style::posix);
+ FileSpec spec(path, FileSpec::Style::posix);
EXPECT_TRUE(spec.IsRelative());
}
}
TEST(FileSpecTest, RemoveLastPathComponent) {
- FileSpec fs_posix("/foo/bar/baz", false, FileSpec::Style::posix);
+ FileSpec fs_posix("/foo/bar/baz", FileSpec::Style::posix);
EXPECT_STREQ("/foo/bar/baz", fs_posix.GetCString());
EXPECT_TRUE(fs_posix.RemoveLastPathComponent());
EXPECT_STREQ("/foo/bar", fs_posix.GetCString());
@@ -341,7 +340,7 @@ TEST(FileSpecTest, RemoveLastPathComponent) {
EXPECT_FALSE(fs_posix.RemoveLastPathComponent());
EXPECT_STREQ("/", fs_posix.GetCString());
- FileSpec fs_posix_relative("./foo/bar/baz", false, FileSpec::Style::posix);
+ FileSpec fs_posix_relative("./foo/bar/baz", FileSpec::Style::posix);
EXPECT_STREQ("foo/bar/baz", fs_posix_relative.GetCString());
EXPECT_TRUE(fs_posix_relative.RemoveLastPathComponent());
EXPECT_STREQ("foo/bar", fs_posix_relative.GetCString());
@@ -350,14 +349,14 @@ TEST(FileSpecTest, RemoveLastPathComponent) {
EXPECT_FALSE(fs_posix_relative.RemoveLastPathComponent());
EXPECT_STREQ("foo", fs_posix_relative.GetCString());
- FileSpec fs_posix_relative2("./", false, FileSpec::Style::posix);
+ FileSpec fs_posix_relative2("./", FileSpec::Style::posix);
EXPECT_STREQ(".", fs_posix_relative2.GetCString());
EXPECT_FALSE(fs_posix_relative2.RemoveLastPathComponent());
EXPECT_STREQ(".", fs_posix_relative2.GetCString());
EXPECT_FALSE(fs_posix_relative.RemoveLastPathComponent());
EXPECT_STREQ(".", fs_posix_relative2.GetCString());
- FileSpec fs_windows("C:\\foo\\bar\\baz", false, FileSpec::Style::windows);
+ FileSpec fs_windows("C:\\foo\\bar\\baz", FileSpec::Style::windows);
EXPECT_STREQ("C:\\foo\\bar\\baz", fs_windows.GetCString());
EXPECT_TRUE(fs_windows.RemoveLastPathComponent());
EXPECT_STREQ("C:\\foo\\bar", fs_windows.GetCString());
diff --git a/unittests/Core/ListenerTest.cpp b/unittests/Utility/ListenerTest.cpp
index 7c5a52e3dc4b..fa49c258f5d1 100644
--- a/unittests/Core/ListenerTest.cpp
+++ b/unittests/Utility/ListenerTest.cpp
@@ -9,8 +9,8 @@
#include "gtest/gtest.h"
-#include "lldb/Core/Broadcaster.h"
-#include "lldb/Core/Listener.h"
+#include "lldb/Utility/Broadcaster.h"
+#include "lldb/Utility/Listener.h"
#include <future>
#include <thread>
@@ -21,7 +21,7 @@ TEST(ListenerTest, GetEventImmediate) {
EventSP event_sp;
Broadcaster broadcaster(nullptr, "test-broadcaster");
- // Create a listener, sign it up, make sure it recieves an event.
+ // Create a listener, sign it up, make sure it receives an event.
ListenerSP listener_sp = Listener::MakeListener("test-listener");
const uint32_t event_mask = 1;
ASSERT_EQ(event_mask,
@@ -58,7 +58,7 @@ TEST(ListenerTest, GetEventWait) {
EventSP event_sp;
Broadcaster broadcaster(nullptr, "test-broadcaster");
- // Create a listener, sign it up, make sure it recieves an event.
+ // Create a listener, sign it up, make sure it receives an event.
ListenerSP listener_sp = Listener::MakeListener("test-listener");
const uint32_t event_mask = 1;
ASSERT_EQ(event_mask,
diff --git a/unittests/Host/PredicateTest.cpp b/unittests/Utility/PredicateTest.cpp
index 88ee6b6fc106..327dd80b23ee 100644
--- a/unittests/Host/PredicateTest.cpp
+++ b/unittests/Utility/PredicateTest.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/Host/Predicate.h"
+#include "lldb/Utility/Predicate.h"
#include "gtest/gtest.h"
#include <thread>
diff --git a/unittests/Utility/RegisterValueTest.cpp b/unittests/Utility/RegisterValueTest.cpp
new file mode 100644
index 000000000000..711bbcb965e6
--- /dev/null
+++ b/unittests/Utility/RegisterValueTest.cpp
@@ -0,0 +1,23 @@
+//===-- RegisterValueTest.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/RegisterValue.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+TEST(RegisterValueTest, GetSet8) {
+ RegisterValue R8(uint8_t(47));
+ EXPECT_EQ(47u, R8.GetAsUInt8());
+ R8 = uint8_t(42);
+ EXPECT_EQ(42u, R8.GetAsUInt8());
+ EXPECT_EQ(42u, R8.GetAsUInt16());
+ EXPECT_EQ(42u, R8.GetAsUInt32());
+ EXPECT_EQ(42u, R8.GetAsUInt64());
+}
diff --git a/unittests/Utility/ReproducerTest.cpp b/unittests/Utility/ReproducerTest.cpp
new file mode 100644
index 000000000000..aadb92b21843
--- /dev/null
+++ b/unittests/Utility/ReproducerTest.cpp
@@ -0,0 +1,134 @@
+//===-- ReproducerTest.cpp --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/Reproducer.h"
+
+using namespace llvm;
+using namespace lldb_private;
+using namespace lldb_private::repro;
+
+class DummyProvider : public repro::Provider<DummyProvider> {
+public:
+ static constexpr const char *NAME = "dummy";
+
+ DummyProvider(const FileSpec &directory) : Provider(directory) {
+ m_info.name = "dummy";
+ m_info.files.push_back("dummy.yaml");
+ }
+
+ static char ID;
+};
+
+class DummyReproducer : public Reproducer {
+public:
+ DummyReproducer() : Reproducer(){};
+
+ using Reproducer::SetCapture;
+ using Reproducer::SetReplay;
+};
+
+char DummyProvider::ID = 0;
+
+TEST(ReproducerTest, SetCapture) {
+ DummyReproducer reproducer;
+
+ // Initially both generator and loader are unset.
+ EXPECT_EQ(nullptr, reproducer.GetGenerator());
+ EXPECT_EQ(nullptr, reproducer.GetLoader());
+
+ // Enable capture and check that means we have a generator.
+ EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
+ Succeeded());
+ EXPECT_NE(nullptr, reproducer.GetGenerator());
+ EXPECT_EQ(FileSpec("/bogus/path"), reproducer.GetGenerator()->GetRoot());
+ EXPECT_EQ(FileSpec("/bogus/path"), reproducer.GetReproducerPath());
+
+ // Ensure that we cannot enable replay.
+ EXPECT_THAT_ERROR(reproducer.SetReplay(FileSpec("/bogus/path")), Failed());
+ EXPECT_EQ(nullptr, reproducer.GetLoader());
+
+ // Ensure we can disable the generator again.
+ EXPECT_THAT_ERROR(reproducer.SetCapture(llvm::None), Succeeded());
+ EXPECT_EQ(nullptr, reproducer.GetGenerator());
+ EXPECT_EQ(nullptr, reproducer.GetLoader());
+}
+
+TEST(ReproducerTest, SetReplay) {
+ DummyReproducer reproducer;
+
+ // Initially both generator and loader are unset.
+ EXPECT_EQ(nullptr, reproducer.GetGenerator());
+ EXPECT_EQ(nullptr, reproducer.GetLoader());
+
+ // Expected to fail because we can't load the index.
+ EXPECT_THAT_ERROR(reproducer.SetReplay(FileSpec("/bogus/path")), Failed());
+ // However the loader should still be set, which we check here.
+ EXPECT_NE(nullptr, reproducer.GetLoader());
+
+ // Make sure the bogus path is correctly set.
+ EXPECT_EQ(FileSpec("/bogus/path"), reproducer.GetLoader()->GetRoot());
+ EXPECT_EQ(FileSpec("/bogus/path"), reproducer.GetReproducerPath());
+
+ // Ensure that we cannot enable replay.
+ EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")), Failed());
+ EXPECT_EQ(nullptr, reproducer.GetGenerator());
+}
+
+TEST(GeneratorTest, Create) {
+ DummyReproducer reproducer;
+
+ EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
+ Succeeded());
+ auto &generator = *reproducer.GetGenerator();
+
+ auto *provider = generator.Create<DummyProvider>();
+ EXPECT_NE(nullptr, provider);
+ EXPECT_EQ(FileSpec("/bogus/path"), provider->GetRoot());
+ EXPECT_EQ(std::string("dummy"), provider->GetInfo().name);
+ EXPECT_EQ((size_t)1, provider->GetInfo().files.size());
+ EXPECT_EQ(std::string("dummy.yaml"), provider->GetInfo().files.front());
+}
+
+TEST(GeneratorTest, Get) {
+ DummyReproducer reproducer;
+
+ EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
+ Succeeded());
+ auto &generator = *reproducer.GetGenerator();
+
+ auto *provider = generator.Create<DummyProvider>();
+ EXPECT_NE(nullptr, provider);
+
+ auto *provider_alt = generator.Get<DummyProvider>();
+ EXPECT_EQ(provider, provider_alt);
+}
+
+TEST(GeneratorTest, GetOrCreate) {
+ DummyReproducer reproducer;
+
+ EXPECT_THAT_ERROR(reproducer.SetCapture(FileSpec("/bogus/path")),
+ Succeeded());
+ auto &generator = *reproducer.GetGenerator();
+
+ auto &provider = generator.GetOrCreate<DummyProvider>();
+ EXPECT_EQ(FileSpec("/bogus/path"), provider.GetRoot());
+ EXPECT_EQ(std::string("dummy"), provider.GetInfo().name);
+ EXPECT_EQ((size_t)1, provider.GetInfo().files.size());
+ EXPECT_EQ(std::string("dummy.yaml"), provider.GetInfo().files.front());
+
+ auto &provider_alt = generator.GetOrCreate<DummyProvider>();
+ EXPECT_EQ(&provider, &provider_alt);
+}
diff --git a/unittests/Core/ScalarTest.cpp b/unittests/Utility/ScalarTest.cpp
index 9c241c26e66c..e66876bc8267 100644
--- a/unittests/Core/ScalarTest.cpp
+++ b/unittests/Utility/ScalarTest.cpp
@@ -9,9 +9,9 @@
#include "gtest/gtest.h"
-#include "lldb/Core/Scalar.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "llvm/Testing/Support/Error.h"
@@ -19,6 +19,52 @@
using namespace lldb_private;
using namespace llvm;
+template <typename T>
+bool checkInequality(T c1, T c2) {
+ return (Scalar(c1) != Scalar(c2));
+}
+
+template <typename T>
+bool checkEquality(T c1, T c2) {
+ return (Scalar(c1) == Scalar(c2));
+}
+
+TEST(ScalarTest, Equality) {
+ ASSERT_TRUE(checkInequality<int>(23, 24));
+ ASSERT_TRUE(checkEquality<int>(96, 96));
+ ASSERT_TRUE(checkInequality<float>(4.0f, 4.5f));
+ ASSERT_TRUE(checkEquality<float>(4.0f, 4.0f));
+
+ auto apint1 = APInt(64, 234);
+ auto apint2 = APInt(64, 246);
+ ASSERT_TRUE(checkInequality<APInt>(apint1, apint2));
+ ASSERT_TRUE(checkEquality<APInt>(apint1, apint1));
+
+ Scalar void1;
+ Scalar void2;
+ float f1 = 2.0;
+ ASSERT_TRUE(void1 == void2);
+ ASSERT_FALSE(void1 == Scalar(f1));
+}
+
+TEST(ScalarTest, Comparison) {
+ auto s1 = Scalar(23);
+ auto s2 = Scalar(46);
+ ASSERT_TRUE(s1 < s2);
+ ASSERT_TRUE(s1 <= s2);
+ ASSERT_TRUE(s2 > s1);
+ ASSERT_TRUE(s2 >= s1);
+}
+
+TEST(ScalarTest, ComparisonFloat) {
+ auto s1 = Scalar(23.0f);
+ auto s2 = Scalar(46.0f);
+ ASSERT_TRUE(s1 < s2);
+ ASSERT_TRUE(s1 <= s2);
+ ASSERT_TRUE(s2 > s1);
+ ASSERT_TRUE(s2 >= s1);
+}
+
TEST(ScalarTest, RightShiftOperator) {
int a = 0x00001000;
int b = 0xFFFFFFFF;
diff --git a/unittests/Utility/StateTest.cpp b/unittests/Utility/StateTest.cpp
new file mode 100644
index 000000000000..7a19307bc76e
--- /dev/null
+++ b/unittests/Utility/StateTest.cpp
@@ -0,0 +1,31 @@
+//===-- StateTest.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/State.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "gtest/gtest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+TEST(StateTest, Formatv) {
+ EXPECT_EQ("invalid", llvm::formatv("{0}", eStateInvalid).str());
+ EXPECT_EQ("unloaded", llvm::formatv("{0}", eStateUnloaded).str());
+ EXPECT_EQ("connected", llvm::formatv("{0}", eStateConnected).str());
+ EXPECT_EQ("attaching", llvm::formatv("{0}", eStateAttaching).str());
+ EXPECT_EQ("launching", llvm::formatv("{0}", eStateLaunching).str());
+ EXPECT_EQ("stopped", llvm::formatv("{0}", eStateStopped).str());
+ EXPECT_EQ("running", llvm::formatv("{0}", eStateRunning).str());
+ EXPECT_EQ("stepping", llvm::formatv("{0}", eStateStepping).str());
+ EXPECT_EQ("crashed", llvm::formatv("{0}", eStateCrashed).str());
+ EXPECT_EQ("detached", llvm::formatv("{0}", eStateDetached).str());
+ EXPECT_EQ("exited", llvm::formatv("{0}", eStateExited).str());
+ EXPECT_EQ("suspended", llvm::formatv("{0}", eStateSuspended).str());
+
+}
diff --git a/unittests/Utility/StatusTest.cpp b/unittests/Utility/StatusTest.cpp
index b3f5182a5d8f..4e0cfb9f45f7 100644
--- a/unittests/Utility/StatusTest.cpp
+++ b/unittests/Utility/StatusTest.cpp
@@ -10,6 +10,10 @@
#include "lldb/Utility/Status.h"
#include "gtest/gtest.h"
+#ifdef _WIN32
+#include <winerror.h>
+#endif
+
using namespace lldb_private;
using namespace lldb;
@@ -51,3 +55,22 @@ TEST(StatusTest, ErrorConversion) {
EXPECT_TRUE(bool(foo));
EXPECT_EQ("foo", llvm::toString(std::move(foo)));
}
+
+#ifdef _WIN32
+TEST(StatusTest, ErrorWin32) {
+ auto success = Status(NO_ERROR, ErrorType::eErrorTypeWin32);
+ EXPECT_STREQ(NULL, success.AsCString());
+ EXPECT_FALSE(success.ToError());
+ EXPECT_TRUE(success.Success());
+
+ auto s = Status(ERROR_ACCESS_DENIED, ErrorType::eErrorTypeWin32);
+ EXPECT_TRUE(s.Fail());
+ EXPECT_STREQ("Access is denied. ", s.AsCString());
+
+ s.SetError(ERROR_IPSEC_IKE_TIMED_OUT, ErrorType::eErrorTypeWin32);
+ EXPECT_STREQ("Negotiation timed out ", s.AsCString());
+
+ s.SetError(16000, ErrorType::eErrorTypeWin32);
+ EXPECT_STREQ("unknown error", s.AsCString());
+}
+#endif
diff --git a/unittests/Utility/StreamTeeTest.cpp b/unittests/Utility/StreamTeeTest.cpp
index 150a8a5b1206..9fcfbc802587 100644
--- a/unittests/Utility/StreamTeeTest.cpp
+++ b/unittests/Utility/StreamTeeTest.cpp
@@ -90,7 +90,9 @@ namespace {
void Flush() override {
++m_flush_count;
}
- size_t Write(const void *src, size_t src_len) override { return src_len; }
+ size_t WriteImpl(const void *src, size_t src_len) override {
+ return src_len;
+ }
};
}
diff --git a/unittests/Utility/StreamTest.cpp b/unittests/Utility/StreamTest.cpp
index 2e30357bb292..0fdee0969c0e 100644
--- a/unittests/Utility/StreamTest.cpp
+++ b/unittests/Utility/StreamTest.cpp
@@ -44,161 +44,257 @@ TEST_F(StreamTest, ChangingByteOrder) {
TEST_F(StreamTest, PutChar) {
s.PutChar('a');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("a", TakeValue());
s.PutChar('1');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("1", TakeValue());
}
TEST_F(StreamTest, PutCharWhitespace) {
s.PutChar(' ');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(" ", TakeValue());
s.PutChar('\n');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\n", TakeValue());
s.PutChar('\r');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\r", TakeValue());
s.PutChar('\t');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\t", TakeValue());
}
TEST_F(StreamTest, PutCString) {
s.PutCString("");
+ EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue());
s.PutCString("foobar");
+ EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("foobar", TakeValue());
s.PutCString(" ");
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(" ", TakeValue());
}
TEST_F(StreamTest, PutCStringWithStringRef) {
s.PutCString(llvm::StringRef(""));
+ EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue());
s.PutCString(llvm::StringRef("foobar"));
+ EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("foobar", TakeValue());
s.PutCString(llvm::StringRef(" "));
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(" ", TakeValue());
}
TEST_F(StreamTest, QuotedCString) {
s.QuotedCString("foo");
+ EXPECT_EQ(5U, s.GetWrittenBytes());
EXPECT_EQ(R"("foo")", TakeValue());
s.QuotedCString("ba r");
+ EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ(R"("ba r")", TakeValue());
s.QuotedCString(" ");
+ EXPECT_EQ(3U, s.GetWrittenBytes());
EXPECT_EQ(R"(" ")", TakeValue());
}
TEST_F(StreamTest, PutCharNull) {
s.PutChar('\0');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\0", 1), TakeValue());
s.PutChar('a');
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("a", 1), TakeValue());
}
TEST_F(StreamTest, PutCStringAsRawHex8) {
+ s.PutCStringAsRawHex8("");
+ EXPECT_EQ(0U, s.GetWrittenBytes());
+ EXPECT_EQ("", TakeValue());
+
s.PutCStringAsRawHex8("foobar");
+ EXPECT_EQ(12U, s.GetWrittenBytes());
EXPECT_EQ("666f6f626172", TakeValue());
s.PutCStringAsRawHex8(" ");
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("20", TakeValue());
}
TEST_F(StreamTest, PutHex8) {
s.PutHex8((uint8_t)55);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("37", TakeValue());
+
s.PutHex8(std::numeric_limits<uint8_t>::max());
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("ff", TakeValue());
+
s.PutHex8((uint8_t)0);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("00", TakeValue());
}
TEST_F(StreamTest, PutNHex8) {
s.PutNHex8(0, (uint8_t)55);
+ EXPECT_EQ(0U, s.GetWrittenBytes());
EXPECT_EQ("", TakeValue());
+
s.PutNHex8(1, (uint8_t)55);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("37", TakeValue());
+
s.PutNHex8(2, (uint8_t)55);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("3737", TakeValue());
+
s.PutNHex8(1, (uint8_t)56);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("38", TakeValue());
}
TEST_F(StreamTest, PutHex16ByteOrderLittle) {
s.PutHex16(0x1234U, lldb::eByteOrderLittle);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("3412", TakeValue());
+
s.PutHex16(std::numeric_limits<uint16_t>::max(), lldb::eByteOrderLittle);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("ffff", TakeValue());
+
s.PutHex16(0U, lldb::eByteOrderLittle);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("0000", TakeValue());
}
TEST_F(StreamTest, PutHex16ByteOrderBig) {
s.PutHex16(0x1234U, lldb::eByteOrderBig);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("1234", TakeValue());
+
s.PutHex16(std::numeric_limits<uint16_t>::max(), lldb::eByteOrderBig);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("ffff", TakeValue());
+
s.PutHex16(0U, lldb::eByteOrderBig);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("0000", TakeValue());
}
TEST_F(StreamTest, PutHex32ByteOrderLittle) {
s.PutHex32(0x12345678U, lldb::eByteOrderLittle);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("78563412", TakeValue());
+
s.PutHex32(std::numeric_limits<uint32_t>::max(), lldb::eByteOrderLittle);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("ffffffff", TakeValue());
+
s.PutHex32(0U, lldb::eByteOrderLittle);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("00000000", TakeValue());
}
TEST_F(StreamTest, PutHex32ByteOrderBig) {
s.PutHex32(0x12345678U, lldb::eByteOrderBig);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("12345678", TakeValue());
+
s.PutHex32(std::numeric_limits<uint32_t>::max(), lldb::eByteOrderBig);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("ffffffff", TakeValue());
+
s.PutHex32(0U, lldb::eByteOrderBig);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("00000000", TakeValue());
}
TEST_F(StreamTest, PutHex64ByteOrderLittle) {
s.PutHex64(0x1234567890ABCDEFU, lldb::eByteOrderLittle);
+ EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("efcdab9078563412", TakeValue());
+
s.PutHex64(std::numeric_limits<uint64_t>::max(), lldb::eByteOrderLittle);
+ EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("ffffffffffffffff", TakeValue());
+
s.PutHex64(0U, lldb::eByteOrderLittle);
+ EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("0000000000000000", TakeValue());
}
TEST_F(StreamTest, PutHex64ByteOrderBig) {
s.PutHex64(0x1234567890ABCDEFU, lldb::eByteOrderBig);
+ EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("1234567890abcdef", TakeValue());
+
s.PutHex64(std::numeric_limits<uint64_t>::max(), lldb::eByteOrderBig);
+ EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("ffffffffffffffff", TakeValue());
+
s.PutHex64(0U, lldb::eByteOrderBig);
+ EXPECT_EQ(16U, s.GetWrittenBytes());
EXPECT_EQ("0000000000000000", TakeValue());
}
+TEST_F(StreamTest, PutMaxHex64ByteOrderBig) {
+ std::size_t bytes;
+ bytes = s.PutMaxHex64(0x12U, 1, lldb::eByteOrderBig);
+ EXPECT_EQ(2U, bytes);
+ bytes = s.PutMaxHex64(0x1234U, 2, lldb::eByteOrderBig);
+ EXPECT_EQ(4U, bytes);
+ bytes = s.PutMaxHex64(0x12345678U, 4, lldb::eByteOrderBig);
+ EXPECT_EQ(8U, bytes);
+ bytes = s.PutMaxHex64(0x1234567890ABCDEFU, 8, lldb::eByteOrderBig);
+ EXPECT_EQ(16U, bytes);
+ EXPECT_EQ(30U, s.GetWrittenBytes());
+ EXPECT_EQ("121234123456781234567890abcdef", TakeValue());
+}
+
+TEST_F(StreamTest, PutMaxHex64ByteOrderLittle) {
+ std::size_t bytes;
+ bytes = s.PutMaxHex64(0x12U, 1, lldb::eByteOrderLittle);
+ EXPECT_EQ(2U, bytes);
+ bytes = s.PutMaxHex64(0x1234U, 2, lldb::eByteOrderLittle);
+ EXPECT_EQ(4U, bytes);
+ bytes = s.PutMaxHex64(0x12345678U, 4, lldb::eByteOrderLittle);
+ EXPECT_EQ(8U, bytes);
+ bytes = s.PutMaxHex64(0x1234567890ABCDEFU, 8, lldb::eByteOrderLittle);
+ EXPECT_EQ(16U, bytes);
+ EXPECT_EQ(30U, s.GetWrittenBytes());
+ EXPECT_EQ("12341278563412efcdab9078563412", TakeValue());
+}
+
//------------------------------------------------------------------------------
// Shift operator tests.
//------------------------------------------------------------------------------
TEST_F(StreamTest, ShiftOperatorChars) {
s << 'a' << 'b';
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("ab", TakeValue());
}
TEST_F(StreamTest, ShiftOperatorStrings) {
s << "cstring\n";
+ EXPECT_EQ(8U, s.GetWrittenBytes());
s << llvm::StringRef("llvm::StringRef\n");
+ EXPECT_EQ(24U, s.GetWrittenBytes());
EXPECT_EQ("cstring\nllvm::StringRef\n", TakeValue());
}
@@ -207,6 +303,7 @@ TEST_F(StreamTest, ShiftOperatorInts) {
s << std::numeric_limits<int16_t>::max() << " ";
s << std::numeric_limits<int32_t>::max() << " ";
s << std::numeric_limits<int64_t>::max();
+ EXPECT_EQ(40U, s.GetWrittenBytes());
EXPECT_EQ("127 32767 2147483647 9223372036854775807", TakeValue());
}
@@ -215,6 +312,7 @@ TEST_F(StreamTest, ShiftOperatorUInts) {
s << std::numeric_limits<uint16_t>::max() << " ";
s << std::numeric_limits<uint32_t>::max() << " ";
s << std::numeric_limits<uint64_t>::max();
+ EXPECT_EQ(33U, s.GetWrittenBytes());
EXPECT_EQ("ff ffff ffffffff ffffffffffffffff", TakeValue());
}
@@ -230,6 +328,7 @@ TEST_F(StreamTest, ShiftOperatorPtr) {
int *ptr = &i;
s << ptr;
+ EXPECT_NE(0U, s.GetWrittenBytes());
EXPECT_TRUE(!TakeValue().empty());
}
@@ -239,6 +338,7 @@ TEST_F(StreamTest, PutPtr) {
int *ptr = &i;
s.PutPointer(ptr);
+ EXPECT_NE(0U, s.GetWrittenBytes());
EXPECT_TRUE(!TakeValue().empty());
}
@@ -254,6 +354,7 @@ TEST_F(StreamTest, PutBytesAsRawHex8ToBigEndian) {
uint32_t value = 0x12345678;
s.PutBytesAsRawHex8(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderBig);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("78563412", TakeValue());
}
@@ -261,6 +362,7 @@ TEST_F(StreamTest, PutRawBytesToBigEndian) {
uint32_t value = 0x12345678;
s.PutRawBytes(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderBig);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\x78\x56\x34\x12", TakeValue());
}
@@ -268,6 +370,7 @@ TEST_F(StreamTest, PutBytesAsRawHex8ToLittleEndian) {
uint32_t value = 0x12345678;
s.PutBytesAsRawHex8(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderLittle);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("12345678", TakeValue());
}
@@ -275,6 +378,7 @@ TEST_F(StreamTest, PutRawBytesToLittleEndian) {
uint32_t value = 0x12345678;
s.PutRawBytes(static_cast<void*>(&value), sizeof(value),
hostByteOrder, lldb::eByteOrderLittle);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\x12\x34\x56\x78", TakeValue());
}
@@ -308,72 +412,84 @@ TEST_F(StreamTest, PutRawBytesToMixedEndian) {
TEST_F(BinaryStreamTest, PutULEB128OneByte) {
auto bytes = s.PutULEB128(0x74ULL);
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\x74", TakeValue());
EXPECT_EQ(1U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128TwoBytes) {
auto bytes = s.PutULEB128(0x1985ULL);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("\x85\x33", TakeValue());
EXPECT_EQ(2U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128ThreeBytes) {
auto bytes = s.PutULEB128(0x5023ULL);
+ EXPECT_EQ(3U, s.GetWrittenBytes());
EXPECT_EQ("\xA3\xA0\x1", TakeValue());
EXPECT_EQ(3U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128FourBytes) {
auto bytes = s.PutULEB128(0xA48032ULL);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\xB2\x80\x92\x5", TakeValue());
EXPECT_EQ(4U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128FiveBytes) {
auto bytes = s.PutULEB128(0x12345678ULL);
+ EXPECT_EQ(5U, s.GetWrittenBytes());
EXPECT_EQ("\xF8\xAC\xD1\x91\x1", TakeValue());
EXPECT_EQ(5U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128SixBytes) {
auto bytes = s.PutULEB128(0xABFE3FAFDFULL);
+ EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\x15", TakeValue());
EXPECT_EQ(6U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128SevenBytes) {
auto bytes = s.PutULEB128(0xDABFE3FAFDFULL);
+ EXPECT_EQ(7U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\x3", TakeValue());
EXPECT_EQ(7U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128EightBytes) {
auto bytes = s.PutULEB128(0x7CDABFE3FAFDFULL);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x3", TakeValue());
EXPECT_EQ(8U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128NineBytes) {
auto bytes = s.PutULEB128(0x327CDABFE3FAFDFULL);
+ EXPECT_EQ(9U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x93\x3", TakeValue());
EXPECT_EQ(9U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128MaxValue) {
auto bytes = s.PutULEB128(std::numeric_limits<uint64_t>::max());
+ EXPECT_EQ(10U, s.GetWrittenBytes());
EXPECT_EQ("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x1", TakeValue());
EXPECT_EQ(10U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128Zero) {
auto bytes = s.PutULEB128(0x0U);
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\0", 1), TakeValue());
EXPECT_EQ(1U, bytes);
}
TEST_F(BinaryStreamTest, PutULEB128One) {
auto bytes = s.PutULEB128(0x1U);
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ("\x1", TakeValue());
EXPECT_EQ(1U, bytes);
}
@@ -384,72 +500,84 @@ TEST_F(BinaryStreamTest, PutULEB128One) {
TEST_F(BinaryStreamTest, PutSLEB128OneByte) {
auto bytes = s.PutSLEB128(0x74LL);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\xF4\0", 2), TakeValue());
EXPECT_EQ(2U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128TwoBytes) {
auto bytes = s.PutSLEB128(0x1985LL);
+ EXPECT_EQ(2U, s.GetWrittenBytes());
EXPECT_EQ("\x85\x33", TakeValue());
EXPECT_EQ(2U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128ThreeBytes) {
auto bytes = s.PutSLEB128(0x5023LL);
+ EXPECT_EQ(3U, s.GetWrittenBytes());
EXPECT_EQ("\xA3\xA0\x1", TakeValue());
EXPECT_EQ(3U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128FourBytes) {
auto bytes = s.PutSLEB128(0xA48032LL);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("\xB2\x80\x92\x5", TakeValue());
EXPECT_EQ(4U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128FiveBytes) {
auto bytes = s.PutSLEB128(0x12345678LL);
+ EXPECT_EQ(5U, s.GetWrittenBytes());
EXPECT_EQ("\xF8\xAC\xD1\x91\x1", TakeValue());
EXPECT_EQ(5U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128SixBytes) {
auto bytes = s.PutSLEB128(0xABFE3FAFDFLL);
+ EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\x15", TakeValue());
EXPECT_EQ(6U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128SevenBytes) {
auto bytes = s.PutSLEB128(0xDABFE3FAFDFLL);
+ EXPECT_EQ(7U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\x3", TakeValue());
EXPECT_EQ(7U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128EightBytes) {
auto bytes = s.PutSLEB128(0x7CDABFE3FAFDFLL);
+ EXPECT_EQ(8U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x3", TakeValue());
EXPECT_EQ(8U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128NineBytes) {
auto bytes = s.PutSLEB128(0x327CDABFE3FAFDFLL);
+ EXPECT_EQ(9U, s.GetWrittenBytes());
EXPECT_EQ("\xDF\xDF\xFE\xF1\xBF\xB5\xF3\x93\x3", TakeValue());
EXPECT_EQ(9U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128MaxValue) {
auto bytes = s.PutSLEB128(std::numeric_limits<int64_t>::max());
+ EXPECT_EQ(10U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0", 10), TakeValue());
EXPECT_EQ(10U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128Zero) {
auto bytes = s.PutSLEB128(0x0);
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\0", 1), TakeValue());
EXPECT_EQ(1U, bytes);
}
TEST_F(BinaryStreamTest, PutSLEB128One) {
auto bytes = s.PutSLEB128(0x1);
+ EXPECT_EQ(1U, s.GetWrittenBytes());
EXPECT_EQ(std::string("\x1", 1), TakeValue());
EXPECT_EQ(1U, bytes);
}
@@ -463,12 +591,14 @@ TEST_F(BinaryStreamTest, PutSLEB128One) {
TEST_F(StreamTest, PutULEB128) {
auto bytes = s.PutULEB128(0x74ULL);
+ EXPECT_EQ(4U, s.GetWrittenBytes());
EXPECT_EQ("0x74", TakeValue());
EXPECT_EQ(4U, bytes);
}
TEST_F(StreamTest, PutSLEB128) {
auto bytes = s.PutSLEB128(0x1985LL);
+ EXPECT_EQ(6U, s.GetWrittenBytes());
EXPECT_EQ("0x6533", TakeValue());
EXPECT_EQ(6U, bytes);
}
diff --git a/unittests/Utility/StringLexerTest.cpp b/unittests/Utility/StringLexerTest.cpp
new file mode 100644
index 000000000000..8084ddd950ca
--- /dev/null
+++ b/unittests/Utility/StringLexerTest.cpp
@@ -0,0 +1,141 @@
+//===-- StringLexerTest.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/StringLexer.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_utility;
+
+TEST(StringLexerTest, GetUnlexed) {
+ StringLexer l("foo");
+ EXPECT_EQ("foo", l.GetUnlexed());
+ l.Next();
+ EXPECT_EQ("oo", l.GetUnlexed());
+ l.Next();
+ l.Next();
+ EXPECT_EQ("", l.GetUnlexed());
+}
+
+TEST(StringLexerTest, HasAtLeast) {
+ StringLexer l("foo");
+ EXPECT_FALSE(l.HasAtLeast(5));
+ EXPECT_FALSE(l.HasAtLeast(4));
+ EXPECT_TRUE(l.HasAtLeast(3));
+ EXPECT_TRUE(l.HasAtLeast(2));
+ EXPECT_TRUE(l.HasAtLeast(1));
+
+ l.Next();
+ EXPECT_FALSE(l.HasAtLeast(5));
+ EXPECT_FALSE(l.HasAtLeast(4));
+ EXPECT_FALSE(l.HasAtLeast(3));
+ EXPECT_TRUE(l.HasAtLeast(2));
+ EXPECT_TRUE(l.HasAtLeast(1));
+
+ l.Next();
+ l.Next();
+ EXPECT_FALSE(l.HasAtLeast(5));
+ EXPECT_FALSE(l.HasAtLeast(4));
+ EXPECT_FALSE(l.HasAtLeast(3));
+ EXPECT_FALSE(l.HasAtLeast(2));
+ EXPECT_FALSE(l.HasAtLeast(1));
+}
+
+TEST(StringLexerTest, AdvanceIf) {
+ StringLexer l("foobar");
+
+ EXPECT_FALSE(l.AdvanceIf("oo"));
+ // Skip the "fo" part.
+ EXPECT_TRUE(l.AdvanceIf("fo"));
+ EXPECT_FALSE(l.AdvanceIf("obarz"));
+ // Skip the remaining string.
+ EXPECT_TRUE(l.AdvanceIf("obar"));
+
+ EXPECT_FALSE(l.AdvanceIf("obarz"));
+ EXPECT_FALSE(l.AdvanceIf("foo"));
+ EXPECT_FALSE(l.AdvanceIf("o"));
+ EXPECT_FALSE(l.AdvanceIf(" "));
+}
+
+TEST(StringLexerTest, PutBack) {
+ StringLexer l("foo");
+
+ l.Next();
+ l.PutBack(1);
+ EXPECT_EQ("foo", l.GetUnlexed());
+
+ l.Next();
+ l.Next();
+ l.Next();
+ l.PutBack(2);
+ EXPECT_EQ("oo", l.GetUnlexed());
+
+ l.PutBack(1);
+ EXPECT_EQ("foo", l.GetUnlexed());
+}
+
+TEST(StringLexerTest, Peek) {
+ StringLexer l("foo");
+
+ EXPECT_EQ('f', l.Peek());
+ l.Next();
+ EXPECT_EQ('o', l.Peek());
+ l.Next();
+ EXPECT_EQ('o', l.Peek());
+}
+
+TEST(StringLexerTest, Next) {
+ StringLexer l("foo");
+ EXPECT_EQ('f', l.Next());
+ EXPECT_EQ('o', l.Next());
+ EXPECT_EQ('o', l.Next());
+}
+
+TEST(StringLexerTest, NextIf) {
+ StringLexer l("foo");
+
+ EXPECT_FALSE(l.NextIf('\0'));
+ EXPECT_FALSE(l.NextIf(' '));
+ EXPECT_FALSE(l.NextIf('o'));
+
+ EXPECT_TRUE(l.NextIf('f'));
+
+ EXPECT_FALSE(l.NextIf('\0'));
+ EXPECT_FALSE(l.NextIf(' '));
+ EXPECT_FALSE(l.NextIf('f'));
+
+ EXPECT_TRUE(l.NextIf('o'));
+
+ EXPECT_FALSE(l.NextIf('\0'));
+ EXPECT_FALSE(l.NextIf(' '));
+ EXPECT_FALSE(l.NextIf('f'));
+
+ EXPECT_TRUE(l.NextIf('o'));
+}
+
+TEST(StringLexerTest, NextIfList) {
+ StringLexer l("foo");
+
+ EXPECT_FALSE(l.NextIf({'\0', ' ', 'o'}).first);
+
+ auto r = l.NextIf({'f'});
+ EXPECT_TRUE(r.first);
+ EXPECT_EQ('f', r.second);
+
+ EXPECT_FALSE(l.NextIf({'\0', ' ', 'f'}).first);
+
+ r = l.NextIf({'f', 'o'});
+ EXPECT_TRUE(r.first);
+ EXPECT_EQ('o', r.second);
+
+ EXPECT_FALSE(l.NextIf({'\0', ' ', 'f'}).first);
+
+ r = l.NextIf({'*', 'f', 'o', 'o'});
+ EXPECT_TRUE(r.first);
+ EXPECT_EQ('o', r.second);
+}
diff --git a/unittests/Utility/StringListTest.cpp b/unittests/Utility/StringListTest.cpp
new file mode 100644
index 000000000000..fcd2da675f72
--- /dev/null
+++ b/unittests/Utility/StringListTest.cpp
@@ -0,0 +1,512 @@
+//===-- StringListTest.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/StringList.h"
+#include "lldb/Utility/StreamString.h"
+#include "gtest/gtest.h"
+
+using namespace lldb_private;
+
+TEST(StringListTest, DefaultConstructor) {
+ StringList s;
+ EXPECT_EQ(0U, s.GetSize());
+}
+
+TEST(StringListTest, Assignment) {
+ StringList orig;
+ orig.AppendString("foo");
+ orig.AppendString("bar");
+
+ StringList s = orig;
+
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+
+ ASSERT_EQ(2U, orig.GetSize());
+ EXPECT_STREQ("foo", orig.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", orig.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, AppendStringStdString) {
+ StringList s;
+ s.AppendString("foo");
+ ASSERT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s.AppendString("bar");
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, AppendStringCString) {
+ StringList s;
+ s.AppendString("foo", strlen("foo"));
+ ASSERT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s.AppendString("bar", strlen("bar"));
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, AppendStringMove) {
+ StringList s;
+ std::string foo = "foo";
+ std::string bar = "bar";
+
+ s.AppendString(std::move(foo));
+ ASSERT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s.AppendString(std::move(bar));
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, ShiftStdString) {
+ StringList s;
+ std::string foo = "foo";
+ std::string bar = "bar";
+
+ s << foo;
+ ASSERT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s << bar;
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, ShiftCString) {
+ StringList s;
+ s << "foo";
+ ASSERT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s << "bar";
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, ShiftMove) {
+ StringList s;
+ std::string foo = "foo";
+ std::string bar = "bar";
+
+ s << std::move(foo);
+ ASSERT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s << std::move(bar);
+ ASSERT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, AppendListCStringArrayEmpty) {
+ StringList s;
+ s.AppendList(nullptr, 0);
+ EXPECT_EQ(0U, s.GetSize());
+}
+
+TEST(StringListTest, AppendListCStringArray) {
+ StringList s;
+ const char *items[3] = {"foo", "", "bar"};
+ s.AppendList(items, 3);
+
+ EXPECT_EQ(3U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("", s.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(2));
+}
+
+TEST(StringListTest, AppendList) {
+ StringList other;
+ other.AppendString("foo");
+ other.AppendString("");
+ other.AppendString("bar");
+
+ StringList empty;
+
+ StringList s;
+ s.AppendList(other);
+
+ EXPECT_EQ(3U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("", s.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(2));
+
+ EXPECT_EQ(3U, other.GetSize());
+ EXPECT_STREQ("foo", other.GetStringAtIndex(0));
+ EXPECT_STREQ("", other.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", other.GetStringAtIndex(2));
+
+ s.AppendList(empty);
+ s.AppendList(other);
+ EXPECT_EQ(6U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("", s.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(2));
+ EXPECT_STREQ("foo", s.GetStringAtIndex(3));
+ EXPECT_STREQ("", s.GetStringAtIndex(4));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(5));
+
+ EXPECT_EQ(3U, other.GetSize());
+ EXPECT_STREQ("foo", other.GetStringAtIndex(0));
+ EXPECT_STREQ("", other.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", other.GetStringAtIndex(2));
+}
+
+TEST(StringListTest, GetSize) {
+ StringList s;
+ s.AppendString("foo");
+ EXPECT_EQ(1U, s.GetSize());
+
+ s.AppendString("foo");
+ EXPECT_EQ(2U, s.GetSize());
+
+ s.AppendString("foobar");
+ EXPECT_EQ(3U, s.GetSize());
+}
+
+TEST(StringListTest, SetSize) {
+ StringList s;
+ s.SetSize(3);
+ EXPECT_EQ(3U, s.GetSize());
+ EXPECT_STREQ("", s.GetStringAtIndex(0));
+ EXPECT_STREQ("", s.GetStringAtIndex(1));
+ EXPECT_STREQ("", s.GetStringAtIndex(2));
+}
+
+TEST(StringListTest, SplitIntoLines) {
+ StringList s;
+ s.SplitIntoLines("\nfoo\nbar\n\n");
+ EXPECT_EQ(4U, s.GetSize());
+ EXPECT_STREQ("", s.GetStringAtIndex(0));
+ EXPECT_STREQ("foo", s.GetStringAtIndex(1));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(2));
+ EXPECT_STREQ("", s.GetStringAtIndex(3));
+}
+
+TEST(StringListTest, SplitIntoLinesSingleTrailingCR) {
+ StringList s;
+ s.SplitIntoLines("\r");
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("", s.GetStringAtIndex(0));
+}
+
+TEST(StringListTest, SplitIntoLinesEmpty) {
+ StringList s;
+ s.SplitIntoLines("");
+ EXPECT_EQ(0U, s.GetSize());
+}
+
+TEST(StringListTest, LongestCommonPrefixEmpty) {
+ StringList s;
+ std::string prefix = "this should be cleared";
+ s.LongestCommonPrefix(prefix);
+ EXPECT_EQ("", prefix);
+}
+
+TEST(StringListTest, LongestCommonPrefix) {
+ StringList s;
+ s.AppendString("foo");
+ s.AppendString("foobar");
+ s.AppendString("foo");
+ s.AppendString("foozar");
+
+ std::string prefix = "this should be cleared";
+ s.LongestCommonPrefix(prefix);
+ EXPECT_EQ("foo", prefix);
+}
+
+TEST(StringListTest, LongestCommonPrefixSingleElement) {
+ StringList s;
+ s.AppendString("foo");
+
+ std::string prefix = "this should be cleared";
+ s.LongestCommonPrefix(prefix);
+ EXPECT_EQ("foo", prefix);
+}
+
+TEST(StringListTest, LongestCommonPrefixDuplicateElement) {
+ StringList s;
+ s.AppendString("foo");
+ s.AppendString("foo");
+
+ std::string prefix = "this should be cleared";
+ s.LongestCommonPrefix(prefix);
+ EXPECT_EQ("foo", prefix);
+}
+
+TEST(StringListTest, LongestCommonPrefixNoPrefix) {
+ StringList s;
+ s.AppendString("foo");
+ s.AppendString("1foobar");
+ s.AppendString("2foo");
+ s.AppendString("3foozar");
+
+ std::string prefix = "this should be cleared";
+ s.LongestCommonPrefix(prefix);
+ EXPECT_EQ("", prefix);
+}
+
+TEST(StringListTest, Clear) {
+ StringList s;
+ s.Clear();
+ EXPECT_EQ(0U, s.GetSize());
+
+ s.AppendString("foo");
+ s.Clear();
+ EXPECT_EQ(0U, s.GetSize());
+
+ s.AppendString("foo");
+ s.AppendString("foo");
+ s.Clear();
+ EXPECT_EQ(0U, s.GetSize());
+}
+
+TEST(StringListTest, PopBack) {
+ StringList s;
+ s.AppendString("foo");
+ s.AppendString("bar");
+ s.AppendString("boo");
+
+ s.PopBack();
+ EXPECT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+
+ s.PopBack();
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s.PopBack();
+ EXPECT_EQ(0U, s.GetSize());
+}
+
+TEST(StringListTest, RemoveBlankLines) {
+ StringList s;
+
+ // Nothing to remove yet.
+ s.RemoveBlankLines();
+ EXPECT_EQ(0U, s.GetSize());
+
+ // Add some lines.
+ s.AppendString("");
+ s.AppendString("");
+ s.AppendString("\t");
+ s.AppendString("");
+ s.AppendString(" ");
+ s.AppendString("");
+ s.AppendString("");
+ s.AppendString("f");
+ s.AppendString("");
+ s.AppendString("");
+
+ // And remove all the empty ones again.
+ s.RemoveBlankLines();
+
+ EXPECT_EQ(3U, s.GetSize());
+ EXPECT_STREQ("\t", s.GetStringAtIndex(0));
+ EXPECT_STREQ(" ", s.GetStringAtIndex(1));
+ EXPECT_STREQ("f", s.GetStringAtIndex(2));
+}
+
+TEST(StringListTest, InsertStringAtIndexStart) {
+ StringList s;
+
+ s.InsertStringAtIndex(0, "bar");
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("bar", s.GetStringAtIndex(0));
+
+ s.InsertStringAtIndex(0, "foo");
+ EXPECT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, InsertStringAtIndexEnd) {
+ StringList s;
+
+ s.InsertStringAtIndex(0, "foo");
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ s.InsertStringAtIndex(1, "bar");
+ EXPECT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, InsertStringAtIndexOutOfBounds) {
+ StringList s;
+
+ s.InsertStringAtIndex(1, "foo");
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+
+ // FIXME: Inserting at an OOB index will always just append to the list. This
+ // seems not very intuitive.
+ s.InsertStringAtIndex(3, "bar");
+ EXPECT_EQ(2U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+ EXPECT_STREQ("bar", s.GetStringAtIndex(1));
+}
+
+TEST(StringListTest, InsertStringAtIndexStdString) {
+ StringList s;
+
+ std::string foo = "foo";
+ s.InsertStringAtIndex(0, foo);
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+}
+
+TEST(StringListTest, InsertStringAtIndexMove) {
+ StringList s;
+
+ std::string foo = "foo";
+ s.InsertStringAtIndex(0, std::move(foo));
+ EXPECT_EQ(1U, s.GetSize());
+ EXPECT_STREQ("foo", s.GetStringAtIndex(0));
+}
+
+TEST(StringListTest, CopyListEmpty) {
+ StringList s;
+
+ EXPECT_EQ("", s.CopyList());
+ EXPECT_EQ("", s.CopyList("+"));
+}
+
+TEST(StringListTest, CopyListSingle) {
+ StringList s;
+ s.AppendString("ab");
+
+ EXPECT_EQ("ab", s.CopyList());
+ EXPECT_EQ("-ab", s.CopyList("-"));
+}
+
+TEST(StringListTest, CopyList) {
+ StringList s;
+ s.AppendString("ab");
+ s.AppendString("cd");
+
+ EXPECT_EQ("ab\ncd", s.CopyList());
+ EXPECT_EQ("-ab\n-cd", s.CopyList("-"));
+}
+
+TEST(StringListTest, Join) {
+ StringList s;
+ s.AppendString("ab");
+ s.AppendString("cd");
+
+ StreamString ss;
+ s.Join(" ", ss);
+
+ EXPECT_EQ("ab cd", ss.GetString());
+}
+
+TEST(StringListTest, JoinEmpty) {
+ StringList s;
+
+ StreamString ss;
+ s.Join(" ", ss);
+
+ EXPECT_EQ("", ss.GetString());
+}
+
+TEST(StringListTest, JoinSingle) {
+ StringList s;
+ s.AppendString("foo");
+
+ StreamString ss;
+ s.Join(" ", ss);
+
+ EXPECT_EQ("foo", ss.GetString());
+}
+
+TEST(StringListTest, JoinThree) {
+ StringList s;
+ s.AppendString("1");
+ s.AppendString("2");
+ s.AppendString("3");
+
+ StreamString ss;
+ s.Join(" ", ss);
+
+ EXPECT_EQ("1 2 3", ss.GetString());
+}
+
+TEST(StringListTest, JoinNonSpace) {
+ StringList s;
+ s.AppendString("1");
+ s.AppendString("2");
+ s.AppendString("3");
+
+ StreamString ss;
+ s.Join(".", ss);
+
+ EXPECT_EQ("1.2.3", ss.GetString());
+}
+
+TEST(StringListTest, JoinMultiCharSeparator) {
+ StringList s;
+ s.AppendString("1");
+ s.AppendString("2");
+ s.AppendString("3");
+
+ StreamString ss;
+ s.Join("--", ss);
+
+ EXPECT_EQ("1--2--3", ss.GetString());
+}
+
+TEST(StringListTest, GetMaxStringLengthEqualSize) {
+ StringList s;
+ s.AppendString("123");
+ s.AppendString("123");
+ EXPECT_EQ(3U, s.GetMaxStringLength());
+}
+
+TEST(StringListTest, GetMaxStringLengthIncreasingSize) {
+ StringList s;
+ s.AppendString("123");
+ s.AppendString("1234");
+ EXPECT_EQ(4U, s.GetMaxStringLength());
+}
+
+TEST(StringListTest, GetMaxStringLengthDecreasingSize) {
+ StringList s;
+ s.AppendString("1234");
+ s.AppendString("123");
+ EXPECT_EQ(4U, s.GetMaxStringLength());
+}
+
+TEST(StringListTest, GetMaxStringLengthMixed) {
+ StringList s;
+ s.AppendString("123");
+ s.AppendString("1");
+ s.AppendString("123");
+ s.AppendString("1234");
+ s.AppendString("123");
+ s.AppendString("1");
+ EXPECT_EQ(4U, s.GetMaxStringLength());
+}
+
+TEST(StringListTest, GetMaxStringLengthEmpty) {
+ StringList s;
+ EXPECT_EQ(0U, s.GetMaxStringLength());
+}
diff --git a/unittests/Utility/StructuredDataTest.cpp b/unittests/Utility/StructuredDataTest.cpp
index 15a2ca6bf70a..878b2022c256 100644
--- a/unittests/Utility/StructuredDataTest.cpp
+++ b/unittests/Utility/StructuredDataTest.cpp
@@ -35,11 +35,11 @@ TEST(StructuredDataTest, StringDump) {
TEST(StructuredDataTest, ParseJSONFromFile) {
Status status;
auto object_sp = StructuredData::ParseJSONFromFile(
- FileSpec("non-existing-file.json", false), status);
+ FileSpec("non-existing-file.json"), status);
EXPECT_EQ(nullptr, object_sp);
std::string input = GetInputFilePath("StructuredData-basic.json");
- object_sp = StructuredData::ParseJSONFromFile(FileSpec(input, false), status);
+ object_sp = StructuredData::ParseJSONFromFile(FileSpec(input), status);
ASSERT_NE(nullptr, object_sp);
StreamString S;
diff --git a/unittests/tools/CMakeLists.txt b/unittests/tools/CMakeLists.txt
index e4fc3e62c087..d180ebe8987d 100644
--- a/unittests/tools/CMakeLists.txt
+++ b/unittests/tools/CMakeLists.txt
@@ -1,5 +1,5 @@
if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|NetBSD")
- if (CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_DEBUGSERVER)
+ if ((CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_TEST_DEBUGSERVER) OR (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin" AND SKIP_LLDB_SERVER_BUILD))
# These tests are meant to test lldb-server/debugserver in isolation, and
# don't provide any value if run against a server copied from somewhere.
else()
diff --git a/unittests/tools/lldb-server/CMakeLists.txt b/unittests/tools/lldb-server/CMakeLists.txt
index dcbd9bed529f..60616c93153f 100644
--- a/unittests/tools/lldb-server/CMakeLists.txt
+++ b/unittests/tools/lldb-server/CMakeLists.txt
@@ -12,7 +12,7 @@ endfunction()
add_lldb_test_executable(thread_inferior inferior/thread_inferior.cpp)
add_lldb_test_executable(environment_check inferior/environment_check.cpp)
-if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+if(DEBUGSERVER_PATH)
add_definitions(-DLLDB_SERVER="${DEBUGSERVER_PATH}" -DLLDB_SERVER_IS_DEBUGSERVER=1)
else()
add_definitions(-DLLDB_SERVER="$<TARGET_FILE:lldb-server>" -DLLDB_SERVER_IS_DEBUGSERVER=0)
diff --git a/unittests/tools/lldb-server/tests/MessageObjects.h b/unittests/tools/lldb-server/tests/MessageObjects.h
index ac090c6d7f32..e8d5ba94580e 100644
--- a/unittests/tools/lldb-server/tests/MessageObjects.h
+++ b/unittests/tools/lldb-server/tests/MessageObjects.h
@@ -10,8 +10,8 @@
#ifndef LLDB_SERVER_TESTS_MESSAGEOBJECTS_H
#define LLDB_SERVER_TESTS_MESSAGEOBJECTS_H
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/Host.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-types.h"
#include "llvm/ADT/DenseMap.h"
diff --git a/unittests/tools/lldb-server/tests/TestBase.h b/unittests/tools/lldb-server/tests/TestBase.h
index 8956490e945c..7ca1c1a975a8 100644
--- a/unittests/tools/lldb-server/tests/TestBase.h
+++ b/unittests/tools/lldb-server/tests/TestBase.h
@@ -11,6 +11,7 @@
#define LLDB_SERVER_TESTS_TESTBASE_H
#include "TestClient.h"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "llvm/Support/Path.h"
#include "llvm/Testing/Support/Error.h"
@@ -20,7 +21,10 @@ namespace llgs_tests {
class TestBase: public ::testing::Test {
public:
- static void SetUpTestCase() { lldb_private::HostInfo::Initialize(); }
+ static void SetUpTestCase() {
+ lldb_private::FileSystem::Initialize();
+ lldb_private::HostInfo::Initialize();
+ }
static std::string getInferiorPath(llvm::StringRef Name) {
llvm::SmallString<64> Path(LLDB_TEST_INFERIOR_PATH);
diff --git a/utils/sync-source/README.txt b/utils/sync-source/README.txt
index 9e019b64d9ad..5d1dc641ed12 100644
--- a/utils/sync-source/README.txt
+++ b/utils/sync-source/README.txt
@@ -97,7 +97,7 @@ syncsource.py configuration in ~/.syncsourcerc:
# option.
#
# Below, I have transfer of the lldb dir skip everything
- # rooted at "/llvm" below the the lldb dir. This is
+ # rooted at "/llvm" below the lldb dir. This is
# because we want the source OS X lldb to move to
# a destination of {some-dest-root}/llvm/tools/lldb, and
# not have the OS-X-inverted llvm copy over with the lldb
diff --git a/www/build.html b/www/build.html
index fd35b5116ba6..381e17c4af13 100755
--- a/www/build.html
+++ b/www/build.html
@@ -143,7 +143,7 @@
<div class="post" id="BuildingLldbOnMacOSX">
<h1 class="postheader">Building LLDB on Mac OS X</h1>
<div class="postcontent">
- <p>Building on Mac OS X is as easy as downloading the code and building the Xcode project or workspace:</p>
+ <p> There are two ways to build LLDB on Mac OS X: Using Xcode and using CMake
</div>
<div class="postcontent">
<h2>Preliminaries</h2>
@@ -151,13 +151,34 @@
<li>XCode 4.3 or newer requires the "Command Line Tools" component (XCode->Preferences->Downloads->Components).</li>
<li>Mac OS X Lion or newer requires installing <a href="http://swig.org">Swig</a>.</li>
</ul>
- <h2>Building LLDB</h2>
+ <h2>Building LLDB with Xcode</h2>
+ <p>Building on Mac OS X with Xcode is as easy as downloading the code and building the Xcode project or workspace:</p>
<ul>
<li><a href="download.html">Download</a> the lldb sources.</li>
<li>Follow the code signing instructions in <b>lldb/docs/code-signing.txt</b></li>
<li>In Xcode 3.x: <b>lldb/lldb.xcodeproj</b>, select the <b>lldb-tool</b> target, and build.</li>
<li>In Xcode 4.x: <b>lldb/lldb.xcworkspace</b>, select the <b>lldb-tool</b> scheme, and build.</li>
</ul>
+ <h2>Building LLDB with CMake</h2>
+ <p> First download the LLVM, Clang, libc++ and LLDB sources. Refer to <a href="source.html">this page</a> for precise instructions on this step.</p>
+ <p> Refer to the code signing instructions in <b>lldb/docs/code-signing.txt</b> for info on codesigning debugserver during the build.</p>
+ <p> Using CMake is documented on the <a href="http://llvm.org/docs/CMake.html">Building LLVM with CMake</a> page.
+ Ninja is the recommended generator to use when building LLDB with CMake.</p>
+ <code>
+ &gt; cmake $PATH_TO_LLVM -G Ninja
+ <br />&gt; ninja lldb
+ </code>
+ <p>
+ As noted in the "Building LLVM with CMake" page mentioned above, you can pass
+ variables to cmake to change build behavior. If LLDB is built as a part of LLVM,
+ then you can pass LLVM-specific CMake variables to cmake when building LLDB.
+ </p>
+ <p>Here are some commonly used LLDB-specific CMake variables:</p>
+ <ul>
+ <li><code><b>LLDB_EXPORT_ALL_SYMBOLS</b>:BOOL </code>: Exports all symbols. Useful in conjunction with CMAKE_BUILD_TYPE=Debug.</li>
+ <li><code><b>LLDB_BUILD_FRAMEWORK</b>:BOOL </code>: Builds LLDB.framework as Xcode would</li>
+ <li><code><b>LLDB_CODESIGN_IDENTITY</b>:STRING </code>: Determines the codesign identity to use. An empty string means skip building debugserver to avoid codesigning.</li>
+ </ul>
</div>
<div class="postfooter"></div>
</div>
diff --git a/www/download.html b/www/download.html
index 8624f970f6d8..201fe12208c6 100755
--- a/www/download.html
+++ b/www/download.html
@@ -36,16 +36,19 @@
<div class="post">
<h1 class ="postheader">LLDB releases</h1>
<div class="postcontent">
- <p>Debian packages are available for LLDB 3.2 and later.</p>
+ <p>Debian packages are available for LLDB 3.5 and later.</p>
<ul>
- <li><a href="http://packages.debian.org/experimental/lldb-3.4">LLDB 3.4 - incremental release</a> (experimental)</li>
- <ul>
- <li><a href="http://packages.debian.org/experimental/amd64/lldb-3.4/download">amd64</a> (x86-64)</li>
- <li><a href="http://packages.debian.org/experimental/s390/lldb-3.4/download">System/390</a> (i386)</li>
- </ul>
- <li><a href="http://packages.debian.org/unstable/lldb-3.3">LLDB 3.3</a> (unstable)</li>
- <li><a href="http://packages.debian.org/unstable/lldb-3.2">LLDB 3.2</a> (unstable)</li>
+ <li><a href="https://packages.debian.org/jessie/lldb">jessie - LLDB 3.5</a></li>
+ <li><a href="https://packages.debian.org/stretch/lldb">stretch - LLDB 3.8</a></li>
+ <li><a href="https://packages.debian.org/buster/lldb">buster - LLDB 6.0</a></li>
+ <li><a href="https://packages.debian.org/sid/lldb">sid - LLDB 6.0</a></li>
</ul>
+ <p>ubuntu packages are available for LLDB 3.8 and later.</p>
+ <ul>
+ <li><a href="https://packages.ubuntu.com/xenial/lldb">ubuntu 16.04LTS - LLDB 3.8</a></li>
+ <li><a href="https://packages.ubuntu.com/bionic/lldb">ubuntu 18.04LTS - LLDB 6.0</a></li>
+ </ul>
+ <p>Arch Linux packages the latest <a href="https://www.archlinux.org/packages/extra/x86_64/lldb/">LLDB 6.0</a></p>
</div>
<div class="postfooter"></div>
</div>
diff --git a/www/python-reference.html b/www/python-reference.html
index d6aa80f87a1b..bde728f9a4c9 100755
--- a/www/python-reference.html
+++ b/www/python-reference.html
@@ -316,6 +316,195 @@ Enter your Python command(s). Type 'DONE' to end.
</div>
</div>
+ </div>
+ <div class="post">
+ <h1 class ="postheader">Using the Python API's to create custom breakpoints</h1>
+ <div class="postcontent">
+
+ <p>Another use of the Python API's in lldb is to create a custom breakpoint resolver. This facility
+ was added in r342259.
+ </p>
+ <p>
+ It allows you to provide the algorithm which will be used in the breakpoint's
+ search of the space of the code in a given Target
+ to determine where to set the breakpoint locations - the actual places where the breakpoint will trigger.
+ To understand how this works you need to know a little about how lldb handles breakpoints.
+ </p>
+ <p>
+ In lldb, a breakpoint is composed of three parts: the Searcher, the Resolver, and the Stop Options. The Searcher and
+ Resolver cooperate to determine how breakpoint locations are set and differ between each breakpoint type.
+ Stop options determine what happens when a location triggers and includes the commands, conditions, ignore counts, etc.
+ Stop options are common between all breakpoint types, so for our purposes only the Searcher and Resolver are relevant.
+ </p>
+ <p>
+ The Searcher's job is to traverse in a structured way the code in the current target. It
+ proceeds from the Target, to search all the Modules in the Target, in each Module it can recurse
+ into the Compile Units in that module, and within each Compile Unit it can recurse over the Functions
+ it contains.
+ </p>
+ <p>
+ The Searcher can be provided with a SearchFilter that it will use to restrict this search. For instance, if the
+ SearchFilter specifies a list of Modules, the Searcher will not recurse into Modules that aren't on the list.
+ When you pass the <b>-s modulename</b> flag to <b>break set</b> you are creating a Module-based search filter.
+ When you pass <b>-f filename.c</b> to <b>break set -n</b> you are creating a file based search filter. If neither
+ of these is specified, the breakpoint will have a no-op search filter, so all parts of the program are searched
+ and all locations accepted.
+ </p>
+ <p>
+ The Resolver has two functions. The most important one is the callback it provides. This will get called at the appropriate time
+ in the course of the search. The callback is where the job of adding locations to the breakpoint gets done.
+ </p>
+ <p>
+ The other function is specifying to the Searcher at what depth in the above described recursion it wants to be
+ called. Setting a search depth also provides a stop for the recursion. For instance, if you request a Module depth
+ search, then the callback will be called for each Module as it gets added to the Target, but the searcher will not recurse into the
+ Compile Units in the module.
+ </p>
+ <p>
+ One other slight sublety is that the depth at which you get called back is not necessarily the depth at which the
+ the SearchFilter is specified. For instance, if you are doing symbol searches, it is convenient to use the Module
+ depth for the search, since symbols are stored in the module.
+ But the SearchFilter might specify some subset of CompileUnits, so not all the symbols you might find in each module
+ will pass the search. You don't need to
+ handle this situation yourself, since <b>SBBreakpoint::AddLocation</b> will only add locations that pass the Search Filter.
+ This API returns an SBError to inform you whether your location was added.
+ </p>
+ <p>
+ When the breakpoint is originally created, its Searcher will process all the currently loaded modules.
+ The Searcher will also visit any new modules as they are added to the target. This happens, for instance, when
+ a new shared library gets added to the target in the course of running, or on rerunning if any of the currently
+ loaded modules have been changed. Note, in the latter case, all the locations set in the old module will get
+ deleted and you will be asked to recreate them in the new version of the module when your callback gets called
+ with that module. For this reason, you shouldn't
+ try to manage the locations you add to the breakpoint yourself. Note that the Breakpoint takes care of
+ deduplicating equal addresses in AddLocation, so you shouldn't need to worry about that anyway.
+ </p>
+ <p>
+ At present, when adding a scripted Breakpoint type, you can only provide a custom Resolver, not a custom SearchFilter.
+ </p>
+ <p>
+ The custom Resolver is provided as a Python class with the following methods:
+ </p>
+</tt></pre></code>
+ <p><table class="stats" width="620" cellspacing="0">
+ <tr>
+ <td class="hed" width="10%">Name</td>
+ <td class="hed" width="10%">Arguments</td>
+ <td class="hed" width="80%">Description</td>
+ </tr>
+
+
+ <tr>
+ <td class="content">
+ <b>__init__</b>
+ </td>
+ <td class="content">
+ <b>bkpt: lldb.SBBreakpoint</b>
+ <b>extra_args: lldb.SBStructuredData</b>
+ </td>
+ <td class="content">
+ <p>
+ This is the constructor for the new Resolver.
+ </p>
+ <p>
+ <b>bkpt</b> is the breakpoint owning this Resolver.
+ </p>
+ <p>
+ <b>extra_args</b> is an SBStructuredData object that the user can pass in when creating instances of this
+ breakpoint. It is not required, but is quite handy. For instance if you were implementing a breakpoint on some
+ symbol name, you could write a generic symbol name based Resolver, and then allow the user to pass
+ in the particular symbol in the extra_args
+ </td>
+ </tr>
+
+ <tr>
+ <td class="content">
+ <b>__callback__</b>
+ </td>
+ <td class="content">
+ <b>sym_ctx: lldb.SBSymbolContext</b>
+ </td>
+ <td class="content">
+ This is the Resolver callback.
+ The <b>sym_ctx</b> argument will be filled with the current stage
+ of the search.
+ </p>
+ <p>
+ For instance, if you asked for a search depth of lldb.eSearchDepthCompUnit, then the
+ target, module and compile_unit fields of the sym_ctx will be filled. The callback should look just in the
+ context passed in <b>sym_ctx</b> for new locations. If the callback finds an address of interest, it
+ can add it to the breakpoint with the <b>SBBreakpoint::AddLocation</b> method, using the breakpoint passed
+ in to the <b>__init__</b> method.
+ </td>
+ </tr>
+ <tr>
+ <td class="content">
+ <b>__get_depth__</b>
+ </td>
+ <td class="content">
+ <b>None</b>
+ </td>
+ <td class="content">
+ Specify the depth at which you wish your callback to get called. The currently supported options are:
+ <dl>
+ <dt>lldb.eSearchDepthModule</dt>
+ <dt>lldb.eSearchDepthCompUnit</dt>
+ <dt>lldb.eSearchDepthFunction</dt>
+ </dl>
+ For instance, if you are looking
+ up symbols, which are stored at the Module level, you will want to get called back module by module.
+ So you would want to return <b>lldb.eSearchDepthModule</b>. This method is optional. If not provided the search
+ will be done at Module depth.
+ </td>
+ </tr>
+ <tr>
+ <td class="content">
+ <b>get_short_help</b>
+ </td>
+ <td class="content">
+ <b>None</b>
+ </td>
+ <td class="content">
+ This is an optional method. If provided, the returned string will be printed at the beginning of
+ the description for this breakpoint.
+ </td>
+ </tr>
+ </table>
+
+ <p>To define a new breakpoint command defined by this class from the lldb command line, use the command:</p>
+
+<code><pre><tt>(lldb) <strong>breakpoint set -P MyModule.MyResolverClass</strong>
+</tt></pre></code>
+ <p>You can also populate the extra_args SBStructuredData with a dictionary of key/value pairs with:</p>
+
+<code><pre><tt>(lldb) <strong>breakpoint set -P MyModule.MyResolverClass -k key_1 -v value_1 -k key_2 -v value_2</strong>
+</tt></pre></code>
+ <p>Although you can't write a scripted SearchFilter, both the command line and the SB API's for adding a
+ scripted resolver allow you to specify a SearchFilter restricted to certain modules or certain compile
+ units. When using the command line to create the resolver, you can specify a Module specific SearchFilter
+ by passing the <b>-s ModuleName</b> option - which can be specified multiple times.
+ You can also specify a SearchFilter restricted to certain
+ compile units by passing in the <b>-f CompUnitName</b> option. This can also be specified more than
+ once. And you can mix the two to specify &quotthis comp unit in this module&quot. So, for instance,
+ </p>
+
+<code><pre><tt>(lldb) <strong>breakpoint set -P MyModule.MyResolverClass -s a.out</strong>
+</tt></pre></code>
+ <p>
+ will use your resolver, but will only recurse into or accept new locations in the module a.out.
+ </p>
+
+ <p>Another option for creating scripted breakpoints is to use the <b>SBTarget.CreateBreakpointFromScript</b> API.
+ This one has the advantage that you can pass in an arbitrary SBStructuredData object, so you can
+ create more complex parametrizations.
+ SBStructuredData has a handy SetFromJSON method which you can use for this purpose.
+ Your __init__ function gets passed this SBStructuredData object.
+ This API also allows you to directly provide the list of Modules and the list of CompileUnits that will
+ make up the SearchFilter. If you pass in empty lists, the breakpoint will use the default &quotsearch everywhere,accept
+ everything&quot filter.
+ </p>
+
+ </div>
<div class="post">
<h1 class ="postheader">Using the Python API's to create custom stepping logic</h1>
<div class="postcontent">
@@ -654,13 +843,14 @@ $2 = 0x000000010010aba0 Let's Be Friendsfoobar</tt></pre></code>
<b>LLDB.framework</b> to create your own stand-alone python programs, you will
need to tell python where to look in order to find this module. This
is done by setting the <b>PYTHONPATH</b> environment variable, adding
- a path to the directory that contains the <b>lldb.py</b> python module. On
- Mac OS X, this is contained inside the LLDB.framework, so you would do:
+ a path to the directory that contains the <b>lldb.py</b> python module. The
+ lldb driver program has an option to report the path to the lldb module.
+ You can use that to point to correct lldb.py:
<p>For csh and tcsh:</p>
- <p><code>% <b>setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python</b></code></p>
+ <p><code>% <b>setenv PYTHONPATH `lldb -P`</b></p>
<p>For sh and bash:
- <p><code>% <b>export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python</b></code></p>
+ <p><code>% <b>export PYTHONPATH=`lldb -P`</b></p>
<p> Alternately, you can append the LLDB Python directory to the <b>sys.path</b> list directly in
your Python code before importing the lldb module.</p>
@@ -738,11 +928,64 @@ if target:
<font color=green># We do have a symbol, print some info for the symbol</font>
print symbol
</tt></pre></code>
- </div>
- <div class="postfooter"></div>
+ </div>
+ <div class="postfooter"></div>
+ </div>
+
+ <div class="post">
+ <h1 class ="postheader">Writing LLDB frame recognizers in Python</h1>
+ <div class="postcontent">
+
+ <p>Frame recognizers allow for retrieving information about special frames based on
+ ABI, arguments or other special properties of that frame, even without source
+ code or debug info. Currently, one use case is to extract function arguments
+ that would otherwise be unaccesible, or augment existing arguments.</p>
+
+ <p>Adding a custom frame recognizer is done by implementing a Python class
+ and using the '<b>frame recognizer add</b>' command. The Python class should have a
+ '<b>get_recognized_arguments</b>' method and it will receive an argument of type
+ <b>lldb.SBFrame</b> representing the current frame that we are trying to recognize.
+ The method should return a (possibly empty) list of <b>lldb.SBValue</b> objects that
+ represent the recognized arguments.</p>
+
+ <p>An example of a recognizer that retrieves the file descriptor values from libc
+ functions '<b>read</b>', '<b>write</b>' and '<b>close</b>' follows:</p>
+
+<code><pre><tt> class LibcFdRecognizer(object):
+ def get_recognized_arguments(self, frame):
+ if frame.name in ["read", "write", "close"]:
+ fd = frame.EvaluateExpression("$arg1").unsigned
+ value = lldb.target.CreateValueFromExpression("fd", "(int)%d" % fd)
+ return [value]
+ return []
+</tt></pre></code>
+
+ <p>The file containing this implementation can be imported via '<b>command script
+ import</b>' and then we can register this recognizer with '<b>frame recognizer add</b>'.
+ It's important to restrict the recognizer to the libc library (which is
+ libsystem_kernel.dylib on macOS) to avoid matching functions with the same name in other modules:</p>
+
+<code><pre><tt>(lldb) <b>command script import .../fd_recognizer.py</b>
+(lldb) <b>frame recognizer add -l fd_recognizer.LibcFdRecognizer -n read -s libsystem_kernel.dylib</b>
+</tt></pre></code>
+
+ <p>When the program is stopped at the beginning of the '<b>read</b>' function in libc, we
+ can view the recognizer arguments in '<b>frame variable</b>':</p>
+
+<code><pre><tt>(lldb) <b>b read</b>
+(lldb) <b>r</b>
+Process 1234 stopped
+* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.3
+ frame #0: 0x00007fff06013ca0 libsystem_kernel.dylib`read
+(lldb) <b>frame variable</b>
+(int) fd = 3
+</tt></pre></code>
- </div>
- </div>
+ </div>
+ <div class="postfooter"></div>
+ </div>
+
+ </div>
</div>
</body>
</html>
diff --git a/www/python_reference/epydoc.css b/www/python_reference/epydoc.css
index 86d417068248..1a0abed4b570 100644
--- a/www/python_reference/epydoc.css
+++ b/www/python_reference/epydoc.css
@@ -176,7 +176,7 @@ table.summary
font-family: monospace; }
/* Variable values
- * - In the 'variable details' sections, each varaible's value is
+ * - In the 'variable details' sections, each variable's value is
* listed in a 'pre.variable' box. The width of this box is
* restricted to 80 chars; if the value's repr is longer than
* this it will be wrapped, using a backslash marked with
diff --git a/www/symbols.html b/www/symbols.html
index af98e7d24dde..e744a3f3b05b 100755
--- a/www/symbols.html
+++ b/www/symbols.html
@@ -262,6 +262,17 @@ A40597AA-5529-3337-8C09-D8A014EB1578.plist
&lt;string&gt;/path/to/foo.dSYM/Contents/Resources/DWARF/foo&lt;/string&gt;
&lt;key&gt;DBGSymbolRichExecutable&lt;/key&gt;
&lt;string&gt;/path/to/unstripped/executable&lt;/string&gt;
+ &lt;key&gt;DBGVersion&lt;/key&gt;
+ &lt;string&gt;3&lt;/string&gt;
+ &lt;key&gt;DBGSourcePathRemapping&lt;/key&gt;
+ &lt;dict&gt;
+ &lt;key&gt;/path/to/build/time/src/location1&lt;/key&gt;
+ &lt;string&gt;/path/to/debug/time/src/location&lt;/string&gt;
+ &lt;key&gt;/path/to/build/time/src/location2&lt;/key&gt;
+ &lt;string&gt;/path/to/debug/time/src/location&lt;/string&gt;
+ &lt;/dict&gt;
+ &lt;key&gt;DBGSymbolRichExecutable&lt;/key&gt;
+ &lt;string&gt;/path/to/unstripped/executable&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</tt></pre></code>
@@ -271,6 +282,22 @@ so making the results of your shell script will be very easy to create by
combining two plists into a single one where you take the UUID and use it a
string key, and the value is the contents of the plist.
+<p>LLDB will read the following entries from the per-UUID plist file in the dSYM
+bundle: <b>DBGSymbolRichExecutable</b>, <b>DBGBuildSourcePath</b> and
+<b>DBGSourcePath</b>, and <b>DBGSourcePathRemapping</b> if <b>DBGVersion</b> is 3
+or higher. <b>DBGBuildSourcePath</b> and <b>DBGSourcePath</b> are for remapping
+a single file path. For instance, the files may be in /BuildDir/SheetApp/SheetApp-37
+when built, but they are in /SourceDir/SheetApp/SheetApp-37 at debug time, those
+two paths could be listed in those keys. If there are multiple source path
+remappings, the <b>DBGSourcePathRemapping</b> dictionary can be used, where an
+arbitrary number of entries may be present. <b>DBGVersion</b> should be 3 or
+<b>DBGSourcePathRemapping</b> will not be read. If both <b>DBGSourcePathRemapping</b>
+AND <b>DBGBuildSourcePath</b>/<b>DBGSourcePath</b> are present in the plist, the
+<b>DBGSourcePathRemapping</b> entries will be used for path remapping first. This
+may allow for more specific remappings in the <b>DBGSourcePathRemapping</b>
+dictionary and a less specific remapping in the
+<b>DBGBuildSourcePath</b>/<b>DBGSourcePath</b> pair as a last resort.
+
</div>
<div class="postfooter"></div>